From e05d202ebf0904cf0a980fde76f4a38bb8dc7c3b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 16 Apr 2024 22:05:12 +0200 Subject: [PATCH 001/127] gh-117755: Remove tests on huge memory allocations (#117938) Remove unreliable tests on huge memory allocations: * Remove test_maxcontext_exact_arith() of test_decimal. Stefan Krah, test author, agreed on removing the test: https://github.com/python/cpython/issues/114331#issuecomment-1925731273 * Remove test_constructor() tests of test_io. Sam Gross suggests remove them: https://github.com/python/cpython/pull/117809#pullrequestreview-2003889558 On Linux, depending how overcommit is configured, especially on Linux s390x, a huge memory allocation (half or more of the full address space) can succeed, but then the process will eat the full system swap and make the system slower and slower until the whole system becomes unusable. Moreover, these tests had to be skipped when Python is built with sanitizers. --- Lib/test/test_decimal.py | 48 +------------------------------------ Lib/test/test_io.py | 51 +--------------------------------------- 2 files changed, 2 insertions(+), 97 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 05dcb25a7e59504..7010c34792e0937 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -34,12 +34,10 @@ import locale from test.support import (is_resource_enabled, requires_IEEE_754, requires_docstrings, - check_sanitizer, check_disallow_instantiation) from test.support import (TestFailed, run_with_locale, cpython_only, - darwin_malloc_err_warning, is_emscripten, - skip_on_s390x) + darwin_malloc_err_warning) from test.support.import_helper import import_fresh_module from test.support import threading_helper from test.support import warnings_helper @@ -5644,50 +5642,6 @@ def __abs__(self): self.assertEqual(Decimal.from_float(cls(101.1)), Decimal.from_float(101.1)) - # Issue 41540: - @unittest.skipIf(sys.platform.startswith("aix"), - "AIX: default ulimit: test is flaky because of extreme over-allocation") - @unittest.skipIf(is_emscripten, "Test is unstable on Emscripten") - @unittest.skipIf(check_sanitizer(address=True, memory=True), - "ASAN/MSAN sanitizer defaults to crashing " - "instead of returning NULL for malloc failure.") - # gh-114331: The test allocates 784 271 641 GiB and mimalloc does not fail - # to allocate it when using mimalloc on s390x. - @skip_on_s390x - def test_maxcontext_exact_arith(self): - - # Make sure that exact operations do not raise MemoryError due - # to huge intermediate values when the context precision is very - # large. - - # The following functions fill the available precision and are - # therefore not suitable for large precisions (by design of the - # specification). - MaxContextSkip = ['logical_invert', 'next_minus', 'next_plus', - 'logical_and', 'logical_or', 'logical_xor', - 'next_toward', 'rotate', 'shift'] - - Decimal = C.Decimal - Context = C.Context - localcontext = C.localcontext - - # Here only some functions that are likely candidates for triggering a - # MemoryError are tested. deccheck.py has an exhaustive test. - maxcontext = Context(prec=C.MAX_PREC, Emin=C.MIN_EMIN, Emax=C.MAX_EMAX) - with localcontext(maxcontext): - self.assertEqual(Decimal(0).exp(), 1) - self.assertEqual(Decimal(1).ln(), 0) - self.assertEqual(Decimal(1).log10(), 0) - self.assertEqual(Decimal(10**2).log10(), 2) - self.assertEqual(Decimal(10**223).log10(), 223) - self.assertEqual(Decimal(10**19).logb(), 19) - self.assertEqual(Decimal(4).sqrt(), 2) - self.assertEqual(Decimal("40E9").sqrt(), Decimal('2.0E+5')) - self.assertEqual(divmod(Decimal(10), 3), (3, 1)) - self.assertEqual(Decimal(10) // 3, 3) - self.assertEqual(Decimal(4) / 2, 2) - self.assertEqual(Decimal(400) ** -1, Decimal('0.0025')) - def test_c_immutable_types(self): SignalDict = type(C.Context().flags) SignalDictMixin = SignalDict.__bases__[0] diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index c3dc0572c58c27e..e5cb08c2cdd04c7 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -40,8 +40,7 @@ from test.support.script_helper import ( assert_python_ok, assert_python_failure, run_python_until_end) from test.support import ( - import_helper, is_apple, os_helper, skip_if_sanitizer, threading_helper, warnings_helper, - skip_on_s390x + import_helper, is_apple, os_helper, threading_helper, warnings_helper, ) from test.support.os_helper import FakePath @@ -1698,22 +1697,6 @@ def test_seek_character_device_file(self): class CBufferedReaderTest(BufferedReaderTest, SizeofTest): tp = io.BufferedReader - @skip_if_sanitizer(memory=True, address=True, thread=True, - reason="sanitizer defaults to crashing " - "instead of returning NULL for malloc failure.") - # gh-117755: The test allocates 9 223 372 036 854 775 807 bytes - # (0x7fffffffffffffff) and mimalloc fails with a division by zero on s390x. - @skip_on_s390x - def test_constructor(self): - BufferedReaderTest.test_constructor(self) - # The allocation can succeed on 32-bit builds, e.g. with more - # than 2 GiB RAM and a 64-bit kernel. - if sys.maxsize > 0x7FFFFFFF: - rawio = self.MockRawIO() - bufio = self.tp(rawio) - self.assertRaises((OverflowError, MemoryError, ValueError), - bufio.__init__, rawio, sys.maxsize) - def test_initialization(self): rawio = self.MockRawIO([b"abc"]) bufio = self.tp(rawio) @@ -2069,22 +2052,6 @@ def test_slow_close_from_thread(self): class CBufferedWriterTest(BufferedWriterTest, SizeofTest): tp = io.BufferedWriter - @skip_if_sanitizer(memory=True, address=True, thread=True, - reason="sanitizer defaults to crashing " - "instead of returning NULL for malloc failure.") - # gh-117755: The test allocates 9 223 372 036 854 775 807 bytes - # (0x7fffffffffffffff) and mimalloc fails with a division by zero on s390x. - @skip_on_s390x - def test_constructor(self): - BufferedWriterTest.test_constructor(self) - # The allocation can succeed on 32-bit builds, e.g. with more - # than 2 GiB RAM and a 64-bit kernel. - if sys.maxsize > 0x7FFFFFFF: - rawio = self.MockRawIO() - bufio = self.tp(rawio) - self.assertRaises((OverflowError, MemoryError, ValueError), - bufio.__init__, rawio, sys.maxsize) - def test_initialization(self): rawio = self.MockRawIO() bufio = self.tp(rawio) @@ -2594,22 +2561,6 @@ def test_interleaved_readline_write(self): class CBufferedRandomTest(BufferedRandomTest, SizeofTest): tp = io.BufferedRandom - @skip_if_sanitizer(memory=True, address=True, thread=True, - reason="sanitizer defaults to crashing " - "instead of returning NULL for malloc failure.") - # gh-117755: The test allocates 9 223 372 036 854 775 807 bytes - # (0x7fffffffffffffff) and mimalloc fails with a division by zero on s390x. - @skip_on_s390x - def test_constructor(self): - BufferedRandomTest.test_constructor(self) - # The allocation can succeed on 32-bit builds, e.g. with more - # than 2 GiB RAM and a 64-bit kernel. - if sys.maxsize > 0x7FFFFFFF: - rawio = self.MockRawIO() - bufio = self.tp(rawio) - self.assertRaises((OverflowError, MemoryError, ValueError), - bufio.__init__, rawio, sys.maxsize) - def test_garbage_collection(self): CBufferedReaderTest.test_garbage_collection(self) CBufferedWriterTest.test_garbage_collection(self) From 3fe03ccea61121b05e933013f76aa02f690014c1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 16 Apr 2024 22:34:12 +0200 Subject: [PATCH 002/127] gh-117755: Fix mimalloc for huge allocation on s390x (#117809) Fix mimalloc allocator for huge memory allocation (around 8,589,934,592 GiB) on s390x. Abort allocation early in mimalloc if the number of slices doesn't fit into uint32_t, to prevent a integer overflow (cast 64-bit size_t to uint32_t). --- .../2024-04-12-12-28-49.gh-issue-117755.6ct8kU.rst | 2 ++ Objects/mimalloc/segment.c | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-12-12-28-49.gh-issue-117755.6ct8kU.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-12-12-28-49.gh-issue-117755.6ct8kU.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-12-12-28-49.gh-issue-117755.6ct8kU.rst new file mode 100644 index 000000000000000..a65ec43e25d1c55 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-12-12-28-49.gh-issue-117755.6ct8kU.rst @@ -0,0 +1,2 @@ +Fix mimalloc allocator for huge memory allocation (around 8,589,934,592 GiB) on +s390x. Patch by Victor Stinner. diff --git a/Objects/mimalloc/segment.c b/Objects/mimalloc/segment.c index 08b156433653a43..0b4d3abc07a93cb 100644 --- a/Objects/mimalloc/segment.c +++ b/Objects/mimalloc/segment.c @@ -814,6 +814,9 @@ static mi_segment_t* mi_segment_os_alloc( size_t required, size_t page_alignment const size_t extra = align_offset - info_size; // recalculate due to potential guard pages *psegment_slices = mi_segment_calculate_slices(required + extra, ppre_size, pinfo_slices); + + // mi_page_t.slice_count type is uint32_t + if (*psegment_slices > (size_t)UINT32_MAX) return NULL; } const size_t segment_size = (*psegment_slices) * MI_SEGMENT_SLICE_SIZE; @@ -865,6 +868,9 @@ static mi_segment_t* mi_segment_alloc(size_t required, size_t page_alignment, mi size_t pre_size; size_t segment_slices = mi_segment_calculate_slices(required, &pre_size, &info_slices); + // mi_page_t.slice_count type is uint32_t + if (segment_slices > (size_t)UINT32_MAX) return NULL; + // Commit eagerly only if not the first N lazy segments (to reduce impact of many threads that allocate just a little) const bool eager_delay = (// !_mi_os_has_overcommit() && // never delay on overcommit systems _mi_current_thread_count() > 1 && // do not delay for the first N threads From 919784737c69e0f8e34d7d7a2e85b02628af6e66 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 16 Apr 2024 23:26:54 +0200 Subject: [PATCH 003/127] gh-117645: Increase WASI stack size from 512 KiB to 8 MiB (#117674) Increase also the initial memory from 10 MiB to 20 MiB. Reenable test_dynamic on WASI build. --- Include/cpython/pystate.h | 11 +++-------- Lib/test/test_dynamic.py | 3 +-- .../2024-04-09-12-59-06.gh-issue-117645.0oEVAa.rst | 2 ++ configure | 2 +- configure.ac | 5 +++-- 5 files changed, 10 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2024-04-09-12-59-06.gh-issue-117645.0oEVAa.rst diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 7fb6b1763921733..6d5dba2bf3725b9 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -198,14 +198,6 @@ struct _ts { #ifdef Py_DEBUG // A debug build is likely built with low optimization level which implies // higher stack memory usage than a release build: use a lower limit. -# if defined(__wasi__) - // Based on wasmtime 16. -# define Py_C_RECURSION_LIMIT 150 -# else -# define Py_C_RECURSION_LIMIT 500 -# endif -#elif defined(__wasi__) - // Based on wasmtime 16. # define Py_C_RECURSION_LIMIT 500 #elif defined(__s390x__) # define Py_C_RECURSION_LIMIT 800 @@ -219,6 +211,9 @@ struct _ts { # define Py_C_RECURSION_LIMIT 3000 #elif defined(_Py_ADDRESS_SANITIZER) # define Py_C_RECURSION_LIMIT 4000 +#elif defined(__wasi__) + // Based on wasmtime 16. +# define Py_C_RECURSION_LIMIT 5000 #else // This value is duplicated in Lib/test/support/__init__.py # define Py_C_RECURSION_LIMIT 10000 diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py index 0cb56a98f1c12af..0aa3be6a1bde6ae 100644 --- a/Lib/test/test_dynamic.py +++ b/Lib/test/test_dynamic.py @@ -4,7 +4,7 @@ import sys import unittest -from test.support import is_wasi, swap_item, swap_attr +from test.support import swap_item, swap_attr class RebindBuiltinsTests(unittest.TestCase): @@ -134,7 +134,6 @@ def test_eval_gives_lambda_custom_globals(self): self.assertEqual(foo(), 7) - @unittest.skipIf(is_wasi, "stack depth too shallow in WASI") def test_load_global_specialization_failure_keeps_oparg(self): # https://github.com/python/cpython/issues/91625 class MyGlobals(dict): diff --git a/Misc/NEWS.d/next/Build/2024-04-09-12-59-06.gh-issue-117645.0oEVAa.rst b/Misc/NEWS.d/next/Build/2024-04-09-12-59-06.gh-issue-117645.0oEVAa.rst new file mode 100644 index 000000000000000..83df6338c291ab0 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2024-04-09-12-59-06.gh-issue-117645.0oEVAa.rst @@ -0,0 +1,2 @@ +Increase WASI stack size from 512 KiB to 8 MiB and the initial memory from 10 +MiB to 20 MiB. Patch by Victor Stinner. diff --git a/configure b/configure index 80403255a814afd..6782d470aadfff5 100755 --- a/configure +++ b/configure @@ -9530,7 +9530,7 @@ then : fi - as_fn_append LDFLAGS_NODIST " -z stack-size=524288 -Wl,--stack-first -Wl,--initial-memory=10485760" + as_fn_append LDFLAGS_NODIST " -z stack-size=8388608 -Wl,--stack-first -Wl,--initial-memory=20971520" ;; #( *) : diff --git a/configure.ac b/configure.ac index ec925d4d4a0a5ac..51a0d35dbc328e9 100644 --- a/configure.ac +++ b/configure.ac @@ -2384,9 +2384,10 @@ AS_CASE([$ac_sys_system], AS_VAR_APPEND([LDFLAGS_NODIST], [" -Wl,--max-memory=10485760"]) ]) - dnl increase initial memory and stack size, move stack first + dnl gh-117645: Set the memory size to 20 MiB, the stack size to 8 MiB, + dnl and move the stack first. dnl https://github.com/WebAssembly/wasi-libc/issues/233 - AS_VAR_APPEND([LDFLAGS_NODIST], [" -z stack-size=524288 -Wl,--stack-first -Wl,--initial-memory=10485760"]) + AS_VAR_APPEND([LDFLAGS_NODIST], [" -z stack-size=8388608 -Wl,--stack-first -Wl,--initial-memory=20971520"]) ] ) From de0dc68b8263da4e3e69d517f303b9b08b36f142 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 17 Apr 2024 00:10:05 +0200 Subject: [PATCH 004/127] gh-115009: Update Windows installer to use SQLite 3.45.3 (GH-117445) --- .../2024-04-15-21-23-34.gh-issue-115009.uhisHP.rst | 1 + Misc/externals.spdx.json | 8 ++++---- PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2024-04-15-21-23-34.gh-issue-115009.uhisHP.rst diff --git a/Misc/NEWS.d/next/Windows/2024-04-15-21-23-34.gh-issue-115009.uhisHP.rst b/Misc/NEWS.d/next/Windows/2024-04-15-21-23-34.gh-issue-115009.uhisHP.rst new file mode 100644 index 000000000000000..01269b2f3e5216e --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2024-04-15-21-23-34.gh-issue-115009.uhisHP.rst @@ -0,0 +1 @@ +Update Windows installer to use SQLite 3.45.3. diff --git a/Misc/externals.spdx.json b/Misc/externals.spdx.json index 6df6401835c6f10..17d9e372fd0b893 100644 --- a/Misc/externals.spdx.json +++ b/Misc/externals.spdx.json @@ -91,21 +91,21 @@ "checksums": [ { "algorithm": "SHA256", - "checksumValue": "6f0364a27375435a34137b138ca4fedef8d23eec6493ca1dfff33bfc0c34fda4" + "checksumValue": "730e4a3efd6a63828bee499940fb13acc2a32c182502ce8a1d970387895d0504" } ], - "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/sqlite-3.45.1.0.tar.gz", + "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/sqlite-3.45.3.0.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:sqlite:sqlite:3.45.1.0:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:sqlite:sqlite:3.45.3.0:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], "licenseConcluded": "NOASSERTION", "name": "sqlite", "primaryPackagePurpose": "SOURCE", - "versionInfo": "3.45.1.0" + "versionInfo": "3.45.3.0" }, { "SPDXID": "SPDXRef-PACKAGE-tcl-core", diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index f5b7e114c98dedd..8f07c414272c474 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,7 +55,7 @@ set libraries=%libraries% bzip2-1.0.8 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.4 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.0.13 set libraries=%libraries% mpdecimal-2.5.1 -set libraries=%libraries% sqlite-3.45.1.0 +set libraries=%libraries% sqlite-3.45.3.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.13.1 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.13.1 set libraries=%libraries% xz-5.2.5 diff --git a/PCbuild/python.props b/PCbuild/python.props index a8d08073fbd11ec..9f8b42d71cd2f3d 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -68,7 +68,7 @@ - $(ExternalsDir)sqlite-3.45.1.0\ + $(ExternalsDir)sqlite-3.45.3.0\ $(ExternalsDir)bzip2-1.0.8\ $(ExternalsDir)xz-5.2.5\ $(ExternalsDir)libffi-3.4.4\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 1fdd8a4a5ab52bd..f4dfe0e9015f028 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -191,7 +191,7 @@ _ssl again when building. _sqlite3 - Wraps SQLite 3.45.1, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.45.3, which is itself built by sqlite3.vcxproj Homepage: https://www.sqlite.org/ _tkinter From d70ee13e575ae4832f2824add64dba77ce5ab7ad Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Tue, 16 Apr 2024 17:11:43 -0500 Subject: [PATCH 005/127] gh-112844: Fix xz CPE identifier (GH-117656) --- Misc/externals.spdx.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/externals.spdx.json b/Misc/externals.spdx.json index 17d9e372fd0b893..bef0ce7d7e61752 100644 --- a/Misc/externals.spdx.json +++ b/Misc/externals.spdx.json @@ -161,7 +161,7 @@ "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:xz_project:xz:5.2.5:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:tukaani:xz:5.2.5:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], From dd4383f3c12fc938a445d974543f897c3fc07c0a Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 16 Apr 2024 15:37:18 -0700 Subject: [PATCH 006/127] linecache: Fix docstring location (#117948) gh-117501 put some code before the docstring, so now it is no longer recognized as a docstring. --- Lib/linecache.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Lib/linecache.py b/Lib/linecache.py index d1113b108dc5e44..3462f1c451ba291 100644 --- a/Lib/linecache.py +++ b/Lib/linecache.py @@ -78,16 +78,15 @@ def checkcache(filename=None): def updatecache(filename, module_globals=None): - # These imports are not at top level because linecache is in the critical - # path of the interpreter startup and importing os and sys take a lot of time - # and slow down the startup sequence. - import os - import sys - """Update a cache entry and return its list of lines. If something's wrong, print a message, discard the cache entry, and return an empty list.""" + # These imports are not at top level because linecache is in the critical + # path of the interpreter startup and importing os and sys take a lot of time + # and slows down the startup sequence. + import os + import sys import tokenize if filename in cache: From a23fa3368e50866f31d6fc1c66a9a5ca2a580239 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 17 Apr 2024 00:55:53 +0200 Subject: [PATCH 007/127] gh-117945: Fix `os.path.ismount()` documentation (#117947) --- Doc/library/os.path.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst index ebeb3bb50b8b1f7..24d423eb5fbfed7 100644 --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -302,8 +302,8 @@ the :mod:`glob` module.) always mount points, and for any other path ``GetVolumePathName`` is called to see if it is different from the input path. - .. versionadded:: 3.4 - Support for detecting non-root mount points on Windows. + .. versionchanged:: 3.4 + Added support for detecting non-root mount points on Windows. .. versionchanged:: 3.6 Accepts a :term:`path-like object`. From c69968ff69b59b27d43708379e4399f424f92075 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 10:18:24 +0300 Subject: [PATCH 008/127] gh-71966: Move the module docstring from _pydecimal to decimal (GH-117919) Now it is set even if the C implementation is used. Also add a one-line synopsis. --- Lib/_pydecimal.py | 99 +-------------------------------------------- Lib/decimal.py | 101 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 100 deletions(-) diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 2692f2fcba45bf2..de4561a5ee050b8 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -13,104 +13,7 @@ # bug) and will be backported. At this point the spec is stabilizing # and the updates are becoming fewer, smaller, and less significant. -""" -This is an implementation of decimal floating point arithmetic based on -the General Decimal Arithmetic Specification: - - http://speleotrove.com/decimal/decarith.html - -and IEEE standard 854-1987: - - http://en.wikipedia.org/wiki/IEEE_854-1987 - -Decimal floating point has finite precision with arbitrarily large bounds. - -The purpose of this module is to support arithmetic using familiar -"schoolhouse" rules and to avoid some of the tricky representation -issues associated with binary floating point. The package is especially -useful for financial applications or for contexts where users have -expectations that are at odds with binary floating point (for instance, -in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead -of 0.0; Decimal('1.00') % Decimal('0.1') returns the expected -Decimal('0.00')). - -Here are some examples of using the decimal module: - ->>> from decimal import * ->>> setcontext(ExtendedContext) ->>> Decimal(0) -Decimal('0') ->>> Decimal('1') -Decimal('1') ->>> Decimal('-.0123') -Decimal('-0.0123') ->>> Decimal(123456) -Decimal('123456') ->>> Decimal('123.45e12345678') -Decimal('1.2345E+12345680') ->>> Decimal('1.33') + Decimal('1.27') -Decimal('2.60') ->>> Decimal('12.34') + Decimal('3.87') - Decimal('18.41') -Decimal('-2.20') ->>> dig = Decimal(1) ->>> print(dig / Decimal(3)) -0.333333333 ->>> getcontext().prec = 18 ->>> print(dig / Decimal(3)) -0.333333333333333333 ->>> print(dig.sqrt()) -1 ->>> print(Decimal(3).sqrt()) -1.73205080756887729 ->>> print(Decimal(3) ** 123) -4.85192780976896427E+58 ->>> inf = Decimal(1) / Decimal(0) ->>> print(inf) -Infinity ->>> neginf = Decimal(-1) / Decimal(0) ->>> print(neginf) --Infinity ->>> print(neginf + inf) -NaN ->>> print(neginf * inf) --Infinity ->>> print(dig / 0) -Infinity ->>> getcontext().traps[DivisionByZero] = 1 ->>> print(dig / 0) -Traceback (most recent call last): - ... - ... - ... -decimal.DivisionByZero: x / 0 ->>> c = Context() ->>> c.traps[InvalidOperation] = 0 ->>> print(c.flags[InvalidOperation]) -0 ->>> c.divide(Decimal(0), Decimal(0)) -Decimal('NaN') ->>> c.traps[InvalidOperation] = 1 ->>> print(c.flags[InvalidOperation]) -1 ->>> c.flags[InvalidOperation] = 0 ->>> print(c.flags[InvalidOperation]) -0 ->>> print(c.divide(Decimal(0), Decimal(0))) -Traceback (most recent call last): - ... - ... - ... -decimal.InvalidOperation: 0 / 0 ->>> print(c.flags[InvalidOperation]) -1 ->>> c.flags[InvalidOperation] = 0 ->>> c.traps[InvalidOperation] = 0 ->>> print(c.divide(Decimal(0), Decimal(0))) -NaN ->>> print(c.flags[InvalidOperation]) -1 ->>> -""" +"""Python decimal arithmetic module""" __all__ = [ # Two major classes diff --git a/Lib/decimal.py b/Lib/decimal.py index 7746ea2601024ce..d61e374b9f99987 100644 --- a/Lib/decimal.py +++ b/Lib/decimal.py @@ -1,11 +1,108 @@ +"""Decimal fixed point and floating point arithmetic. + +This is an implementation of decimal floating point arithmetic based on +the General Decimal Arithmetic Specification: + + http://speleotrove.com/decimal/decarith.html + +and IEEE standard 854-1987: + + http://en.wikipedia.org/wiki/IEEE_854-1987 + +Decimal floating point has finite precision with arbitrarily large bounds. + +The purpose of this module is to support arithmetic using familiar +"schoolhouse" rules and to avoid some of the tricky representation +issues associated with binary floating point. The package is especially +useful for financial applications or for contexts where users have +expectations that are at odds with binary floating point (for instance, +in binary floating point, 1.00 % 0.1 gives 0.09999999999999995 instead +of 0.0; Decimal('1.00') % Decimal('0.1') returns the expected +Decimal('0.00')). + +Here are some examples of using the decimal module: + +>>> from decimal import * +>>> setcontext(ExtendedContext) +>>> Decimal(0) +Decimal('0') +>>> Decimal('1') +Decimal('1') +>>> Decimal('-.0123') +Decimal('-0.0123') +>>> Decimal(123456) +Decimal('123456') +>>> Decimal('123.45e12345678') +Decimal('1.2345E+12345680') +>>> Decimal('1.33') + Decimal('1.27') +Decimal('2.60') +>>> Decimal('12.34') + Decimal('3.87') - Decimal('18.41') +Decimal('-2.20') +>>> dig = Decimal(1) +>>> print(dig / Decimal(3)) +0.333333333 +>>> getcontext().prec = 18 +>>> print(dig / Decimal(3)) +0.333333333333333333 +>>> print(dig.sqrt()) +1 +>>> print(Decimal(3).sqrt()) +1.73205080756887729 +>>> print(Decimal(3) ** 123) +4.85192780976896427E+58 +>>> inf = Decimal(1) / Decimal(0) +>>> print(inf) +Infinity +>>> neginf = Decimal(-1) / Decimal(0) +>>> print(neginf) +-Infinity +>>> print(neginf + inf) +NaN +>>> print(neginf * inf) +-Infinity +>>> print(dig / 0) +Infinity +>>> getcontext().traps[DivisionByZero] = 1 +>>> print(dig / 0) +Traceback (most recent call last): + ... + ... + ... +decimal.DivisionByZero: x / 0 +>>> c = Context() +>>> c.traps[InvalidOperation] = 0 +>>> print(c.flags[InvalidOperation]) +0 +>>> c.divide(Decimal(0), Decimal(0)) +Decimal('NaN') +>>> c.traps[InvalidOperation] = 1 +>>> print(c.flags[InvalidOperation]) +1 +>>> c.flags[InvalidOperation] = 0 +>>> print(c.flags[InvalidOperation]) +0 +>>> print(c.divide(Decimal(0), Decimal(0))) +Traceback (most recent call last): + ... + ... + ... +decimal.InvalidOperation: 0 / 0 +>>> print(c.flags[InvalidOperation]) +1 +>>> c.flags[InvalidOperation] = 0 +>>> c.traps[InvalidOperation] = 0 +>>> print(c.divide(Decimal(0), Decimal(0))) +NaN +>>> print(c.flags[InvalidOperation]) +1 +>>> +""" try: from _decimal import * - from _decimal import __doc__ from _decimal import __version__ from _decimal import __libmpdec_version__ except ImportError: from _pydecimal import * - from _pydecimal import __doc__ from _pydecimal import __version__ from _pydecimal import __libmpdec_version__ From 8123c34faa5aab20edc268c7f8a81e6a765af366 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Wed, 17 Apr 2024 10:25:05 +0300 Subject: [PATCH 009/127] gh-117923: Catch ``test_webbrowser.test_parse_args_error`` stderr output (#117924) --- Lib/test/test_webbrowser.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py index 849665294c3dfa0..ae8d776e8413ffc 100644 --- a/Lib/test/test_webbrowser.py +++ b/Lib/test/test_webbrowser.py @@ -461,11 +461,23 @@ def test_parse_args_error(self): "https://example.com --new-window --new-tab", "https://example.com -n --new-tab", "https://example.com --new-window -t", - # Ensure ambiguous shortening fails - "https://example.com --new", ]: + with support.captured_stderr() as stderr: + with self.assertRaises(SystemExit): + webbrowser.parse_args(shlex.split(command)) + self.assertIn( + 'error: argument -t/--new-tab: not allowed with argument -n/--new-window', + stderr.getvalue(), + ) + + # Ensure ambiguous shortening fails + with support.captured_stderr() as stderr: with self.assertRaises(SystemExit): - webbrowser.parse_args(shlex.split(command)) + webbrowser.parse_args(shlex.split("https://example.com --new")) + self.assertIn( + 'error: ambiguous option: --new could match --new-window, --new-tab', + stderr.getvalue() + ) def test_main(self): for command, expected_url, expected_new_win in [ From 8cc9adbfddc8e37cf7d621b12754eecb0584f5da Mon Sep 17 00:00:00 2001 From: tsufeki Date: Wed, 17 Apr 2024 09:39:15 +0200 Subject: [PATCH 010/127] gh-75171: Fix parsing invalid email address headers starting or ending with a dot (GH-15600) Co-authored-by: Tim Bell Co-authored-by: Serhiy Storchaka --- Lib/email/_header_value_parser.py | 19 ++++++++++---- .../test_email/test__header_value_parser.py | 26 +++++++++++++++++++ Lib/test/test_email/test_headerregistry.py | 20 ++++++++++++++ .../2019-08-29-20-26-08.bpo-30988.b-_h5O.rst | 1 + 4 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index e4a342d446f6a38..0cf23fc9f656b1b 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -566,12 +566,14 @@ def display_name(self): if res[0].token_type == 'cfws': res.pop(0) else: - if res[0][0].token_type == 'cfws': + if (isinstance(res[0], TokenList) and + res[0][0].token_type == 'cfws'): res[0] = TokenList(res[0][1:]) if res[-1].token_type == 'cfws': res.pop() else: - if res[-1][-1].token_type == 'cfws': + if (isinstance(res[-1], TokenList) and + res[-1][-1].token_type == 'cfws'): res[-1] = TokenList(res[-1][:-1]) return res.value @@ -586,9 +588,13 @@ def value(self): quote = True if len(self) != 0 and quote: pre = post = '' - if self[0].token_type=='cfws' or self[0][0].token_type=='cfws': + if (self[0].token_type == 'cfws' or + isinstance(self[0], TokenList) and + self[0][0].token_type == 'cfws'): pre = ' ' - if self[-1].token_type=='cfws' or self[-1][-1].token_type=='cfws': + if (self[-1].token_type == 'cfws' or + isinstance(self[-1], TokenList) and + self[-1][-1].token_type == 'cfws'): post = ' ' return pre+quote_string(self.display_name)+post else: @@ -1772,7 +1778,10 @@ def get_name_addr(value): raise errors.HeaderParseError( "expected name-addr but found '{}'".format(token)) if leader is not None: - token[0][:0] = [leader] + if isinstance(token[0], TokenList): + token[0][:0] = [leader] + else: + token[:0] = [leader] leader = None name_addr.append(token) token, value = get_angle_addr(value) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index f7e80749c456f8f..dd1af9954c61dac 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1805,6 +1805,32 @@ def test_get_name_addr_qs_name(self): self.assertIsNone(name_addr.route) self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com') + def test_get_name_addr_ending_with_dot_without_space(self): + name_addr = self._test_get_x(parser.get_name_addr, + 'John X.', + 'John X.', + '"John X."', + [errors.ObsoleteHeaderDefect], + '') + self.assertEqual(name_addr.display_name, 'John X.') + self.assertEqual(name_addr.local_part, 'jxd') + self.assertEqual(name_addr.domain, 'example.com') + self.assertIsNone(name_addr.route) + self.assertEqual(name_addr.addr_spec, 'jxd@example.com') + + def test_get_name_addr_starting_with_dot(self): + name_addr = self._test_get_x(parser.get_name_addr, + '. Doe ', + '. Doe ', + '". Doe" ', + [errors.InvalidHeaderDefect, errors.ObsoleteHeaderDefect], + '') + self.assertEqual(name_addr.display_name, '. Doe') + self.assertEqual(name_addr.local_part, 'jxd') + self.assertEqual(name_addr.domain, 'example.com') + self.assertIsNone(name_addr.route) + self.assertEqual(name_addr.addr_spec, 'jxd@example.com') + def test_get_name_addr_with_route(self): name_addr = self._test_get_x(parser.get_name_addr, '"Roy.A.Bear" <@two.example.com: dinsdale@example.com>', diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 25347ef13c21475..bb7ca8dfd8c52cc 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1237,6 +1237,26 @@ class TestAddressHeader(TestHeaderBase): 'example.com', None), + 'name_ending_with_dot_without_space': + ('John X.', + [errors.ObsoleteHeaderDefect], + '"John X." ', + 'John X.', + 'jxd@example.com', + 'jxd', + 'example.com', + None), + + 'name_starting_with_dot': + ('. Doe ', + [errors.InvalidHeaderDefect, errors.ObsoleteHeaderDefect], + '". Doe" ', + '. Doe', + 'jxd@example.com', + 'jxd', + 'example.com', + None), + } # XXX: Need many more examples, and in particular some with names in diff --git a/Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst b/Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst new file mode 100644 index 000000000000000..c776c73ba160e06 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst @@ -0,0 +1 @@ +Fix parsing of emails with invalid address headers having a leading or trailing dot. Patch by tsufeki. From f74e51229c83e3265f905dc15283bfe0ec1a659e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 10:44:41 +0300 Subject: [PATCH 011/127] gh-86650: Fix IndexError when parse emails with invalid Message-ID (GH-117934) In particularly, one-off addresses generated by Microsoft Outlook: https://learn.microsoft.com/en-us/office/client-developer/outlook/mapi/one-off-addresses Co-authored-by: fsc-eriker <72394365+fsc-eriker@users.noreply.github.com> --- Lib/email/_header_value_parser.py | 5 ++++ .../test_email/test__header_value_parser.py | 25 +++++++++++++++++++ ...4-04-16-18-34-11.gh-issue-86650.Zeydyg.rst | 2 ++ 3 files changed, 32 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2024-04-16-18-34-11.gh-issue-86650.Zeydyg.rst diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 0cf23fc9f656b1b..7755e629500a8fb 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1520,13 +1520,18 @@ def get_obs_local_part(value): raise token, value = get_cfws(value) obs_local_part.append(token) + if not obs_local_part: + raise errors.HeaderParseError( + "expected obs-local-part but found '{}'".format(value)) if (obs_local_part[0].token_type == 'dot' or obs_local_part[0].token_type=='cfws' and + len(obs_local_part) > 1 and obs_local_part[1].token_type=='dot'): obs_local_part.defects.append(errors.InvalidHeaderDefect( "Invalid leading '.' in local part")) if (obs_local_part[-1].token_type == 'dot' or obs_local_part[-1].token_type=='cfws' and + len(obs_local_part) > 1 and obs_local_part[-2].token_type=='dot'): obs_local_part.defects.append(errors.InvalidHeaderDefect( "Invalid trailing '.' in local part")) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index dd1af9954c61dac..39ed4ee2a381590 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2724,6 +2724,31 @@ def test_get_msg_id_no_angle_end(self): ) self.assertEqual(msg_id.token_type, 'msg-id') + def test_get_msg_id_empty_id_left(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_msg_id("<@domain>") + + def test_get_msg_id_empty_id_right(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_msg_id("") + + def test_get_msg_id_with_brackets(self): + # Microsof Outlook generates non-standard one-off addresses: + # https://learn.microsoft.com/en-us/office/client-developer/outlook/mapi/one-off-addresses + with self.assertRaises(errors.HeaderParseError): + parser.get_msg_id("<[abrakadabra@microsoft.com]>") + + def test_get_msg_id_ws_only_local(self): + msg_id = self._test_get_x( + parser.get_msg_id, + "< @domain>", + "< @domain>", + "< @domain>", + [errors.ObsoleteHeaderDefect], + "" + ) + self.assertEqual(msg_id.token_type, 'msg-id') + @parameterize diff --git a/Misc/NEWS.d/next/Library/2024-04-16-18-34-11.gh-issue-86650.Zeydyg.rst b/Misc/NEWS.d/next/Library/2024-04-16-18-34-11.gh-issue-86650.Zeydyg.rst new file mode 100644 index 000000000000000..8a1626fa63c8041 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-16-18-34-11.gh-issue-86650.Zeydyg.rst @@ -0,0 +1,2 @@ +Fix IndexError when parse some emails with invalid Message-ID (including +one-off addresses generated by Microsoft Outlook). From 8515fd79fef1ac16d7848cec5ec1797294cb5366 Mon Sep 17 00:00:00 2001 From: Joshua Root Date: Wed, 17 Apr 2024 19:26:10 +1000 Subject: [PATCH 012/127] gh-117845: Detect libedit hook function signature in configure (#117870) Older libedit versions (like Apple's) use a different type signature for rl_startup_hook and rl_pre_input_hook. Add a configure check to determine which signature is accepted by introducing the Py_RL_STARTUP_HOOK_TAKES_ARGS macro in pyconfig.h. --- ...-04-15-08-35-06.gh-issue-117845.IowzyW.rst | 1 + Modules/readline.c | 4 +- configure | 50 +++++++++++++++++++ configure.ac | 15 ++++++ pyconfig.h.in | 3 ++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2024-04-15-08-35-06.gh-issue-117845.IowzyW.rst diff --git a/Misc/NEWS.d/next/Build/2024-04-15-08-35-06.gh-issue-117845.IowzyW.rst b/Misc/NEWS.d/next/Build/2024-04-15-08-35-06.gh-issue-117845.IowzyW.rst new file mode 100644 index 000000000000000..02d62da15b25466 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2024-04-15-08-35-06.gh-issue-117845.IowzyW.rst @@ -0,0 +1 @@ +Fix building against recent libedit versions by detecting readline hook signatures in :program:`configure`. diff --git a/Modules/readline.c b/Modules/readline.c index e29051c37f88271..c5c34535de01546 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -1041,7 +1041,7 @@ on_hook(PyObject *func) } static int -#if defined(_RL_FUNCTION_TYPEDEF) +#if defined(_RL_FUNCTION_TYPEDEF) || !defined(Py_RL_STARTUP_HOOK_TAKES_ARGS) on_startup_hook(void) #else on_startup_hook(const char *Py_UNUSED(text), int Py_UNUSED(state)) @@ -1061,7 +1061,7 @@ on_startup_hook(const char *Py_UNUSED(text), int Py_UNUSED(state)) #ifdef HAVE_RL_PRE_INPUT_HOOK static int -#if defined(_RL_FUNCTION_TYPEDEF) +#if defined(_RL_FUNCTION_TYPEDEF) || !defined(Py_RL_STARTUP_HOOK_TAKES_ARGS) on_pre_input_hook(void) #else on_pre_input_hook(const char *Py_UNUSED(text), int Py_UNUSED(state)) diff --git a/configure b/configure index 6782d470aadfff5..29a7d5b2b86c293 100755 --- a/configure +++ b/configure @@ -25367,6 +25367,56 @@ printf "%s\n" "#define HAVE_RL_COMPDISP_FUNC_T 1" >>confdefs.h fi + # Some editline versions declare rl_startup_hook as taking no args, others + # declare it as taking 2. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if rl_startup_hook takes arguments" >&5 +printf %s "checking if rl_startup_hook takes arguments... " >&6; } +if test ${ac_cv_readline_rl_startup_hook_takes_args+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include /* Must be first for Gnu Readline */ + #ifdef WITH_EDITLINE + # include + #else + # include + # include + #endif + + extern int test_hook_func(const char *text, int state); +int +main (void) +{ +rl_startup_hook=test_hook_func; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_readline_rl_startup_hook_takes_args=yes +else $as_nop + ac_cv_readline_rl_startup_hook_takes_args=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_readline_rl_startup_hook_takes_args" >&5 +printf "%s\n" "$ac_cv_readline_rl_startup_hook_takes_args" >&6; } + if test "x$ac_cv_readline_rl_startup_hook_takes_args" = xyes +then : + + +printf "%s\n" "#define Py_RL_STARTUP_HOOK_TAKES_ARGS 1" >>confdefs.h + + +fi + CFLAGS=$save_CFLAGS diff --git a/configure.ac b/configure.ac index 51a0d35dbc328e9..7723c805b93daee 100644 --- a/configure.ac +++ b/configure.ac @@ -6341,6 +6341,21 @@ AS_VAR_IF([with_readline], [no], [ # in readline as well as newer editline (April 2023) AC_CHECK_TYPES([rl_compdisp_func_t], [], [], [readline_includes]) + # Some editline versions declare rl_startup_hook as taking no args, others + # declare it as taking 2. + AC_CACHE_CHECK([if rl_startup_hook takes arguments], [ac_cv_readline_rl_startup_hook_takes_args], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([readline_includes] + [extern int test_hook_func(const char *text, int state);], + [rl_startup_hook=test_hook_func;])], + [ac_cv_readline_rl_startup_hook_takes_args=yes], + [ac_cv_readline_rl_startup_hook_takes_args=no] + ) + ]) + AS_VAR_IF([ac_cv_readline_rl_startup_hook_takes_args], [yes], [ + AC_DEFINE([Py_RL_STARTUP_HOOK_TAKES_ARGS], [1], [Define if rl_startup_hook takes arguments]) + ]) + m4_undefine([readline_includes]) ])dnl WITH_SAVE_ENV() ]) diff --git a/pyconfig.h.in b/pyconfig.h.in index e28baef51d57373..c279b147db3bdd2 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1659,6 +1659,9 @@ SipHash13: 3, externally defined: 0 */ #undef Py_HASH_ALGORITHM +/* Define if rl_startup_hook takes arguments */ +#undef Py_RL_STARTUP_HOOK_TAKES_ARGS + /* Define if you want to enable internal statistics gathering. */ #undef Py_STATS From 8429b4565deaef7a86bffc0ce58bc0eab1d7ae48 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 12:50:07 +0300 Subject: [PATCH 013/127] gh-117879: Fix test_httpservers for the build with profiling (GH-117932) --- Lib/test/test_httpservers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 7c0edfea4f97782..1c370dcafa9fea0 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -815,6 +815,9 @@ def tearDown(self): os.rmdir(self.cgi_dir_in_sub_dir) os.rmdir(self.sub_dir_2) os.rmdir(self.sub_dir_1) + # The 'gmon.out' file can be written in the current working + # directory if C-level code profiling with gprof is enabled. + os_helper.unlink(os.path.join(self.parent_dir, 'gmon.out')) os.rmdir(self.parent_dir) finally: BaseTestCase.tearDown(self) From 44890b209ebe2efaf4f57eed04967948547cfa3b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 12:50:49 +0300 Subject: [PATCH 014/127] gh-117907: Fix test_inspect for the build with enabled tracing references (GH-117922) --- Lib/test/test_inspect/test_inspect.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index e8b09c413f12da9..b2265e44e0c79b8 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -5338,6 +5338,8 @@ def test_types_module_has_signatures(self): def test_sys_module_has_signatures(self): no_signature = {'getsizeof', 'set_asyncgen_hooks'} + no_signature |= {name for name in ['getobjects'] + if hasattr(sys, name)} self._test_module_has_signatures(sys, no_signature) def test_abc_module_has_signatures(self): From 51132da0c4dac13500d9bb86b2fdad42091d3fd9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 12:53:40 +0300 Subject: [PATCH 015/127] gh-117503: Fix support of non-ASCII user names in posixpath.expanduser() (GH-117504) They are now supported in bytes paths as well as in string paths. --- Lib/posixpath.py | 2 +- Lib/test/test_posixpath.py | 11 +++++++++++ .../2024-04-03-15-04-23.gh-issue-117503.NMfwup.rst | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-03-15-04-23.gh-issue-117503.NMfwup.rst diff --git a/Lib/posixpath.py b/Lib/posixpath.py index dd29fbb1614aa80..11cbaca53edb125 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -262,7 +262,7 @@ def expanduser(path): return path name = path[1:i] if isinstance(name, bytes): - name = name.decode('ascii') + name = os.fsdecode(name) try: pwent = pwd.getpwnam(name) except KeyError: diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index 7c122e6204b1005..604af5bafa7f136 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -344,6 +344,17 @@ def test_expanduser_pwd(self): for path in ('~', '~/.local', '~vstinner/'): self.assertEqual(posixpath.expanduser(path), path) + @unittest.skipIf(sys.platform == "vxworks", + "no home directory on VxWorks") + def test_expanduser_pwd2(self): + pwd = import_helper.import_module('pwd') + for e in pwd.getpwall(): + name = e.pw_name + home = e.pw_dir + self.assertEqual(posixpath.expanduser('~' + name), home) + self.assertEqual(posixpath.expanduser(os.fsencode('~' + name)), + os.fsencode(home)) + NORMPATH_CASES = [ ("", "."), ("/", "/"), diff --git a/Misc/NEWS.d/next/Library/2024-04-03-15-04-23.gh-issue-117503.NMfwup.rst b/Misc/NEWS.d/next/Library/2024-04-03-15-04-23.gh-issue-117503.NMfwup.rst new file mode 100644 index 000000000000000..f0ea513ac9d4a90 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-03-15-04-23.gh-issue-117503.NMfwup.rst @@ -0,0 +1,2 @@ +Fix support of non-ASCII user names in bytes paths in +:func:`os.path.expanduser` on Posix. From 4e502a4997af4c8042a6ac13115a3f8ba31520ea Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 12:58:19 +0300 Subject: [PATCH 016/127] gh-117394: Speed up os.path.ismount() on Posix (GH-117447) It is now 2-3 times faster if the user has permissions. --- Lib/posixpath.py | 9 ++++++--- .../2024-04-02-11-17-44.gh-issue-117394.2aoSlb.rst | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-02-11-17-44.gh-issue-117394.2aoSlb.rst diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 11cbaca53edb125..79cda50753e0d20 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -206,11 +206,14 @@ def ismount(path): parent = join(path, b'..') else: parent = join(path, '..') - parent = realpath(parent) try: s2 = os.lstat(parent) - except (OSError, ValueError): - return False + except OSError: + parent = realpath(parent) + try: + s2 = os.lstat(parent) + except OSError: + return False # path/.. on a different device as path or the same i-node as path return s1.st_dev != s2.st_dev or s1.st_ino == s2.st_ino diff --git a/Misc/NEWS.d/next/Library/2024-04-02-11-17-44.gh-issue-117394.2aoSlb.rst b/Misc/NEWS.d/next/Library/2024-04-02-11-17-44.gh-issue-117394.2aoSlb.rst new file mode 100644 index 000000000000000..7b695be4b35d0c7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-02-11-17-44.gh-issue-117394.2aoSlb.rst @@ -0,0 +1 @@ +:func:`os.path.ismount` is now 2-3 times faster if the user has permissions. From aec1dac4efe36a7db51f08385ddcce978814dbe3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 13:00:25 +0300 Subject: [PATCH 017/127] gh-117313: Fix re-folding email messages containing non-standard line separators (GH-117369) Only treat '\n', '\r' and '\r\n' as line separators in re-folding the email messages. Preserve control characters '\v', '\f', '\x1c', '\x1d' and '\x1e' and Unicode line separators '\x85', '\u2028' and '\u2029' as is. --- Lib/email/policy.py | 5 +- Lib/test/test_email/test_generator.py | 49 +++++++++++++++++++ ...-03-29-15-14-51.gh-issue-117313.ks_ONu.rst | 4 ++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-03-29-15-14-51.gh-issue-117313.ks_ONu.rst diff --git a/Lib/email/policy.py b/Lib/email/policy.py index 8816c84ed175a70..46b7de5bb6d8ae8 100644 --- a/Lib/email/policy.py +++ b/Lib/email/policy.py @@ -21,7 +21,7 @@ 'HTTP', ] -linesep_splitter = re.compile(r'\n|\r') +linesep_splitter = re.compile(r'\n|\r\n?') @_extend_docstrings class EmailPolicy(Policy): @@ -205,7 +205,8 @@ def _fold(self, name, value, refold_binary=False): if hasattr(value, 'name'): return value.fold(policy=self) maxlen = self.max_line_length if self.max_line_length else sys.maxsize - lines = value.splitlines() + # We can't use splitlines here because it splits on more than \r and \n. + lines = linesep_splitter.split(value) refold = (self.refold_source == 'all' or self.refold_source == 'long' and (lines and len(lines[0])+len(name)+2 > maxlen or diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py index 89e7edeb63a8926..3ebcb684d006d08 100644 --- a/Lib/test/test_email/test_generator.py +++ b/Lib/test/test_email/test_generator.py @@ -140,6 +140,39 @@ def test_flatten_linesep_overrides_policy(self): g.flatten(msg, linesep='\n') self.assertEqual(s.getvalue(), self.typ(expected)) + def test_flatten_linesep(self): + source = 'Subject: one\n two\r three\r\n four\r\n\r\ntest body\r\n' + msg = self.msgmaker(self.typ(source)) + self.assertEqual(msg['Subject'], 'one two three four') + + expected = 'Subject: one\n two\n three\n four\n\ntest body\n' + s = self.ioclass() + g = self.genclass(s) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + + expected = 'Subject: one two three four\n\ntest body\n' + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(refold_source='all')) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + + def test_flatten_control_linesep(self): + source = 'Subject: one\v two\f three\x1c four\x1d five\x1e six\r\n\r\ntest body\r\n' + msg = self.msgmaker(self.typ(source)) + self.assertEqual(msg['Subject'], 'one\v two\f three\x1c four\x1d five\x1e six') + + expected = 'Subject: one\v two\f three\x1c four\x1d five\x1e six\n\ntest body\n' + s = self.ioclass() + g = self.genclass(s) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(refold_source='all')) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + def test_set_mangle_from_via_policy(self): source = textwrap.dedent("""\ Subject: test that @@ -224,6 +257,22 @@ class TestGenerator(TestGeneratorBase, TestEmailBase): ioclass = io.StringIO typ = str + def test_flatten_unicode_linesep(self): + source = 'Subject: one\x85 two\u2028 three\u2029 four\r\n\r\ntest body\r\n' + msg = self.msgmaker(self.typ(source)) + self.assertEqual(msg['Subject'], 'one\x85 two\u2028 three\u2029 four') + + expected = 'Subject: =?utf-8?b?b25lwoUgdHdv4oCoIHRocmVl4oCp?= four\n\ntest body\n' + s = self.ioclass() + g = self.genclass(s) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + + s = self.ioclass() + g = self.genclass(s, policy=self.policy.clone(refold_source='all')) + g.flatten(msg) + self.assertEqual(s.getvalue(), self.typ(expected)) + class TestBytesGenerator(TestGeneratorBase, TestEmailBase): diff --git a/Misc/NEWS.d/next/Library/2024-03-29-15-14-51.gh-issue-117313.ks_ONu.rst b/Misc/NEWS.d/next/Library/2024-03-29-15-14-51.gh-issue-117313.ks_ONu.rst new file mode 100644 index 000000000000000..e67576ee574f922 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-03-29-15-14-51.gh-issue-117313.ks_ONu.rst @@ -0,0 +1,4 @@ +Only treat ``'\n'``, ``'\r'`` and ``'\r\n'`` as line separators in +re-folding the :mod:`email` messages. Preserve control characters ``'\v'``, +``'\f'``, ``'\x1c'``, ``'\x1d'`` and ``'\x1e'`` and Unicode line separators +``'\x85'``, ``'\u2028'`` and ``'\u2029'`` as is. From 438b7c3071eebaccd1ba215f15a239345b22f813 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 13:03:26 +0300 Subject: [PATCH 018/127] gh-73231: Update documentation for PyErr_SetFromWindowsErr() (GH-117226) --- Doc/c-api/exceptions.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index ba13fd1b9973e03..d5c25a68c47bd61 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -221,13 +221,14 @@ For convenience, some of these functions will always return a .. c:function:: PyObject* PyErr_SetFromWindowsErr(int ierr) - This is a convenience function to raise :exc:`WindowsError`. If called with + This is a convenience function to raise :exc:`OSError`. If called with *ierr* of ``0``, the error code returned by a call to :c:func:`!GetLastError` is used instead. It calls the Win32 function :c:func:`!FormatMessage` to retrieve the Windows description of error code given by *ierr* or :c:func:`!GetLastError`, - then it constructs a tuple object whose first item is the *ierr* value and whose - second item is the corresponding error message (gotten from - :c:func:`!FormatMessage`), and then calls ``PyErr_SetObject(PyExc_WindowsError, + then it constructs a :exc:`OSError` object with the :attr:`~OSError.winerror` + attribute set to the error code, the :attr:`~OSError.strerror` attribute + set to the corresponding error message (gotten from + :c:func:`!FormatMessage`), and then calls ``PyErr_SetObject(PyExc_OSError, object)``. This function always returns ``NULL``. .. availability:: Windows. From c917b3e8e113a3e1ffe118e581fac29eaf365191 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 13:05:22 +0300 Subject: [PATCH 019/127] gh-65824: Add "Help on ..." to the "less" prompt in pydoc (GH-116183) --- Lib/pydoc.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py index d9cf03fb4ffd2a3..02af672a628f5ab 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1637,11 +1637,11 @@ def bold(self, text): # --------------------------------------------------------- user interfaces -def pager(text): +def pager(text, title=''): """The first time this is called, determine what kind of pager to use.""" global pager pager = getpager() - pager(text) + pager(text, title) def getpager(): """Decide what method to use for paging through text.""" @@ -1656,24 +1656,24 @@ def getpager(): use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER') if use_pager: if sys.platform == 'win32': # pipes completely broken in Windows - return lambda text: tempfilepager(plain(text), use_pager) + return lambda text, title='': tempfilepager(plain(text), use_pager) elif os.environ.get('TERM') in ('dumb', 'emacs'): - return lambda text: pipepager(plain(text), use_pager) + return lambda text, title='': pipepager(plain(text), use_pager, title) else: - return lambda text: pipepager(text, use_pager) + return lambda text, title='': pipepager(text, use_pager, title) if os.environ.get('TERM') in ('dumb', 'emacs'): return plainpager if sys.platform == 'win32': - return lambda text: tempfilepager(plain(text), 'more <') + return lambda text, title='': tempfilepager(plain(text), 'more <') if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0: - return lambda text: pipepager(text, 'less') + return lambda text, title='': pipepager(text, 'less', title) import tempfile (fd, filename) = tempfile.mkstemp() os.close(fd) try: if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0: - return lambda text: pipepager(text, 'more') + return lambda text, title='': pipepager(text, 'more', title) else: return ttypager finally: @@ -1683,12 +1683,18 @@ def plain(text): """Remove boldface formatting from text.""" return re.sub('.\b', '', text) -def pipepager(text, cmd): +def escape_less(s): + return re.sub(r'([?:.%\\])', r'\\\1', s) + +def pipepager(text, cmd, title=''): """Page through text by feeding it to another program.""" import subprocess env = os.environ.copy() + if title: + title += ' ' + esc_title = escape_less(title) prompt_string = ( - ' ' + f' {esc_title}' + '?ltline %lt?L/%L.' ':byte %bB?s/%s.' '.' @@ -1716,7 +1722,7 @@ def pipepager(text, cmd): # left running and the terminal is in raw mode and unusable. pass -def tempfilepager(text, cmd): +def tempfilepager(text, cmd, title=''): """Page through text by invoking a program on a temporary file.""" import tempfile with tempfile.TemporaryDirectory() as tempdir: @@ -1733,7 +1739,7 @@ def _escape_stdout(text): encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8' return text.encode(encoding, 'backslashreplace').decode(encoding) -def ttypager(text): +def ttypager(text, title=''): """Page through text on a text terminal.""" lines = plain(_escape_stdout(text)).split('\n') try: @@ -1777,7 +1783,7 @@ def ttypager(text): if tty: tty.tcsetattr(fd, tty.TCSAFLUSH, old) -def plainpager(text): +def plainpager(text, title=''): """Simply print unformatted text. This is the ultimate fallback.""" sys.stdout.write(plain(_escape_stdout(text))) @@ -1879,7 +1885,8 @@ def doc(thing, title='Python Library Documentation: %s', forceload=0, """Display text documentation, given an object or a path to an object.""" if output is None: try: - pager(render_doc(thing, title, forceload)) + what = thing if isinstance(thing, str) else type(thing).__name__ + pager(render_doc(thing, title, forceload), f'Help on {what!s}') except ImportError as exc: if is_cli: raise @@ -2253,7 +2260,7 @@ def showtopic(self, topic, more_xrefs=''): text = 'Related help topics: ' + ', '.join(xrefs.split()) + '\n' wrapped_text = textwrap.wrap(text, 72) doc += '\n%s\n' % '\n'.join(wrapped_text) - pager(doc) + pager(doc, f'Help on {topic!s}') def _gettopic(self, topic, more_xrefs=''): """Return unbuffered tuple of (topic, xrefs). From 147cd0581e35a10204776029aeaa7fa1901056bc Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 17 Apr 2024 11:08:05 +0100 Subject: [PATCH 020/127] GH-117760: Streamline the trashcan mechanism (GH-117763) --- Include/cpython/object.h | 47 +++++++------ Include/cpython/pystate.h | 7 +- Include/internal/pycore_object.h | 1 - Objects/object.c | 114 ++++--------------------------- Python/pystate.c | 2 + 5 files changed, 43 insertions(+), 128 deletions(-) diff --git a/Include/cpython/object.h b/Include/cpython/object.h index b64db1ba9a6dd20..2797051281f3b4a 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -448,8 +448,8 @@ without deallocating anything (and so unbounded call-stack depth is avoided). When the call stack finishes unwinding again, code generated by the END macro notices this, and calls another routine to deallocate all the objects that may have been added to the list of deferred deallocations. In effect, a -chain of N deallocations is broken into (N-1)/(_PyTrash_UNWIND_LEVEL-1) pieces, -with the call stack never exceeding a depth of _PyTrash_UNWIND_LEVEL. +chain of N deallocations is broken into (N-1)/(Py_TRASHCAN_HEADROOM-1) pieces, +with the call stack never exceeding a depth of Py_TRASHCAN_HEADROOM. Since the tp_dealloc of a subclass typically calls the tp_dealloc of the base class, we need to ensure that the trashcan is only triggered on the tp_dealloc @@ -461,30 +461,33 @@ passed as second argument to Py_TRASHCAN_BEGIN(). /* Python 3.9 private API, invoked by the macros below. */ PyAPI_FUNC(int) _PyTrash_begin(PyThreadState *tstate, PyObject *op); PyAPI_FUNC(void) _PyTrash_end(PyThreadState *tstate); + +PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op); +PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(PyThreadState *tstate); + + /* Python 3.10 private API, invoked by the Py_TRASHCAN_BEGIN(). */ -PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc); -#define Py_TRASHCAN_BEGIN_CONDITION(op, cond) \ - do { \ - PyThreadState *_tstate = NULL; \ - /* If "cond" is false, then _tstate remains NULL and the deallocator \ - * is run normally without involving the trashcan */ \ - if (cond) { \ - _tstate = PyThreadState_GetUnchecked(); \ - if (_PyTrash_begin(_tstate, _PyObject_CAST(op))) { \ - break; \ - } \ - } - /* The body of the deallocator is here. */ -#define Py_TRASHCAN_END \ - if (_tstate) { \ - _PyTrash_end(_tstate); \ - } \ - } while (0); +/* To avoid raising recursion errors during dealloc trigger trashcan before we reach + * recursion limit. To avoid trashing, we don't attempt to empty the trashcan until + * we have headroom above the trigger limit */ +#define Py_TRASHCAN_HEADROOM 50 #define Py_TRASHCAN_BEGIN(op, dealloc) \ - Py_TRASHCAN_BEGIN_CONDITION((op), \ - _PyTrash_cond(_PyObject_CAST(op), (destructor)(dealloc))) +do { \ + PyThreadState *tstate = PyThreadState_Get(); \ + if (tstate->c_recursion_remaining <= Py_TRASHCAN_HEADROOM && Py_TYPE(op)->tp_dealloc == (destructor)dealloc) { \ + _PyTrash_thread_deposit_object(tstate, (PyObject *)op); \ + break; \ + } \ + tstate->c_recursion_remaining--; + /* The body of the deallocator is here. */ +#define Py_TRASHCAN_END \ + tstate->c_recursion_remaining++; \ + if (tstate->delete_later && tstate->c_recursion_remaining > (Py_TRASHCAN_HEADROOM*2)) { \ + _PyTrash_thread_destroy_chain(tstate); \ + } \ +} while (0); PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj); diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 6d5dba2bf3725b9..0611e299403031e 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -56,11 +56,6 @@ typedef struct _stack_chunk { PyObject * data[1]; /* Variable sized */ } _PyStackChunk; -struct _py_trashcan { - int delete_nesting; - PyObject *delete_later; -}; - struct _ts { /* See Python/ceval.c for comments explaining most fields */ @@ -152,7 +147,7 @@ struct _ts { */ unsigned long native_thread_id; - struct _py_trashcan trash; + PyObject *delete_later; /* Tagged pointer to top-most critical section, or zero if there is no * active critical section. Critical sections are only used in diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 7b1c919e627dd4f..512f7a35f50e382 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -615,7 +615,6 @@ _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET(PyObject *op) return (PyWeakReference **)((char *)op + offset); } - // Fast inlined version of PyObject_IS_GC() static inline int _PyObject_IS_GC(PyObject *obj) diff --git a/Objects/object.c b/Objects/object.c index 016d0e1ded92d86..3830db0650bcfc8 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2709,33 +2709,31 @@ Py_ReprLeave(PyObject *obj) /* Trashcan support. */ -#define _PyTrash_UNWIND_LEVEL 50 - /* Add op to the gcstate->trash_delete_later list. Called when the current * call-stack depth gets large. op must be a currently untracked gc'ed * object, with refcount 0. Py_DECREF must already have been called on it. */ -static void -_PyTrash_thread_deposit_object(struct _py_trashcan *trash, PyObject *op) +void +_PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op) { _PyObject_ASSERT(op, _PyObject_IS_GC(op)); _PyObject_ASSERT(op, !_PyObject_GC_IS_TRACKED(op)); _PyObject_ASSERT(op, Py_REFCNT(op) == 0); #ifdef Py_GIL_DISABLED _PyObject_ASSERT(op, op->ob_tid == 0); - op->ob_tid = (uintptr_t)trash->delete_later; + op->ob_tid = (uintptr_t)tstate->delete_later; #else - _PyGCHead_SET_PREV(_Py_AS_GC(op), (PyGC_Head*)trash->delete_later); + _PyGCHead_SET_PREV(_Py_AS_GC(op), (PyGC_Head*)tstate->delete_later); #endif - trash->delete_later = op; + tstate->delete_later = op; } /* Deallocate all the objects in the gcstate->trash_delete_later list. * Called when the call-stack unwinds again. */ -static void -_PyTrash_thread_destroy_chain(struct _py_trashcan *trash) +void +_PyTrash_thread_destroy_chain(PyThreadState *tstate) { - /* We need to increase trash_delete_nesting here, otherwise, + /* We need to increase c_recursion_remaining here, otherwise, _PyTrash_thread_destroy_chain will be called recursively and then possibly crash. An example that may crash without increase: @@ -2746,17 +2744,17 @@ _PyTrash_thread_destroy_chain(struct _py_trashcan *trash) tups = [(tup,) for tup in tups] del tups */ - assert(trash->delete_nesting == 0); - ++trash->delete_nesting; - while (trash->delete_later) { - PyObject *op = trash->delete_later; + assert(tstate->c_recursion_remaining > Py_TRASHCAN_HEADROOM); + tstate->c_recursion_remaining--; + while (tstate->delete_later) { + PyObject *op = tstate->delete_later; destructor dealloc = Py_TYPE(op)->tp_dealloc; #ifdef Py_GIL_DISABLED - trash->delete_later = (PyObject*) op->ob_tid; + tstate->delete_later = (PyObject*) op->ob_tid; op->ob_tid = 0; #else - trash->delete_later = (PyObject*) _PyGCHead_PREV(_Py_AS_GC(op)); + tstate->delete_later = (PyObject*) _PyGCHead_PREV(_Py_AS_GC(op)); #endif /* Call the deallocator directly. This used to try to @@ -2767,92 +2765,10 @@ _PyTrash_thread_destroy_chain(struct _py_trashcan *trash) */ _PyObject_ASSERT(op, Py_REFCNT(op) == 0); (*dealloc)(op); - assert(trash->delete_nesting == 1); - } - --trash->delete_nesting; -} - - -static struct _py_trashcan * -_PyTrash_get_state(PyThreadState *tstate) -{ - if (tstate != NULL) { - return &tstate->trash; - } - // The current thread must be finalizing. - // Fall back to using thread-local state. - // XXX Use thread-local variable syntax? - assert(PyThread_tss_is_created(&_PyRuntime.trashTSSkey)); - struct _py_trashcan *trash = - (struct _py_trashcan *)PyThread_tss_get(&_PyRuntime.trashTSSkey); - if (trash == NULL) { - trash = PyMem_RawMalloc(sizeof(struct _py_trashcan)); - if (trash == NULL) { - Py_FatalError("Out of memory"); - } - PyThread_tss_set(&_PyRuntime.trashTSSkey, (void *)trash); - } - return trash; -} - -static void -_PyTrash_clear_state(PyThreadState *tstate) -{ - if (tstate != NULL) { - assert(tstate->trash.delete_later == NULL); - return; - } - if (PyThread_tss_is_created(&_PyRuntime.trashTSSkey)) { - struct _py_trashcan *trash = - (struct _py_trashcan *)PyThread_tss_get(&_PyRuntime.trashTSSkey); - if (trash != NULL) { - PyThread_tss_set(&_PyRuntime.trashTSSkey, (void *)NULL); - PyMem_RawFree(trash); - } } + tstate->c_recursion_remaining++; } - -int -_PyTrash_begin(PyThreadState *tstate, PyObject *op) -{ - // XXX Make sure the GIL is held. - struct _py_trashcan *trash = _PyTrash_get_state(tstate); - if (trash->delete_nesting >= _PyTrash_UNWIND_LEVEL) { - /* Store the object (to be deallocated later) and jump past - * Py_TRASHCAN_END, skipping the body of the deallocator */ - _PyTrash_thread_deposit_object(trash, op); - return 1; - } - ++trash->delete_nesting; - return 0; -} - - -void -_PyTrash_end(PyThreadState *tstate) -{ - // XXX Make sure the GIL is held. - struct _py_trashcan *trash = _PyTrash_get_state(tstate); - --trash->delete_nesting; - if (trash->delete_nesting <= 0) { - if (trash->delete_later != NULL) { - _PyTrash_thread_destroy_chain(trash); - } - _PyTrash_clear_state(tstate); - } -} - - -/* bpo-40170: It's only be used in Py_TRASHCAN_BEGIN macro to hide - implementation details. */ -int -_PyTrash_cond(PyObject *op, destructor dealloc) -{ - return Py_TYPE(op)->tp_dealloc == dealloc; -} - - void _Py_NO_RETURN _PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg, const char *file, int line, const char *function) diff --git a/Python/pystate.c b/Python/pystate.c index ac38866d301d59a..37480df88aeb726 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1485,6 +1485,8 @@ init_threadstate(_PyThreadStateImpl *_tstate, tstate->what_event = -1; tstate->previous_executor = NULL; + tstate->delete_later = NULL; + llist_init(&_tstate->mem_free_queue); if (interp->stoptheworld.requested || _PyRuntime.stoptheworld.requested) { From 1aa8bbe62f27b564cf15e2aad591c62744354a4e Mon Sep 17 00:00:00 2001 From: Ivan Savin Date: Wed, 17 Apr 2024 14:14:22 +0400 Subject: [PATCH 021/127] bpo-40944: Fix IndexError when parse emails with truncated Message-ID, address, routes, etc (GH-20790) Co-authored-by: Serhiy Storchaka --- Lib/email/_header_value_parser.py | 15 ++++--- .../test_email/test__header_value_parser.py | 40 +++++++++++++++++++ .../2020-06-10-19-24-17.bpo-40943.vjiiN_.rst | 1 + 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-06-10-19-24-17.bpo-40943.vjiiN_.rst diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index 7755e629500a8fb..d1b4c7df4f445f7 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1213,7 +1213,7 @@ def get_bare_quoted_string(value): value is the text between the quote marks, with whitespace preserved and quoted pairs decoded. """ - if value[0] != '"': + if not value or value[0] != '"': raise errors.HeaderParseError( "expected '\"' but found '{}'".format(value)) bare_quoted_string = BareQuotedString() @@ -1454,7 +1454,7 @@ def get_local_part(value): """ local_part = LocalPart() leader = None - if value[0] in CFWS_LEADER: + if value and value[0] in CFWS_LEADER: leader, value = get_cfws(value) if not value: raise errors.HeaderParseError( @@ -1613,7 +1613,7 @@ def get_domain(value): """ domain = Domain() leader = None - if value[0] in CFWS_LEADER: + if value and value[0] in CFWS_LEADER: leader, value = get_cfws(value) if not value: raise errors.HeaderParseError( @@ -1689,6 +1689,8 @@ def get_obs_route(value): if value[0] in CFWS_LEADER: token, value = get_cfws(value) obs_route.append(token) + if not value: + break if value[0] == '@': obs_route.append(RouteComponentMarker) token, value = get_domain(value[1:]) @@ -1707,7 +1709,7 @@ def get_angle_addr(value): """ angle_addr = AngleAddr() - if value[0] in CFWS_LEADER: + if value and value[0] in CFWS_LEADER: token, value = get_cfws(value) angle_addr.append(token) if not value or value[0] != '<': @@ -1717,7 +1719,7 @@ def get_angle_addr(value): value = value[1:] # Although it is not legal per RFC5322, SMTP uses '<>' in certain # circumstances. - if value[0] == '>': + if value and value[0] == '>': angle_addr.append(ValueTerminal('>', 'angle-addr-end')) angle_addr.defects.append(errors.InvalidHeaderDefect( "null addr-spec in angle-addr")) @@ -1769,6 +1771,9 @@ def get_name_addr(value): name_addr = NameAddr() # Both the optional display name and the angle-addr can start with cfws. leader = None + if not value: + raise errors.HeaderParseError( + "expected name-addr but found '{}'".format(value)) if value[0] in CFWS_LEADER: leader, value = get_cfws(value) if not value: diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index 39ed4ee2a381590..56a1e3a3de5aa26 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -801,6 +801,10 @@ def test_get_quoted_string_header_ends_in_qcontent(self): self.assertEqual(qs.content, 'bob') self.assertEqual(qs.quoted_value, ' "bob"') + def test_get_quoted_string_cfws_only_raises(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_quoted_string(' (foo) ') + def test_get_quoted_string_no_quoted_string(self): with self.assertRaises(errors.HeaderParseError): parser.get_quoted_string(' (ab) xyz') @@ -1135,6 +1139,10 @@ def test_get_local_part_complex_obsolete_invalid(self): '@python.org') self.assertEqual(local_part.local_part, 'Fred.A.Johnson and dogs') + def test_get_local_part_empty_raises(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_local_part('') + def test_get_local_part_no_part_raises(self): with self.assertRaises(errors.HeaderParseError): parser.get_local_part(' (foo) ') @@ -1387,6 +1395,10 @@ def test_get_domain_obsolete(self): '') self.assertEqual(domain.domain, 'example.com') + def test_get_domain_empty_raises(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_domain("") + def test_get_domain_no_non_cfws_raises(self): with self.assertRaises(errors.HeaderParseError): parser.get_domain(" (foo)\t") @@ -1512,6 +1524,10 @@ def test_get_obs_route_no_route_before_end_raises(self): with self.assertRaises(errors.HeaderParseError): parser.get_obs_route('(foo) @example.com,') + def test_get_obs_route_no_route_before_end_raises2(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_obs_route('(foo) @example.com, (foo) ') + def test_get_obs_route_no_route_before_special_raises(self): with self.assertRaises(errors.HeaderParseError): parser.get_obs_route('(foo) [abc],') @@ -1520,6 +1536,14 @@ def test_get_obs_route_no_route_before_special_raises2(self): with self.assertRaises(errors.HeaderParseError): parser.get_obs_route('(foo) @example.com [abc],') + def test_get_obs_route_no_domain_after_at_raises(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_obs_route('@') + + def test_get_obs_route_no_domain_after_at_raises2(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_obs_route('@example.com, @') + # get_angle_addr def test_get_angle_addr_simple(self): @@ -1646,6 +1670,14 @@ def test_get_angle_addr_ends_at_special(self): self.assertIsNone(angle_addr.route) self.assertEqual(angle_addr.addr_spec, 'dinsdale@example.com') + def test_get_angle_addr_empty_raise(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_angle_addr('') + + def test_get_angle_addr_left_angle_only_raise(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_angle_addr('<') + def test_get_angle_addr_no_angle_raise(self): with self.assertRaises(errors.HeaderParseError): parser.get_angle_addr('(foo) ') @@ -1857,6 +1889,10 @@ def test_get_name_addr_ends_at_special(self): self.assertIsNone(name_addr.route) self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com') + def test_get_name_addr_empty_raises(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_name_addr('') + def test_get_name_addr_no_content_raises(self): with self.assertRaises(errors.HeaderParseError): parser.get_name_addr(' (foo) ') @@ -2732,6 +2768,10 @@ def test_get_msg_id_empty_id_right(self): with self.assertRaises(errors.HeaderParseError): parser.get_msg_id("") + def test_get_msg_id_no_id_right(self): + with self.assertRaises(errors.HeaderParseError): + parser.get_msg_id(" Date: Wed, 17 Apr 2024 13:59:38 +0200 Subject: [PATCH 022/127] gh-115009: Update macOS installer to use SQLite 3.45.3 (#117443) --- Mac/BuildScript/build-installer.py | 6 +++--- .../macOS/2024-04-15-21-19-39.gh-issue-115009.IdxH9N.rst | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/macOS/2024-04-15-21-19-39.gh-issue-115009.IdxH9N.rst diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index b2f8c77e0c1a73b..286df4862793fba 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -359,9 +359,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.45.1", - url="https://sqlite.org/2024/sqlite-autoconf-3450100.tar.gz", - checksum="cd9c27841b7a5932c9897651e20b86c701dd740556989b01ca596fcfa3d49a0a", + name="SQLite 3.45.3", + url="https://sqlite.org/2024/sqlite-autoconf-3450300.tar.gz", + checksum="b2809ca53124c19c60f42bf627736eae011afdcc205bb48270a5ee9a38191531", extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Misc/NEWS.d/next/macOS/2024-04-15-21-19-39.gh-issue-115009.IdxH9N.rst b/Misc/NEWS.d/next/macOS/2024-04-15-21-19-39.gh-issue-115009.IdxH9N.rst new file mode 100644 index 000000000000000..0c16f716e6a0233 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2024-04-15-21-19-39.gh-issue-115009.IdxH9N.rst @@ -0,0 +1 @@ +Update macOS installer to use SQLite 3.45.3. From 6d0bb43232dd6ebc5245daa4fe29f07f815f0bad Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Wed, 17 Apr 2024 13:55:18 +0100 Subject: [PATCH 023/127] gh-117975: Ensure flush level is checked when configuring a logging MemoryHandler. (GH-117976) --- Lib/logging/config.py | 26 ++++++++++++++------------ Lib/test/test_logging.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Lib/logging/config.py b/Lib/logging/config.py index ea37dd7544564a2..860e47512074704 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -761,18 +761,20 @@ def configure_handler(self, config): klass = cname else: klass = self.resolve(cname) - if issubclass(klass, logging.handlers.MemoryHandler) and\ - 'target' in config: - # Special case for handler which refers to another handler - try: - tn = config['target'] - th = self.config['handlers'][tn] - if not isinstance(th, logging.Handler): - config.update(config_copy) # restore for deferred cfg - raise TypeError('target not configured yet') - config['target'] = th - except Exception as e: - raise ValueError('Unable to set target handler %r' % tn) from e + if issubclass(klass, logging.handlers.MemoryHandler): + if 'flushLevel' in config: + config['flushLevel'] = logging._checkLevel(config['flushLevel']) + if 'target' in config: + # Special case for handler which refers to another handler + try: + tn = config['target'] + th = self.config['handlers'][tn] + if not isinstance(th, logging.Handler): + config.update(config_copy) # restore for deferred cfg + raise TypeError('target not configured yet') + config['target'] = th + except Exception as e: + raise ValueError('Unable to set target handler %r' % tn) from e elif issubclass(klass, logging.handlers.QueueHandler): # Another special case for handler which refers to other handlers # if 'handlers' not in config: diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 3f0b363066df2c8..826b7381686dcb9 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -3036,6 +3036,30 @@ def format(self, record): }, } + config18 = { + "version": 1, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "level": "DEBUG", + }, + "buffering": { + "class": "logging.handlers.MemoryHandler", + "capacity": 5, + "target": "console", + "level": "DEBUG", + "flushLevel": "ERROR" + } + }, + "loggers": { + "mymodule": { + "level": "DEBUG", + "handlers": ["buffering"], + "propagate": "true" + } + } + } + bad_format = { "version": 1, "formatters": { @@ -3522,6 +3546,11 @@ def test_config17_ok(self): h = logging._handlers['hand1'] self.assertEqual(h.formatter.custom_property, 'value') + def test_config18_ok(self): + self.apply_config(self.config18) + handler = logging.getLogger('mymodule').handlers[0] + self.assertEqual(handler.flushLevel, logging.ERROR) + def setup_via_listener(self, text, verify=None): text = text.encode("utf-8") # Ask for a randomly assigned port (by using port 0) From 75eed5b3734edb221cabb8322d8b8bdf9e3ee6b1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Apr 2024 15:01:28 +0200 Subject: [PATCH 024/127] gh-117929: Restore removed PyEval_InitThreads() function (#117931) --- Doc/c-api/init.rst | 30 ++++++++++++++++++- Doc/data/stable_abi.dat | 1 + Doc/whatsnew/3.13.rst | 6 ++-- Include/ceval.h | 2 ++ ...-04-16-13-34-01.gh-issue-117929.HSr419.rst | 2 ++ Misc/stable_abi.toml | 1 - Python/ceval_gil.c | 3 +- 7 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2024-04-16-13-34-01.gh-issue-117929.HSr419.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 05f2fd13cf2069b..9b98e71ae533ecf 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -59,7 +59,7 @@ The following functions can be safely called before Python is initialized: :c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`, :c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`, :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`, - and :c:func:`Py_GetProgramName`. + :c:func:`Py_GetProgramName` and :c:func:`PyEval_InitThreads`. .. _global-conf-vars: @@ -326,6 +326,7 @@ Initializing and finalizing the interpreter .. c:function:: void Py_Initialize() .. index:: + single: PyEval_InitThreads() single: modules (in module sys) single: path (in module sys) pair: module; builtins @@ -841,6 +842,33 @@ code, or when embedding the Python interpreter: This thread's interpreter state. +.. c:function:: void PyEval_InitThreads() + + .. index:: + single: PyEval_AcquireThread() + single: PyEval_ReleaseThread() + single: PyEval_SaveThread() + single: PyEval_RestoreThread() + + Deprecated function which does nothing. + + In Python 3.6 and older, this function created the GIL if it didn't exist. + + .. versionchanged:: 3.9 + The function now does nothing. + + .. versionchanged:: 3.7 + This function is now called by :c:func:`Py_Initialize()`, so you don't + have to call it yourself anymore. + + .. versionchanged:: 3.2 + This function cannot be called before :c:func:`Py_Initialize()` anymore. + + .. deprecated:: 3.9 + + .. index:: pair: module; _thread + + .. c:function:: PyThreadState* PyEval_SaveThread() Release the global interpreter lock (if it has been created) and reset the diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 2763bea5137cc72..aa9022357841941 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -192,6 +192,7 @@ function,PyEval_GetFuncDesc,3.2,, function,PyEval_GetFuncName,3.2,, function,PyEval_GetGlobals,3.2,, function,PyEval_GetLocals,3.2,, +function,PyEval_InitThreads,3.2,, function,PyEval_ReleaseThread,3.2,, function,PyEval_RestoreThread,3.2,, function,PyEval_SaveThread,3.2,, diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index f957698ecb06d8f..86c6a7e93f0a55b 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -2027,9 +2027,9 @@ Removed added in Python 3.8 and the old macros were deprecated in Python 3.11. (Contributed by Irit Katriel in :gh:`105111`.) -* Remove ``PyEval_InitThreads()`` and ``PyEval_ThreadsInitialized()`` - functions, deprecated in Python 3.9. Since Python 3.7, ``Py_Initialize()`` - always creates the GIL: calling ``PyEval_InitThreads()`` did nothing and +* Remove ``PyEval_ThreadsInitialized()`` + function, deprecated in Python 3.9. Since Python 3.7, ``Py_Initialize()`` + always creates the GIL: calling ``PyEval_InitThreads()`` does nothing and ``PyEval_ThreadsInitialized()`` always returned non-zero. (Contributed by Victor Stinner in :gh:`105182`.) diff --git a/Include/ceval.h b/Include/ceval.h index 9885bdb7febc21a..8ea9da8d134ee0d 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -107,6 +107,8 @@ PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(PyFrameObject *f, int exc); PyAPI_FUNC(PyThreadState *) PyEval_SaveThread(void); PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); +Py_DEPRECATED(3.9) PyAPI_FUNC(void) PyEval_InitThreads(void); + PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate); PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate); diff --git a/Misc/NEWS.d/next/C API/2024-04-16-13-34-01.gh-issue-117929.HSr419.rst b/Misc/NEWS.d/next/C API/2024-04-16-13-34-01.gh-issue-117929.HSr419.rst new file mode 100644 index 000000000000000..58d475bbf219811 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-04-16-13-34-01.gh-issue-117929.HSr419.rst @@ -0,0 +1,2 @@ +Restore removed :c:func:`PyEval_InitThreads` function. Patch by Victor +Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 14dda7db1c323e2..ad6f0ee3a5c2123 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -702,7 +702,6 @@ added = '3.2' [function.PyEval_InitThreads] added = '3.2' - abi_only = true [function.PyEval_ReleaseLock] added = '3.2' abi_only = true diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index d88ac65c5cf300a..c0819d8ab1d8d03 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -512,8 +512,7 @@ _PyEval_FiniGIL(PyInterpreterState *interp) interp->ceval.gil = NULL; } -// Function removed in the Python 3.13 API but kept in the stable ABI. -PyAPI_FUNC(void) +void PyEval_InitThreads(void) { /* Do nothing: kept for backward compatibility */ From 8e36cb7bb2a6057445975d46169f23a719909917 Mon Sep 17 00:00:00 2001 From: Diego Russo Date: Wed, 17 Apr 2024 14:31:48 +0100 Subject: [PATCH 025/127] Test: Get the smtp test server using os.getenv() (#117979) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The smtp test server can be set via CPYTHON_TEST_SMTP_SERVER environment variable. If not set, it uses the default value smtp.gmail.com This is needed because the network I'm on filters access to smtp.gmail.com resulting in a failing test. Co-authored-by: Łukasz Langa --- Lib/test/test_smtpnet.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_smtpnet.py b/Lib/test/test_smtpnet.py index 2e0dc1aa276f358..d765746987bc4b0 100644 --- a/Lib/test/test_smtpnet.py +++ b/Lib/test/test_smtpnet.py @@ -2,6 +2,7 @@ from test import support from test.support import import_helper from test.support import socket_helper +import os import smtplib import socket @@ -9,6 +10,8 @@ support.requires("network") +SMTP_TEST_SERVER = os.getenv('CPYTHON_TEST_SMTP_SERVER', 'smtp.gmail.com') + def check_ssl_verifiy(host, port): context = ssl.create_default_context() with socket.create_connection((host, port)) as sock: @@ -22,7 +25,7 @@ def check_ssl_verifiy(host, port): class SmtpTest(unittest.TestCase): - testServer = 'smtp.gmail.com' + testServer = SMTP_TEST_SERVER remotePort = 587 def test_connect_starttls(self): @@ -44,7 +47,7 @@ def test_connect_starttls(self): class SmtpSSLTest(unittest.TestCase): - testServer = 'smtp.gmail.com' + testServer = SMTP_TEST_SERVER remotePort = 465 def test_connect(self): From 5a0209fc23de113747058858a4d2e5fc8213711e Mon Sep 17 00:00:00 2001 From: CF Bolz-Tereick Date: Wed, 17 Apr 2024 15:34:46 +0200 Subject: [PATCH 026/127] GH-100242: bring functools.py partial implementation more in line with C code (GH-100244) in partial.__new__, before checking for the existence of the attribute 'func', first check whether the argument is an instance of partial. --- Lib/functools.py | 2 +- Lib/test/test_functools.py | 13 +++++++++++++ ...2022-12-14-15-53-38.gh-issue-100242.Ny7VUO.rst | 5 +++++ Modules/_functoolsmodule.c | 15 +++++++++++---- 4 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-12-14-15-53-38.gh-issue-100242.Ny7VUO.rst diff --git a/Lib/functools.py b/Lib/functools.py index b42b9eaa0a045c0..a80e1a6c6a56acc 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -285,7 +285,7 @@ def __new__(cls, func, /, *args, **keywords): if not callable(func): raise TypeError("the first argument must be callable") - if hasattr(func, "func"): + if isinstance(func, partial): args = func.args + args keywords = {**func.keywords, **keywords} func = func.func diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index c48c399a10c853a..ec5f6af5e17842c 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -185,6 +185,19 @@ def test_nested_optimization(self): flat = partial(signature, 'asdf', bar=True) self.assertEqual(signature(nested), signature(flat)) + def test_nested_optimization_bug(self): + partial = self.partial + class Builder: + def __call__(self, tag, *children, **attrib): + return (tag, children, attrib) + + def __getattr__(self, tag): + return partial(self, tag) + + B = Builder() + m = B.m + assert m(1, 2, a=2) == ('m', (1, 2), dict(a=2)) + def test_nested_partial_with_attribute(self): # see issue 25137 partial = self.partial diff --git a/Misc/NEWS.d/next/Library/2022-12-14-15-53-38.gh-issue-100242.Ny7VUO.rst b/Misc/NEWS.d/next/Library/2022-12-14-15-53-38.gh-issue-100242.Ny7VUO.rst new file mode 100644 index 000000000000000..e86059942d52db7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-12-14-15-53-38.gh-issue-100242.Ny7VUO.rst @@ -0,0 +1,5 @@ +Bring pure Python implementation ``functools.partial.__new__`` more in line +with the C-implementation by not just always checking for the presence of +the attribute ``'func'`` on the first argument of ``partial``. Instead, both +the Python version and the C version perform an ``isinstance(func, partial)`` +check on the first argument of ``partial``. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 25c0ecde73246d5..406fcf0da2f7e42 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -79,12 +79,19 @@ partial_new(PyTypeObject *type, PyObject *args, PyObject *kw) return NULL; } + _functools_state *state = get_functools_state_by_type(type); + if (state == NULL) { + return NULL; + } + pargs = pkw = NULL; func = PyTuple_GET_ITEM(args, 0); - if (Py_TYPE(func)->tp_call == (ternaryfunc)partial_call) { - // The type of "func" might not be exactly the same type object - // as "type", but if it is called using partial_call, it must have the - // same memory layout (fn, args and kw members). + + int res = PyObject_TypeCheck(func, state->partial_type); + if (res == -1) { + return NULL; + } + if (res == 1) { // We can use its underlying function directly and merge the arguments. partialobject *part = (partialobject *)func; if (part->dict == NULL) { From fccedbda9316d52d93b2db855c07f947fab26ae2 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 17 Apr 2024 16:59:02 +0200 Subject: [PATCH 027/127] gh-117977: Amend version changed annotation for os.chmod, os.chown, and os.listdir (#117978) --- Doc/library/os.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index e2bd481fa30b0dd..06ec7da14ebfaeb 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2135,7 +2135,7 @@ features: .. audit-event:: os.chmod path,mode,dir_fd os.chmod - .. versionadded:: 3.3 + .. versionchanged:: 3.3 Added support for specifying *path* as an open file descriptor, and the *dir_fd* and *follow_symlinks* arguments. @@ -2166,7 +2166,7 @@ features: The function is limited on WASI, see :ref:`wasm-availability` for more information. - .. versionadded:: 3.3 + .. versionchanged:: 3.3 Added support for specifying *path* as an open file descriptor, and the *dir_fd* and *follow_symlinks* arguments. @@ -2310,7 +2310,7 @@ features: .. versionchanged:: 3.2 The *path* parameter became optional. - .. versionadded:: 3.3 + .. versionchanged:: 3.3 Added support for specifying *path* as an open file descriptor. .. versionchanged:: 3.6 From ae8dfd2761e4a45afe0adada0f91f371dd121bb8 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Wed, 17 Apr 2024 17:40:56 +0200 Subject: [PATCH 028/127] Doc: Render version/language selector on Read the Docs (#116966) --- Doc/tools/templates/layout.html | 86 +++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/Doc/tools/templates/layout.html b/Doc/tools/templates/layout.html index 9498b2ccc5af929..3c12b01b558f839 100644 --- a/Doc/tools/templates/layout.html +++ b/Doc/tools/templates/layout.html @@ -41,4 +41,90 @@ {{ "}" }} {{ super() }} + + + {% endblock %} From c179c0e6cbb4d1e981fffd43f207f5b1aa5388e5 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:42:04 +0100 Subject: [PATCH 029/127] gh-117680: make _PyInstructionSequence a PyObject and use it in tests (#117629) --- .../pycore_global_objects_fini_generated.h | 4 + Include/internal/pycore_global_strings.h | 4 + .../internal/pycore_instruction_sequence.h | 16 +- .../internal/pycore_runtime_init_generated.h | 4 + .../internal/pycore_unicodeobject_generated.h | 12 + Lib/test/support/bytecode_helper.py | 85 +++-- Lib/test/test_compile.py | 46 +++ Lib/test/test_compiler_assemble.py | 20 +- Lib/test/test_peepholer.py | 48 +-- ...-04-09-16-07-00.gh-issue-117680.MRZ78K.rst | 1 + Modules/_testinternalcapi.c | 15 + Modules/clinic/_testinternalcapi.c.h | 20 +- Objects/object.c | 2 + Python/clinic/instruction_sequence.c.h | 304 ++++++++++++++++++ Python/compile.c | 198 ++---------- Python/instruction_sequence.c | 300 +++++++++++++++++ Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 + 17 files changed, 838 insertions(+), 242 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-09-16-07-00.gh-issue-117680.MRZ78K.rst create mode 100644 Python/clinic/instruction_sequence.c.h diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 24f32fca2e53310..90a338ade17c61b 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -864,6 +864,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(co_stacksize)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(co_varnames)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(code)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(col_offset)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(command)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(comment_factory)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(compile_mode)); @@ -913,6 +914,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(encode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(encoding)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(end)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(end_col_offset)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(end_lineno)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(end_offset)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(endpos)); @@ -1033,6 +1035,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw1)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw2)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kwdefaults)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(label)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(lambda)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last_exc)); @@ -1096,6 +1099,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(namespaces)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(narg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ndigits)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nested)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(new_file_name)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(new_limit)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(newline)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 024f817408cee53..0899e7ee776617a 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -353,6 +353,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(co_stacksize) STRUCT_FOR_ID(co_varnames) STRUCT_FOR_ID(code) + STRUCT_FOR_ID(col_offset) STRUCT_FOR_ID(command) STRUCT_FOR_ID(comment_factory) STRUCT_FOR_ID(compile_mode) @@ -402,6 +403,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(encode) STRUCT_FOR_ID(encoding) STRUCT_FOR_ID(end) + STRUCT_FOR_ID(end_col_offset) STRUCT_FOR_ID(end_lineno) STRUCT_FOR_ID(end_offset) STRUCT_FOR_ID(endpos) @@ -522,6 +524,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(kw1) STRUCT_FOR_ID(kw2) STRUCT_FOR_ID(kwdefaults) + STRUCT_FOR_ID(label) STRUCT_FOR_ID(lambda) STRUCT_FOR_ID(last) STRUCT_FOR_ID(last_exc) @@ -585,6 +588,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(namespaces) STRUCT_FOR_ID(narg) STRUCT_FOR_ID(ndigits) + STRUCT_FOR_ID(nested) STRUCT_FOR_ID(new_file_name) STRUCT_FOR_ID(new_limit) STRUCT_FOR_ID(newline) diff --git a/Include/internal/pycore_instruction_sequence.h b/Include/internal/pycore_instruction_sequence.h index b57484fa05309fa..ecba0d9d8e996ea 100644 --- a/Include/internal/pycore_instruction_sequence.h +++ b/Include/internal/pycore_instruction_sequence.h @@ -5,10 +5,13 @@ # error "this header requires Py_BUILD_CORE define" #endif +#include "pycore_symtable.h" + #ifdef __cplusplus extern "C" { #endif + typedef struct { int h_label; int h_startdepth; @@ -26,23 +29,30 @@ typedef struct { int i_offset; } _PyInstruction; -typedef struct { +typedef struct instruction_sequence { + PyObject_HEAD _PyInstruction *s_instrs; int s_allocated; int s_used; int s_next_free_label; /* next free label id */ + /* Map of a label id to instruction offset (index into s_instrs). * If s_labelmap is NULL, then each label id is the offset itself. */ - int *s_labelmap; /* label id --> instr offset */ + int *s_labelmap; int s_labelmap_size; + + /* PyList of instruction sequences of nested functions */ + PyObject *s_nested; } _PyInstructionSequence; typedef struct { int id; } _PyJumpTargetLabel; +PyAPI_FUNC(PyObject*)_PyInstructionSequence_New(void); + int _PyInstructionSequence_UseLabel(_PyInstructionSequence *seq, int lbl); int _PyInstructionSequence_Addop(_PyInstructionSequence *seq, int opcode, int oparg, @@ -53,6 +63,8 @@ int _PyInstructionSequence_InsertInstruction(_PyInstructionSequence *seq, int po int opcode, int oparg, _Py_SourceLocation loc); void PyInstructionSequence_Fini(_PyInstructionSequence *seq); +extern PyTypeObject _PyInstructionSequence_Type; +#define _PyInstructionSequence_Check(v) Py_IS_TYPE((v), &_PyInstructionSequence_Type) #ifdef __cplusplus } diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 795f95cb3a78850..d4323e5bd12a67e 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -862,6 +862,7 @@ extern "C" { INIT_ID(co_stacksize), \ INIT_ID(co_varnames), \ INIT_ID(code), \ + INIT_ID(col_offset), \ INIT_ID(command), \ INIT_ID(comment_factory), \ INIT_ID(compile_mode), \ @@ -911,6 +912,7 @@ extern "C" { INIT_ID(encode), \ INIT_ID(encoding), \ INIT_ID(end), \ + INIT_ID(end_col_offset), \ INIT_ID(end_lineno), \ INIT_ID(end_offset), \ INIT_ID(endpos), \ @@ -1031,6 +1033,7 @@ extern "C" { INIT_ID(kw1), \ INIT_ID(kw2), \ INIT_ID(kwdefaults), \ + INIT_ID(label), \ INIT_ID(lambda), \ INIT_ID(last), \ INIT_ID(last_exc), \ @@ -1094,6 +1097,7 @@ extern "C" { INIT_ID(namespaces), \ INIT_ID(narg), \ INIT_ID(ndigits), \ + INIT_ID(nested), \ INIT_ID(new_file_name), \ INIT_ID(new_limit), \ INIT_ID(newline), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 272462e99b0d941..9daef267069d0d1 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -900,6 +900,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(code); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(col_offset); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(command); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1047,6 +1050,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(end); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(end_col_offset); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(end_lineno); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1407,6 +1413,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(kwdefaults); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(label); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(lambda); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1596,6 +1605,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(ndigits); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(nested); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(new_file_name); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); diff --git a/Lib/test/support/bytecode_helper.py b/Lib/test/support/bytecode_helper.py index 7a0e884ccc122ae..85bcd1f0f1cd4f3 100644 --- a/Lib/test/support/bytecode_helper.py +++ b/Lib/test/support/bytecode_helper.py @@ -3,6 +3,7 @@ import unittest import dis import io +import opcode try: import _testinternalcapi except ImportError: @@ -68,16 +69,14 @@ class CompilationStepTestCase(unittest.TestCase): class Label: pass - def assertInstructionsMatch(self, actual_, expected_): - # get two lists where each entry is a label or - # an instruction tuple. Normalize the labels to the - # instruction count of the target, and compare the lists. + def assertInstructionsMatch(self, actual_seq, expected): + # get an InstructionSequence and an expected list, where each + # entry is a label or an instruction tuple. Construct an expcted + # instruction sequence and compare with the one given. - self.assertIsInstance(actual_, list) - self.assertIsInstance(expected_, list) - - actual = self.normalize_insts(actual_) - expected = self.normalize_insts(expected_) + self.assertIsInstance(expected, list) + actual = actual_seq.get_instructions() + expected = self.seq_from_insts(expected).get_instructions() self.assertEqual(len(actual), len(expected)) # compare instructions @@ -87,10 +86,8 @@ def assertInstructionsMatch(self, actual_, expected_): continue self.assertIsInstance(exp, tuple) self.assertIsInstance(act, tuple) - # crop comparison to the provided expected values - if len(act) > len(exp): - act = act[:len(exp)] - self.assertEqual(exp, act) + idx = max([p[0] for p in enumerate(exp) if p[1] != -1]) + self.assertEqual(exp[:idx], act[:idx]) def resolveAndRemoveLabels(self, insts): idx = 0 @@ -105,35 +102,37 @@ def resolveAndRemoveLabels(self, insts): return res - def normalize_insts(self, insts): - """ Map labels to instruction index. - Map opcodes to opnames. - """ - insts = self.resolveAndRemoveLabels(insts) - res = [] - for item in insts: - assert isinstance(item, tuple) - opcode, oparg, *loc = item - opcode = dis.opmap.get(opcode, opcode) - if isinstance(oparg, self.Label): - arg = oparg.value - else: - arg = oparg if opcode in self.HAS_ARG else None - opcode = dis.opname[opcode] - res.append((opcode, arg, *loc)) - return res + def seq_from_insts(self, insts): + labels = {item for item in insts if isinstance(item, self.Label)} + for i, lbl in enumerate(labels): + lbl.value = i - def complete_insts_info(self, insts): - # fill in omitted fields in location, and oparg 0 for ops with no arg. - res = [] + seq = _testinternalcapi.new_instruction_sequence() for item in insts: - assert isinstance(item, tuple) - inst = list(item) - opcode = dis.opmap[inst[0]] - oparg = inst[1] - loc = inst[2:] + [-1] * (6 - len(inst)) - res.append((opcode, oparg, *loc)) - return res + if isinstance(item, self.Label): + seq.use_label(item.value) + else: + op = item[0] + if isinstance(op, str): + op = opcode.opmap[op] + arg, *loc = item[1:] + if isinstance(arg, self.Label): + arg = arg.value + loc = loc + [-1] * (4 - len(loc)) + seq.addop(op, arg or 0, *loc) + return seq + + def check_instructions(self, insts): + for inst in insts: + if isinstance(inst, self.Label): + continue + op, arg, *loc = inst + if isinstance(op, str): + op = opcode.opmap[op] + self.assertEqual(op in opcode.hasarg, + arg is not None, + f"{opcode.opname[op]=} {arg=}") + self.assertTrue(all(isinstance(l, int) for l in loc)) @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") @@ -147,10 +146,8 @@ def generate_code(self, ast): @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") class CfgOptimizationTestCase(CompilationStepTestCase): - def get_optimized(self, insts, consts, nlocals=0): - insts = self.normalize_insts(insts) - insts = self.complete_insts_info(insts) - insts = _testinternalcapi.optimize_cfg(insts, consts, nlocals) + def get_optimized(self, seq, consts, nlocals=0): + insts = _testinternalcapi.optimize_cfg(seq, consts, nlocals) return insts, consts @unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi") diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 638b6e96b5025bf..484d72e63411a80 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -2,6 +2,7 @@ import dis import io import math +import opcode import os import unittest import sys @@ -11,6 +12,8 @@ import types import textwrap import warnings +import _testinternalcapi + from test import support from test.support import (script_helper, requires_debug_ranges, requires_specialization, get_c_recursion_limit) @@ -2419,6 +2422,49 @@ def test_return_inside_async_with_block(self): """ self.check_stack_size(snippet, async_=True) +class TestInstructionSequence(unittest.TestCase): + def compare_instructions(self, seq, expected): + self.assertEqual([(opcode.opname[i[0]],) + i[1:] for i in seq.get_instructions()], + expected) + + def test_basics(self): + seq = _testinternalcapi.new_instruction_sequence() + + def add_op(seq, opname, oparg, bl, bc=0, el=0, ec=0): + seq.addop(opcode.opmap[opname], oparg, bl, bc, el, el) + + add_op(seq, 'LOAD_CONST', 1, 1) + add_op(seq, 'JUMP', lbl1 := seq.new_label(), 2) + add_op(seq, 'LOAD_CONST', 1, 3) + add_op(seq, 'JUMP', lbl2 := seq.new_label(), 4) + seq.use_label(lbl1) + add_op(seq, 'LOAD_CONST', 2, 4) + seq.use_label(lbl2) + add_op(seq, 'RETURN_VALUE', 0, 3) + + expected = [('LOAD_CONST', 1, 1), + ('JUMP', 4, 2), + ('LOAD_CONST', 1, 3), + ('JUMP', 5, 4), + ('LOAD_CONST', 2, 4), + ('RETURN_VALUE', None, 3), + ] + + self.compare_instructions(seq, [ex + (0,0,0) for ex in expected]) + + def test_nested(self): + seq = _testinternalcapi.new_instruction_sequence() + seq.addop(opcode.opmap['LOAD_CONST'], 1, 1, 0, 0, 0) + nested = _testinternalcapi.new_instruction_sequence() + nested.addop(opcode.opmap['LOAD_CONST'], 2, 2, 0, 0, 0) + + self.compare_instructions(seq, [('LOAD_CONST', 1, 1, 0, 0, 0)]) + self.compare_instructions(nested, [('LOAD_CONST', 2, 2, 0, 0, 0)]) + + seq.add_nested(nested) + self.compare_instructions(seq, [('LOAD_CONST', 1, 1, 0, 0, 0)]) + self.compare_instructions(seq.get_nested()[0], [('LOAD_CONST', 2, 2, 0, 0, 0)]) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_compiler_assemble.py b/Lib/test/test_compiler_assemble.py index ab9f04dd63af202..1b98b0d97ed8a50 100644 --- a/Lib/test/test_compiler_assemble.py +++ b/Lib/test/test_compiler_assemble.py @@ -27,8 +27,8 @@ def complete_metadata(self, metadata, filename="myfile.py"): def insts_to_code_object(self, insts, metadata): metadata = self.complete_metadata(metadata) - insts = self.complete_insts_info(insts) - return self.get_code_object(metadata['filename'], insts, metadata) + seq = self.seq_from_insts(insts) + return self.get_code_object(metadata['filename'], seq, metadata) def assemble_test(self, insts, metadata, expected): co = self.insts_to_code_object(insts, metadata) @@ -71,7 +71,7 @@ def test_simple_expr(self): ('BINARY_OP', 0, 1), # '+' ('LOAD_CONST', 0, 1), # 2 ('BINARY_OP', 11, 1), # '/' - ('RETURN_VALUE', 1), + ('RETURN_VALUE', None, 1), ] expected = {(3, 4) : 3.5, (-100, 200) : 50, (10, 18) : 14} self.assemble_test(insts, metadata, expected) @@ -102,13 +102,13 @@ def inner(): ('LOAD_CLOSURE', 0, 1), ('BUILD_TUPLE', 1, 1), ('LOAD_CONST', 1, 1), - ('MAKE_FUNCTION', 0, 2), + ('MAKE_FUNCTION', None, 2), ('SET_FUNCTION_ATTRIBUTE', 8, 2), - ('PUSH_NULL', 0, 1), + ('PUSH_NULL', None, 1), ('CALL', 0, 2), # (lambda: x)() ('LOAD_CONST', 2, 2), # 2 ('BINARY_OP', 6, 2), # % - ('RETURN_VALUE', 0, 2) + ('RETURN_VALUE', None, 2) ] expected = {(0,): 0, (1,): 1, (2,): 0, (120,): 0, (121,): 1} @@ -128,12 +128,12 @@ def test_exception_table(self): ('SETUP_FINALLY', 3), ('RETURN_CONST', 0), ('SETUP_CLEANUP', 8), - ('PUSH_EXC_INFO', 0), - ('POP_TOP', 0), - ('POP_EXCEPT', 0), + ('PUSH_EXC_INFO', None), + ('POP_TOP', None), + ('POP_EXCEPT', None), ('RETURN_CONST', 0), ('COPY', 3), - ('POP_EXCEPT', 0), + ('POP_EXCEPT', None), ('RERAISE', 1), ] co = self.insts_to_code_object(insts, metadata) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index dffedd0b1fc4767..6989aafd293138f 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -1,5 +1,6 @@ import dis from itertools import combinations, product +import opcode import sys import textwrap import unittest @@ -981,10 +982,15 @@ class DirectCfgOptimizerTests(CfgOptimizationTestCase): def cfg_optimization_test(self, insts, expected_insts, consts=None, expected_consts=None, nlocals=0): + + self.check_instructions(insts) + self.check_instructions(expected_insts) + if expected_consts is None: expected_consts = consts - opt_insts, opt_consts = self.get_optimized(insts, consts, nlocals) - expected_insts = self.normalize_insts(expected_insts) + seq = self.seq_from_insts(insts) + opt_insts, opt_consts = self.get_optimized(seq, consts, nlocals) + expected_insts = self.seq_from_insts(expected_insts).get_instructions() self.assertInstructionsMatch(opt_insts, expected_insts) self.assertEqual(opt_consts, expected_consts) @@ -993,10 +999,10 @@ def test_conditional_jump_forward_non_const_condition(self): ('LOAD_NAME', 1, 11), ('POP_JUMP_IF_TRUE', lbl := self.Label(), 12), ('LOAD_CONST', 2, 13), - ('RETURN_VALUE', 13), + ('RETURN_VALUE', None, 13), lbl, ('LOAD_CONST', 3, 14), - ('RETURN_VALUE', 14), + ('RETURN_VALUE', None, 14), ] expected_insts = [ ('LOAD_NAME', 1, 11), @@ -1020,11 +1026,11 @@ def test_conditional_jump_forward_const_condition(self): ('LOAD_CONST', 2, 13), lbl, ('LOAD_CONST', 3, 14), - ('RETURN_VALUE', 14), + ('RETURN_VALUE', None, 14), ] expected_insts = [ - ('NOP', 11), - ('NOP', 12), + ('NOP', None, 11), + ('NOP', None, 12), ('RETURN_CONST', 1, 14), ] self.cfg_optimization_test(insts, @@ -1038,14 +1044,14 @@ def test_conditional_jump_backward_non_const_condition(self): ('LOAD_NAME', 1, 11), ('POP_JUMP_IF_TRUE', lbl1, 12), ('LOAD_NAME', 2, 13), - ('RETURN_VALUE', 13), + ('RETURN_VALUE', None, 13), ] expected = [ lbl := self.Label(), ('LOAD_NAME', 1, 11), ('POP_JUMP_IF_TRUE', lbl, 12), ('LOAD_NAME', 2, 13), - ('RETURN_VALUE', 13), + ('RETURN_VALUE', None, 13), ] self.cfg_optimization_test(insts, expected, consts=list(range(5))) @@ -1056,11 +1062,11 @@ def test_conditional_jump_backward_const_condition(self): ('LOAD_CONST', 3, 11), ('POP_JUMP_IF_TRUE', lbl1, 12), ('LOAD_CONST', 2, 13), - ('RETURN_VALUE', 13), + ('RETURN_VALUE', None, 13), ] expected_insts = [ lbl := self.Label(), - ('NOP', 11), + ('NOP', None, 11), ('JUMP', lbl, 12), ] self.cfg_optimization_test(insts, expected_insts, consts=list(range(5))) @@ -1068,7 +1074,7 @@ def test_conditional_jump_backward_const_condition(self): def test_except_handler_label(self): insts = [ ('SETUP_FINALLY', handler := self.Label(), 10), - ('POP_BLOCK', 0, -1), + ('POP_BLOCK', None, -1), ('RETURN_CONST', 1, 11), handler, ('RETURN_CONST', 2, 12), @@ -1090,16 +1096,16 @@ def test_no_unsafe_static_swap(self): ('SWAP', 3, 4), ('STORE_FAST', 1, 4), ('STORE_FAST', 1, 4), - ('POP_TOP', 0, 4), + ('POP_TOP', None, 4), ('LOAD_CONST', 0, 5), - ('RETURN_VALUE', 5) + ('RETURN_VALUE', None, 5) ] expected_insts = [ ('LOAD_CONST', 0, 1), ('LOAD_CONST', 1, 2), - ('NOP', 0, 3), + ('NOP', None, 3), ('STORE_FAST', 1, 4), - ('POP_TOP', 0, 4), + ('POP_TOP', None, 4), ('RETURN_CONST', 0) ] self.cfg_optimization_test(insts, expected_insts, consts=list(range(3)), nlocals=1) @@ -1113,13 +1119,13 @@ def test_dead_store_elimination_in_same_lineno(self): ('STORE_FAST', 1, 4), ('STORE_FAST', 1, 4), ('LOAD_CONST', 0, 5), - ('RETURN_VALUE', 5) + ('RETURN_VALUE', None, 5) ] expected_insts = [ ('LOAD_CONST', 0, 1), ('LOAD_CONST', 1, 2), - ('NOP', 0, 3), - ('POP_TOP', 0, 4), + ('NOP', None, 3), + ('POP_TOP', None, 4), ('STORE_FAST', 1, 4), ('RETURN_CONST', 0, 5) ] @@ -1134,7 +1140,7 @@ def test_no_dead_store_elimination_in_different_lineno(self): ('STORE_FAST', 1, 5), ('STORE_FAST', 1, 6), ('LOAD_CONST', 0, 5), - ('RETURN_VALUE', 5) + ('RETURN_VALUE', None, 5) ] expected_insts = [ ('LOAD_CONST', 0, 1), @@ -1169,7 +1175,7 @@ def get_insts(lno1, lno2, op1, op2): op = 'JUMP' if 'JUMP' in (op1, op2) else 'JUMP_NO_INTERRUPT' expected_insts = [ ('LOAD_NAME', 0, 10), - ('NOP', 0, 4), + ('NOP', None, 4), (op, 0, 5), ] self.cfg_optimization_test(insts, expected_insts, consts=list(range(5))) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-09-16-07-00.gh-issue-117680.MRZ78K.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-09-16-07-00.gh-issue-117680.MRZ78K.rst new file mode 100644 index 000000000000000..fd437b7fdd36141 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-09-16-07-00.gh-issue-117680.MRZ78K.rst @@ -0,0 +1 @@ +Give ``_PyInstructionSequence`` a Python interface and use it in tests. diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index 36dad024d31c953..cc9e1403f87ecd0 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -22,6 +22,7 @@ #include "pycore_gc.h" // PyGC_Head #include "pycore_hashtable.h" // _Py_hashtable_new() #include "pycore_initconfig.h" // _Py_GetConfigsAsDict() +#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New() #include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy() #include "pycore_long.h" // _PyLong_Sign() #include "pycore_object.h" // _PyObject_IsFreed() @@ -723,6 +724,19 @@ _testinternalcapi_compiler_cleandoc_impl(PyObject *module, PyObject *doc) return _PyCompile_CleanDoc(doc); } +/*[clinic input] + +_testinternalcapi.new_instruction_sequence -> object + +Return a new, empty InstructionSequence. +[clinic start generated code]*/ + +static PyObject * +_testinternalcapi_new_instruction_sequence_impl(PyObject *module) +/*[clinic end generated code: output=ea4243fddb9057fd input=1dec2591b173be83]*/ +{ + return _PyInstructionSequence_New(); +} /*[clinic input] @@ -1952,6 +1966,7 @@ static PyMethodDef module_functions[] = { {"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL}, {"set_eval_frame_record", set_eval_frame_record, METH_O, NULL}, _TESTINTERNALCAPI_COMPILER_CLEANDOC_METHODDEF + _TESTINTERNALCAPI_NEW_INSTRUCTION_SEQUENCE_METHODDEF _TESTINTERNALCAPI_COMPILER_CODEGEN_METHODDEF _TESTINTERNALCAPI_OPTIMIZE_CFG_METHODDEF _TESTINTERNALCAPI_ASSEMBLE_CODE_OBJECT_METHODDEF diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h index cba2a943d03456a..a61858561d5ef87 100644 --- a/Modules/clinic/_testinternalcapi.c.h +++ b/Modules/clinic/_testinternalcapi.c.h @@ -67,6 +67,24 @@ _testinternalcapi_compiler_cleandoc(PyObject *module, PyObject *const *args, Py_ return return_value; } +PyDoc_STRVAR(_testinternalcapi_new_instruction_sequence__doc__, +"new_instruction_sequence($module, /)\n" +"--\n" +"\n" +"Return a new, empty InstructionSequence."); + +#define _TESTINTERNALCAPI_NEW_INSTRUCTION_SEQUENCE_METHODDEF \ + {"new_instruction_sequence", (PyCFunction)_testinternalcapi_new_instruction_sequence, METH_NOARGS, _testinternalcapi_new_instruction_sequence__doc__}, + +static PyObject * +_testinternalcapi_new_instruction_sequence_impl(PyObject *module); + +static PyObject * +_testinternalcapi_new_instruction_sequence(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testinternalcapi_new_instruction_sequence_impl(module); +} + PyDoc_STRVAR(_testinternalcapi_compiler_codegen__doc__, "compiler_codegen($module, /, ast, filename, optimize, compile_mode=0)\n" "--\n" @@ -282,4 +300,4 @@ _testinternalcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignore { return _testinternalcapi_test_long_numbits_impl(module); } -/*[clinic end generated code: output=679bf53bbae20085 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9804015d77d36c77 input=a9049054013a1b77]*/ diff --git a/Objects/object.c b/Objects/object.c index 3830db0650bcfc8..214e7c5b567928f 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -10,6 +10,7 @@ #include "pycore_dict.h" // _PyObject_MakeDictFromInstanceAttributes() #include "pycore_floatobject.h" // _PyFloat_DebugMallocStats() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() +#include "pycore_instruction_sequence.h" // _PyInstructionSequence_Type #include "pycore_hashtable.h" // _Py_hashtable_new() #include "pycore_memoryobject.h" // _PyManagedBuffer_Type #include "pycore_namespace.h" // _PyNamespace_Type @@ -2294,6 +2295,7 @@ static PyTypeObject* static_types[] = { &_PyHamt_BitmapNode_Type, &_PyHamt_CollisionNode_Type, &_PyHamt_Type, + &_PyInstructionSequence_Type, &_PyLegacyEventHandler_Type, &_PyLineIterator, &_PyManagedBuffer_Type, diff --git a/Python/clinic/instruction_sequence.c.h b/Python/clinic/instruction_sequence.c.h new file mode 100644 index 000000000000000..66c2ccadfa03c92 --- /dev/null +++ b/Python/clinic/instruction_sequence.c.h @@ -0,0 +1,304 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif +#include "pycore_modsupport.h" // _PyArg_NoKeywords() + +PyDoc_STRVAR(inst_seq_new__doc__, +"InstructionSequenceType()\n" +"--\n" +"\n" +"Create a new InstructionSequence object."); + +static PyObject * +inst_seq_new_impl(PyTypeObject *type); + +static PyObject * +inst_seq_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + PyTypeObject *base_tp = &_PyInstructionSequence_Type; + + if ((type == base_tp || type->tp_init == base_tp->tp_init) && + !_PyArg_NoPositional("InstructionSequenceType", args)) { + goto exit; + } + if ((type == base_tp || type->tp_init == base_tp->tp_init) && + !_PyArg_NoKeywords("InstructionSequenceType", kwargs)) { + goto exit; + } + return_value = inst_seq_new_impl(type); + +exit: + return return_value; +} + +PyDoc_STRVAR(InstructionSequenceType_use_label__doc__, +"use_label($self, /, label)\n" +"--\n" +"\n" +"Place label at current location."); + +#define INSTRUCTIONSEQUENCETYPE_USE_LABEL_METHODDEF \ + {"use_label", _PyCFunction_CAST(InstructionSequenceType_use_label), METH_FASTCALL|METH_KEYWORDS, InstructionSequenceType_use_label__doc__}, + +static PyObject * +InstructionSequenceType_use_label_impl(_PyInstructionSequence *self, + int label); + +static PyObject * +InstructionSequenceType_use_label(_PyInstructionSequence *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(label), }, + }; + #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[] = {"label", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "use_label", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + int label; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + label = PyLong_AsInt(args[0]); + if (label == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = InstructionSequenceType_use_label_impl(self, label); + +exit: + return return_value; +} + +PyDoc_STRVAR(InstructionSequenceType_addop__doc__, +"addop($self, /, opcode, oparg, lineno, col_offset, end_lineno,\n" +" end_col_offset)\n" +"--\n" +"\n" +"Append an instruction."); + +#define INSTRUCTIONSEQUENCETYPE_ADDOP_METHODDEF \ + {"addop", _PyCFunction_CAST(InstructionSequenceType_addop), METH_FASTCALL|METH_KEYWORDS, InstructionSequenceType_addop__doc__}, + +static PyObject * +InstructionSequenceType_addop_impl(_PyInstructionSequence *self, int opcode, + int oparg, int lineno, int col_offset, + int end_lineno, int end_col_offset); + +static PyObject * +InstructionSequenceType_addop(_PyInstructionSequence *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 6 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(opcode), &_Py_ID(oparg), &_Py_ID(lineno), &_Py_ID(col_offset), &_Py_ID(end_lineno), &_Py_ID(end_col_offset), }, + }; + #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[] = {"opcode", "oparg", "lineno", "col_offset", "end_lineno", "end_col_offset", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "addop", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[6]; + int opcode; + int oparg; + int lineno; + int col_offset; + int end_lineno; + int end_col_offset; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 6, 6, 0, argsbuf); + if (!args) { + goto exit; + } + opcode = PyLong_AsInt(args[0]); + if (opcode == -1 && PyErr_Occurred()) { + goto exit; + } + oparg = PyLong_AsInt(args[1]); + if (oparg == -1 && PyErr_Occurred()) { + goto exit; + } + lineno = PyLong_AsInt(args[2]); + if (lineno == -1 && PyErr_Occurred()) { + goto exit; + } + col_offset = PyLong_AsInt(args[3]); + if (col_offset == -1 && PyErr_Occurred()) { + goto exit; + } + end_lineno = PyLong_AsInt(args[4]); + if (end_lineno == -1 && PyErr_Occurred()) { + goto exit; + } + end_col_offset = PyLong_AsInt(args[5]); + if (end_col_offset == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = InstructionSequenceType_addop_impl(self, opcode, oparg, lineno, col_offset, end_lineno, end_col_offset); + +exit: + return return_value; +} + +PyDoc_STRVAR(InstructionSequenceType_new_label__doc__, +"new_label($self, /)\n" +"--\n" +"\n" +"Return a new label."); + +#define INSTRUCTIONSEQUENCETYPE_NEW_LABEL_METHODDEF \ + {"new_label", (PyCFunction)InstructionSequenceType_new_label, METH_NOARGS, InstructionSequenceType_new_label__doc__}, + +static int +InstructionSequenceType_new_label_impl(_PyInstructionSequence *self); + +static PyObject * +InstructionSequenceType_new_label(_PyInstructionSequence *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = InstructionSequenceType_new_label_impl(self); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(InstructionSequenceType_add_nested__doc__, +"add_nested($self, /, nested)\n" +"--\n" +"\n" +"Add a nested sequence."); + +#define INSTRUCTIONSEQUENCETYPE_ADD_NESTED_METHODDEF \ + {"add_nested", _PyCFunction_CAST(InstructionSequenceType_add_nested), METH_FASTCALL|METH_KEYWORDS, InstructionSequenceType_add_nested__doc__}, + +static PyObject * +InstructionSequenceType_add_nested_impl(_PyInstructionSequence *self, + PyObject *nested); + +static PyObject * +InstructionSequenceType_add_nested(_PyInstructionSequence *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(nested), }, + }; + #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[] = {"nested", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "add_nested", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *nested; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + nested = args[0]; + return_value = InstructionSequenceType_add_nested_impl(self, nested); + +exit: + return return_value; +} + +PyDoc_STRVAR(InstructionSequenceType_get_nested__doc__, +"get_nested($self, /)\n" +"--\n" +"\n" +"Add a nested sequence."); + +#define INSTRUCTIONSEQUENCETYPE_GET_NESTED_METHODDEF \ + {"get_nested", (PyCFunction)InstructionSequenceType_get_nested, METH_NOARGS, InstructionSequenceType_get_nested__doc__}, + +static PyObject * +InstructionSequenceType_get_nested_impl(_PyInstructionSequence *self); + +static PyObject * +InstructionSequenceType_get_nested(_PyInstructionSequence *self, PyObject *Py_UNUSED(ignored)) +{ + return InstructionSequenceType_get_nested_impl(self); +} + +PyDoc_STRVAR(InstructionSequenceType_get_instructions__doc__, +"get_instructions($self, /)\n" +"--\n" +"\n" +"Return the instructions as a list of tuples or labels."); + +#define INSTRUCTIONSEQUENCETYPE_GET_INSTRUCTIONS_METHODDEF \ + {"get_instructions", (PyCFunction)InstructionSequenceType_get_instructions, METH_NOARGS, InstructionSequenceType_get_instructions__doc__}, + +static PyObject * +InstructionSequenceType_get_instructions_impl(_PyInstructionSequence *self); + +static PyObject * +InstructionSequenceType_get_instructions(_PyInstructionSequence *self, PyObject *Py_UNUSED(ignored)) +{ + return InstructionSequenceType_get_instructions_impl(self); +} +/*[clinic end generated code: output=8809d7aa11d9b2bb input=a9049054013a1b77]*/ diff --git a/Python/compile.c b/Python/compile.c index 1e8f97e72cdff6d..3d856b7e4ddd973 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -32,6 +32,7 @@ #include "pycore_code.h" // _PyCode_New() #include "pycore_compile.h" #include "pycore_flowgraph.h" +#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New() #include "pycore_intrinsics.h" #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_pystate.h" // _Py_GetConfig() @@ -248,7 +249,7 @@ struct compiler_unit { PyObject *u_private; /* for private name mangling */ PyObject *u_static_attributes; /* for class: attributes accessed via self.X */ - instr_sequence u_instr_sequence; /* codegen output */ + instr_sequence *u_instr_sequence; /* codegen output */ int u_nfblocks; int u_in_inlined_comp; @@ -281,12 +282,12 @@ struct compiler { int c_nestlevel; PyObject *c_const_cache; /* Python dict holding all constants, including names tuple */ - struct compiler_unit *u; /* compiler state for current block */ + struct compiler_unit *u; /* compiler state for current block */ PyObject *c_stack; /* Python list holding compiler_unit ptrs */ PyArena *c_arena; /* pointer to memory allocation arena */ }; -#define INSTR_SEQUENCE(C) (&((C)->u->u_instr_sequence)) +#define INSTR_SEQUENCE(C) ((C)->u->u_instr_sequence) typedef struct { @@ -567,7 +568,7 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset) static void compiler_unit_free(struct compiler_unit *u) { - PyInstructionSequence_Fini(&u->u_instr_sequence); + Py_CLEAR(u->u_instr_sequence); Py_CLEAR(u->u_ste); Py_CLEAR(u->u_metadata.u_name); Py_CLEAR(u->u_metadata.u_qualname); @@ -976,7 +977,7 @@ compiler_addop_load_const(PyObject *const_cache, struct compiler_unit *u, locati if (arg < 0) { return ERROR; } - return codegen_addop_i(&u->u_instr_sequence, LOAD_CONST, arg, loc); + return codegen_addop_i(u->u_instr_sequence, LOAD_CONST, arg, loc); } static int @@ -987,7 +988,7 @@ compiler_addop_o(struct compiler_unit *u, location loc, if (arg < 0) { return ERROR; } - return codegen_addop_i(&u->u_instr_sequence, opcode, arg, loc); + return codegen_addop_i(u->u_instr_sequence, opcode, arg, loc); } static int @@ -1033,7 +1034,7 @@ compiler_addop_name(struct compiler_unit *u, location loc, arg <<= 2; arg |= 1; } - return codegen_addop_i(&u->u_instr_sequence, opcode, arg, loc); + return codegen_addop_i(u->u_instr_sequence, opcode, arg, loc); } /* Add an opcode with an integer argument */ @@ -1252,6 +1253,8 @@ compiler_enter_scope(struct compiler *c, identifier name, u->u_static_attributes = NULL; } + u->u_instr_sequence = (instr_sequence*)_PyInstructionSequence_New(); + /* Push the old compiler_unit on the stack. */ if (c->u) { PyObject *capsule = PyCapsule_New(c->u, CAPSULE_NAME, NULL); @@ -7526,7 +7529,7 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache, if (consts == NULL) { goto error; } - g = instr_sequence_to_cfg(&u->u_instr_sequence); + g = instr_sequence_to_cfg(u->u_instr_sequence); if (g == NULL) { goto error; } @@ -7593,160 +7596,25 @@ optimize_and_assemble(struct compiler *c, int addNone) * a jump target label marking the beginning of a basic block. */ -static int -instructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq) -{ - assert(PyList_Check(instructions)); - - Py_ssize_t num_insts = PyList_GET_SIZE(instructions); - bool *is_target = PyMem_Calloc(num_insts, sizeof(bool)); - if (is_target == NULL) { - return ERROR; - } - for (Py_ssize_t i = 0; i < num_insts; i++) { - PyObject *item = PyList_GET_ITEM(instructions, i); - if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) { - PyErr_SetString(PyExc_ValueError, "expected a 6-tuple"); - goto error; - } - int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0)); - if (PyErr_Occurred()) { - goto error; - } - if (HAS_TARGET(opcode)) { - int oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1)); - if (PyErr_Occurred()) { - goto error; - } - if (oparg < 0 || oparg >= num_insts) { - PyErr_SetString(PyExc_ValueError, "label out of range"); - goto error; - } - is_target[oparg] = true; - } - } - - for (int i = 0; i < num_insts; i++) { - if (is_target[i]) { - if (_PyInstructionSequence_UseLabel(seq, i) < 0) { - goto error; - } - } - PyObject *item = PyList_GET_ITEM(instructions, i); - if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) { - PyErr_SetString(PyExc_ValueError, "expected a 6-tuple"); - goto error; - } - int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0)); - if (PyErr_Occurred()) { - goto error; - } - int oparg; - if (OPCODE_HAS_ARG(opcode)) { - oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1)); - if (PyErr_Occurred()) { - goto error; - } - } - else { - oparg = 0; - } - location loc; - loc.lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 2)); - if (PyErr_Occurred()) { - goto error; - } - loc.end_lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 3)); - if (PyErr_Occurred()) { - goto error; - } - loc.col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 4)); - if (PyErr_Occurred()) { - goto error; - } - loc.end_col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 5)); - if (PyErr_Occurred()) { - goto error; - } - if (_PyInstructionSequence_Addop(seq, opcode, oparg, loc) < 0) { - goto error; - } - } - PyMem_Free(is_target); - return SUCCESS; -error: - PyMem_Free(is_target); - return ERROR; -} - -static cfg_builder* -instructions_to_cfg(PyObject *instructions) -{ - cfg_builder *g = NULL; - instr_sequence seq; - memset(&seq, 0, sizeof(instr_sequence)); - - if (instructions_to_instr_sequence(instructions, &seq) < 0) { - goto error; - } - g = instr_sequence_to_cfg(&seq); - if (g == NULL) { - goto error; - } - PyInstructionSequence_Fini(&seq); - return g; -error: - _PyCfgBuilder_Free(g); - PyInstructionSequence_Fini(&seq); - return NULL; -} static PyObject * -instr_sequence_to_instructions(instr_sequence *seq) +cfg_to_instruction_sequence(cfg_builder *g) { - PyObject *instructions = PyList_New(0); - if (instructions == NULL) { - return NULL; - } - for (int i = 0; i < seq->s_used; i++) { - instruction *instr = &seq->s_instrs[i]; - location loc = instr->i_loc; - PyObject *inst_tuple = Py_BuildValue( - "(iiiiii)", instr->i_opcode, instr->i_oparg, - loc.lineno, loc.end_lineno, - loc.col_offset, loc.end_col_offset); - if (inst_tuple == NULL) { + instr_sequence *seq = (instr_sequence *)_PyInstructionSequence_New(); + if (seq != NULL) { + if (_PyCfg_ToInstructionSequence(g, seq) < 0) { goto error; } - - int res = PyList_Append(instructions, inst_tuple); - Py_DECREF(inst_tuple); - if (res != 0) { + if (_PyInstructionSequence_ApplyLabelMap(seq) < 0) { goto error; } } - return instructions; + return (PyObject*)seq; error: - Py_XDECREF(instructions); + PyInstructionSequence_Fini(seq); return NULL; } -static PyObject * -cfg_to_instructions(cfg_builder *g) -{ - instr_sequence seq; - memset(&seq, 0, sizeof(seq)); - if (_PyCfg_ToInstructionSequence(g, &seq) < 0) { - return NULL; - } - if (_PyInstructionSequence_ApplyLabelMap(&seq) < 0) { - return NULL; - } - PyObject *res = instr_sequence_to_instructions(&seq); - PyInstructionSequence_Fini(&seq); - return res; -} - // C implementation of inspect.cleandoc() // // Difference from inspect.cleandoc(): @@ -7916,13 +7784,8 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, if (_PyInstructionSequence_ApplyLabelMap(INSTR_SEQUENCE(c)) < 0) { return NULL; } - - PyObject *insts = instr_sequence_to_instructions(INSTR_SEQUENCE(c)); - if (insts == NULL) { - goto finally; - } - res = PyTuple_Pack(2, insts, metadata); - Py_DECREF(insts); + /* Allocate a copy of the instruction sequence on the heap */ + res = PyTuple_Pack(2, INSTR_SEQUENCE(c), metadata); finally: Py_XDECREF(metadata); @@ -7933,16 +7796,19 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, } PyObject * -_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts, int nlocals) +_PyCompile_OptimizeCfg(PyObject *seq, PyObject *consts, int nlocals) { - cfg_builder *g = NULL; - PyObject *res = NULL; + if (!_PyInstructionSequence_Check(seq)) { + PyErr_SetString(PyExc_ValueError, "expected an instruction sequence"); + return NULL; + } PyObject *const_cache = PyDict_New(); if (const_cache == NULL) { return NULL; } - g = instructions_to_cfg(instructions); + PyObject *res = NULL; + cfg_builder *g = instr_sequence_to_cfg((instr_sequence*)seq); if (g == NULL) { goto error; } @@ -7951,7 +7817,7 @@ _PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts, int nlocals) nparams, firstlineno) < 0) { goto error; } - res = cfg_to_instructions(g); + res = cfg_to_instruction_sequence(g); error: Py_DECREF(const_cache); _PyCfgBuilder_Free(g); @@ -7962,8 +7828,12 @@ int _PyCfg_JumpLabelsToTargets(cfg_builder *g); PyCodeObject * _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, - PyObject *instructions) + PyObject *seq) { + if (!_PyInstructionSequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, "expected an instruction sequence"); + return NULL; + } cfg_builder *g = NULL; PyCodeObject *co = NULL; instr_sequence optimized_instrs; @@ -7974,7 +7844,7 @@ _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, return NULL; } - g = instructions_to_cfg(instructions); + g = instr_sequence_to_cfg((instr_sequence*)seq); if (g == NULL) { goto error; } diff --git a/Python/instruction_sequence.c b/Python/instruction_sequence.c index 597d2b73d19f302..d843d5f16901b89 100644 --- a/Python/instruction_sequence.c +++ b/Python/instruction_sequence.c @@ -141,6 +141,21 @@ _PyInstructionSequence_InsertInstruction(instr_sequence *seq, int pos, return SUCCESS; } +int +_PyInstructionSequence_AddNested(instr_sequence *seq, instr_sequence *nested) +{ + if (seq->s_nested == NULL) { + seq->s_nested = PyList_New(0); + if (seq->s_nested == NULL) { + return ERROR; + } + } + if (PyList_Append(seq->s_nested, (PyObject*)nested) < 0) { + return ERROR; + } + return SUCCESS; +} + void PyInstructionSequence_Fini(instr_sequence *seq) { PyMem_Free(seq->s_labelmap); @@ -149,3 +164,288 @@ PyInstructionSequence_Fini(instr_sequence *seq) { PyMem_Free(seq->s_instrs); seq->s_instrs = NULL; } + +/*[clinic input] +class InstructionSequenceType "_PyInstructionSequence *" "&_PyInstructionSequence_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=589963e07480390f]*/ + +#include "clinic/instruction_sequence.c.h" + +static _PyInstructionSequence* +inst_seq_create(void) +{ + _PyInstructionSequence *seq; + seq = PyObject_GC_New(_PyInstructionSequence, &_PyInstructionSequence_Type); + if (seq == NULL) { + return NULL; + } + seq->s_instrs = NULL; + seq->s_allocated = 0; + seq->s_used = 0; + seq->s_next_free_label = 0; + seq->s_labelmap = NULL; + seq->s_labelmap_size = 0; + seq->s_nested = NULL; + + PyObject_GC_Track(seq); + return seq; +} + +PyObject* +_PyInstructionSequence_New(void) +{ + _PyInstructionSequence *seq = inst_seq_create(); + if (seq == NULL) { + return NULL; + } + return (PyObject*)seq; +} + +/*[clinic input] +@classmethod +InstructionSequenceType.__new__ as inst_seq_new + +Create a new InstructionSequence object. +[clinic start generated code]*/ + +static PyObject * +inst_seq_new_impl(PyTypeObject *type) +/*[clinic end generated code: output=98881de92c8876f6 input=b393150146849c74]*/ +{ + return (PyObject*)inst_seq_create(); +} + +/*[clinic input] +InstructionSequenceType.use_label + + label: int + +Place label at current location. +[clinic start generated code]*/ + +static PyObject * +InstructionSequenceType_use_label_impl(_PyInstructionSequence *self, + int label) +/*[clinic end generated code: output=4c06bbacb2854755 input=da55f49bb91841f3]*/ + +{ + if (_PyInstructionSequence_UseLabel(self, label) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +/*[clinic input] +InstructionSequenceType.addop + + opcode: int + oparg: int + lineno: int + col_offset: int + end_lineno: int + end_col_offset: int + +Append an instruction. +[clinic start generated code]*/ + +static PyObject * +InstructionSequenceType_addop_impl(_PyInstructionSequence *self, int opcode, + int oparg, int lineno, int col_offset, + int end_lineno, int end_col_offset) +/*[clinic end generated code: output=af0cc22c048dfbf3 input=012762ac88198713]*/ +{ + _Py_SourceLocation loc = {lineno, col_offset, end_lineno, end_col_offset}; + if (_PyInstructionSequence_Addop(self, opcode, oparg, loc) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +/*[clinic input] +InstructionSequenceType.new_label -> int + +Return a new label. +[clinic start generated code]*/ + +static int +InstructionSequenceType_new_label_impl(_PyInstructionSequence *self) +/*[clinic end generated code: output=dcb0589e4f5bf4bd input=c66040b9897bc327]*/ +{ + _PyJumpTargetLabel lbl = _PyInstructionSequence_NewLabel(self); + return lbl.id; +} + +/*[clinic input] +InstructionSequenceType.add_nested + + nested: object + +Add a nested sequence. +[clinic start generated code]*/ + +static PyObject * +InstructionSequenceType_add_nested_impl(_PyInstructionSequence *self, + PyObject *nested) +/*[clinic end generated code: output=14540fad459f7971 input=f2c482568b3b3c0f]*/ +{ + if (!_PyInstructionSequence_Check(nested)) { + PyErr_Format(PyExc_TypeError, + "expected an instruction sequence, not %T", + Py_TYPE(nested)); + return NULL; + } + if (_PyInstructionSequence_AddNested(self, (_PyInstructionSequence*)nested) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + +/*[clinic input] +InstructionSequenceType.get_nested + +Add a nested sequence. +[clinic start generated code]*/ + +static PyObject * +InstructionSequenceType_get_nested_impl(_PyInstructionSequence *self) +/*[clinic end generated code: output=f415112c292630cb input=e429e474c57b95b4]*/ +{ + if (self->s_nested == NULL) { + return PyList_New(0); + } + return Py_NewRef(self->s_nested); +} + +/*[clinic input] +InstructionSequenceType.get_instructions + +Return the instructions as a list of tuples or labels. +[clinic start generated code]*/ + +static PyObject * +InstructionSequenceType_get_instructions_impl(_PyInstructionSequence *self) +/*[clinic end generated code: output=23f4f3f894c301b3 input=fbadb5dadb611291]*/ +{ + if (_PyInstructionSequence_ApplyLabelMap(self) < 0) { + return NULL; + } + PyObject *instructions = PyList_New(0); + if (instructions == NULL) { + return NULL; + } + for (int i = 0; i < self->s_used; i++) { + instruction *instr = &self->s_instrs[i]; + location loc = instr->i_loc; + PyObject *inst_tuple; + + if (OPCODE_HAS_ARG(instr->i_opcode)) { + inst_tuple = Py_BuildValue( + "(iiiiii)", instr->i_opcode, instr->i_oparg, + loc.lineno, loc.end_lineno, + loc.col_offset, loc.end_col_offset); + } + else { + inst_tuple = Py_BuildValue( + "(iOiiii)", instr->i_opcode, Py_None, + loc.lineno, loc.end_lineno, + loc.col_offset, loc.end_col_offset); + } + if (inst_tuple == NULL) { + goto error; + } + + int res = PyList_Append(instructions, inst_tuple); + Py_DECREF(inst_tuple); + if (res != 0) { + goto error; + } + } + return instructions; +error: + Py_XDECREF(instructions); + return NULL; +} + +static PyMethodDef inst_seq_methods[] = { + INSTRUCTIONSEQUENCETYPE_ADDOP_METHODDEF + INSTRUCTIONSEQUENCETYPE_NEW_LABEL_METHODDEF + INSTRUCTIONSEQUENCETYPE_USE_LABEL_METHODDEF + INSTRUCTIONSEQUENCETYPE_ADD_NESTED_METHODDEF + INSTRUCTIONSEQUENCETYPE_GET_NESTED_METHODDEF + INSTRUCTIONSEQUENCETYPE_GET_INSTRUCTIONS_METHODDEF + {NULL, NULL, 0, NULL}, +}; + +static PyMemberDef inst_seq_memberlist[] = { + {NULL} /* Sentinel */ +}; + +static PyGetSetDef inst_seq_getsetters[] = { + {NULL} /* Sentinel */ +}; + +static void +inst_seq_dealloc(_PyInstructionSequence *seq) +{ + PyObject_GC_UnTrack(seq); + Py_TRASHCAN_BEGIN(seq, inst_seq_dealloc) + PyInstructionSequence_Fini(seq); + PyObject_GC_Del(seq); + Py_TRASHCAN_END +} + +static int +inst_seq_traverse(_PyInstructionSequence *seq, visitproc visit, void *arg) +{ + Py_VISIT(seq->s_nested); + return 0; +} + +static int +inst_seq_clear(_PyInstructionSequence *seq) +{ + Py_CLEAR(seq->s_nested); + return 0; +} + +PyTypeObject _PyInstructionSequence_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "InstructionSequence", + sizeof(_PyInstructionSequence), + 0, + (destructor)inst_seq_dealloc, /*tp_dealloc*/ + 0, /*tp_vectorcall_offset*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_as_async*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ + inst_seq_new__doc__, /* tp_doc */ + (traverseproc)inst_seq_traverse, /* tp_traverse */ + (inquiry)inst_seq_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + inst_seq_methods, /* tp_methods */ + inst_seq_memberlist, /* tp_members */ + inst_seq_getsetters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + inst_seq_new, /* tp_new */ +}; diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 65f94e50e1bd7d3..79a8f850ec14512 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -103,6 +103,7 @@ Python/bltinmodule.c - PyZip_Type - Python/context.c - PyContextToken_Type - Python/context.c - PyContextVar_Type - Python/context.c - PyContext_Type - +Python/instruction_sequence.c - _PyInstructionSequence_Type - Python/traceback.c - PyTraceBack_Type - ##----------------------- From deaecb88fa5da68cbffca413c63af95fd99578dd Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 19:31:26 +0300 Subject: [PATCH 030/127] gh-80361: Fix TypeError in email.Message.get_payload() (GH-117994) It was raised when the charset is rfc2231 encoded, e.g.: Content-Type: text/plain; charset*=ansi-x3.4-1968''utf-8 --- Lib/email/message.py | 2 +- Lib/test/test_email/test_email.py | 15 +++++++++++++++ .../2024-04-17-18-00-30.gh-issue-80361.RstWg-.rst | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-17-18-00-30.gh-issue-80361.RstWg-.rst diff --git a/Lib/email/message.py b/Lib/email/message.py index a14cca56b3745aa..46bb8c21942af85 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -294,7 +294,7 @@ def get_payload(self, i=None, decode=False): try: bpayload = payload.encode('ascii', 'surrogateescape') try: - payload = bpayload.decode(self.get_param('charset', 'ascii'), 'replace') + payload = bpayload.decode(self.get_content_charset('ascii'), 'replace') except LookupError: payload = bpayload.decode('ascii', 'replace') except UnicodeEncodeError: diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index d9af05c306eb303..65ddbabcaa19978 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -4181,6 +4181,21 @@ def test_8bit_in_uuencode_body(self): self.assertEqual(msg.get_payload(decode=True), '<,.V Date: Wed, 17 Apr 2024 09:42:56 -0700 Subject: [PATCH 031/127] gh-117657: Fix data races in the method cache in free-threaded builds (#117954) Fix data races in the method cache in free-threaded builds These are technically data races, but I think they're benign (to the extent that that is actually possible). We update cache entries non-atomically but read them atomically from another thread, and there's nothing that establishes a happens-before relationship between the reads and writes that I can see. --- Objects/typeobject.c | 8 +++++--- Tools/tsan/suppressions_free_threading.txt | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1cb53516a9ae76d..6304ee178fd038d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4974,13 +4974,15 @@ is_dunder_name(PyObject *name) static void update_cache(struct type_cache_entry *entry, PyObject *name, unsigned int version_tag, PyObject *value) { - entry->version = version_tag; - entry->value = value; /* borrowed */ + _Py_atomic_store_uint32_relaxed(&entry->version, version_tag); + _Py_atomic_store_ptr_relaxed(&entry->value, value); /* borrowed */ assert(_PyASCIIObject_CAST(name)->hash != -1); OBJECT_STAT_INC_COND(type_cache_collisions, entry->name != Py_None && entry->name != name); // We're releasing this under the lock for simplicity sake because it's always a // exact unicode object or Py_None so it's safe to do so. - Py_SETREF(entry->name, Py_NewRef(name)); + PyObject *old_name = entry->name; + _Py_atomic_store_ptr_relaxed(&entry->name, Py_NewRef(name)); + Py_DECREF(old_name); } #if Py_GIL_DISABLED diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt index 889b62e59b14a60..6e2bdc1ea85cd6c 100644 --- a/Tools/tsan/suppressions_free_threading.txt +++ b/Tools/tsan/suppressions_free_threading.txt @@ -47,5 +47,4 @@ race:set_inheritable race:start_the_world race:tstate_set_detached race:unicode_hash -race:update_cache race:update_cache_gil_disabled From 0d29302155f49d4d5c7fa34a658ad5a97dd013a2 Mon Sep 17 00:00:00 2001 From: mpage Date: Wed, 17 Apr 2024 10:19:28 -0700 Subject: [PATCH 032/127] gh-117657: Quiet erroneous TSAN reports of data races in `_PySeqLock` (#117955) Quiet erroneous TSAN reports of data races in `_PySeqLock` TSAN reports a couple of data races between the compare/exchange in `_PySeqLock_LockWrite` and the non-atomic loads in `_PySeqLock_{Abandon,Unlock}Write`. This is another instance of TSAN incorrectly modeling failed compare/exchange as a write instead of a load. --- Python/lock.c | 6 +++--- Tools/tsan/suppressions_free_threading.txt | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Python/lock.c b/Python/lock.c index 7d1ead585dee6ce..91c66df8fd90935 100644 --- a/Python/lock.c +++ b/Python/lock.c @@ -472,7 +472,7 @@ _PyRWMutex_Unlock(_PyRWMutex *rwmutex) void _PySeqLock_LockWrite(_PySeqLock *seqlock) { - // lock the entry by setting by moving to an odd sequence number + // lock by moving to an odd sequence number uint32_t prev = _Py_atomic_load_uint32_relaxed(&seqlock->sequence); while (1) { if (SEQLOCK_IS_UPDATING(prev)) { @@ -492,14 +492,14 @@ void _PySeqLock_LockWrite(_PySeqLock *seqlock) void _PySeqLock_AbandonWrite(_PySeqLock *seqlock) { - uint32_t new_seq = seqlock->sequence - 1; + uint32_t new_seq = _Py_atomic_load_uint32_relaxed(&seqlock->sequence) - 1; assert(!SEQLOCK_IS_UPDATING(new_seq)); _Py_atomic_store_uint32(&seqlock->sequence, new_seq); } void _PySeqLock_UnlockWrite(_PySeqLock *seqlock) { - uint32_t new_seq = seqlock->sequence + 1; + uint32_t new_seq = _Py_atomic_load_uint32_relaxed(&seqlock->sequence) + 1; assert(!SEQLOCK_IS_UPDATING(new_seq)); _Py_atomic_store_uint32(&seqlock->sequence, new_seq); } diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt index 6e2bdc1ea85cd6c..80191d6c2484e6f 100644 --- a/Tools/tsan/suppressions_free_threading.txt +++ b/Tools/tsan/suppressions_free_threading.txt @@ -26,7 +26,6 @@ race:_PyObject_GC_IS_SHARED race:_PyObject_GC_SET_SHARED race:_PyObject_GC_TRACK race:_PyType_HasFeature -race:_PyType_Lookup race:assign_version_tag race:compare_unicode_unicode race:delitem_common @@ -47,4 +46,3 @@ race:set_inheritable race:start_the_world race:tstate_set_detached race:unicode_hash -race:update_cache_gil_disabled From 353ea0b273b389e075b2ac9687d3e27467b893cd Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Wed, 17 Apr 2024 19:56:59 +0200 Subject: [PATCH 033/127] gh-94673: Fix compiler warning in typeobject.c (#117980) --- Objects/typeobject.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 6304ee178fd038d..ffd66fd8769e1d7 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -116,11 +116,13 @@ type_from_ref(PyObject *ref) /* helpers for for static builtin types */ +#ifndef NDEBUG static inline int static_builtin_index_is_set(PyTypeObject *self) { return self->tp_subclasses != NULL; } +#endif static inline size_t static_builtin_index_get(PyTypeObject *self) From a4b44d39cd6941cc03590fee7538776728bdfd0a Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 17 Apr 2024 19:32:47 +0100 Subject: [PATCH 034/127] gh-114539: Clarify implicit launching of shells by subprocess (GH-117996) --- Doc/library/subprocess.rst | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 49194b82b4cea2c..1cd233173e85e1d 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -754,8 +754,8 @@ Exceptions defined in this module all inherit from :exc:`SubprocessError`. Security Considerations ----------------------- -Unlike some other popen functions, this implementation will never -implicitly call a system shell. This means that all characters, +Unlike some other popen functions, this library will not +implicitly choose to call a system shell. This means that all characters, including shell metacharacters, can safely be passed to child processes. If the shell is invoked explicitly, via ``shell=True``, it is the application's responsibility to ensure that all whitespace and metacharacters are @@ -764,6 +764,14 @@ quoted appropriately to avoid vulnerabilities. On :ref:`some platforms `, it is possible to use :func:`shlex.quote` for this escaping. +On Windows, batch files (:file:`*.bat` or :file:`*.cmd`) may be launched by the +operating system in a system shell regardless of the arguments passed to this +library. This could result in arguments being parsed according to shell rules, +but without any escaping added by Python. If you are intentionally launching a +batch file with arguments from untrusted sources, consider passing +``shell=True`` to allow Python to escape special characters. See :gh:`114539` +for additional discussion. + Popen Objects ------------- From c1d7147c820545bb0a97a072fdba82154fd97ab6 Mon Sep 17 00:00:00 2001 From: neonene <53406459+neonene@users.noreply.github.com> Date: Thu, 18 Apr 2024 05:43:29 +0900 Subject: [PATCH 035/127] gh-117613: Argument Clinic: disallow defining class parameter at module level (#117950) --- Lib/test/test_clinic.py | 9 +++++++++ Tools/clinic/libclinic/dsl_parser.py | 2 ++ 2 files changed, 11 insertions(+) diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 43b629f59f03461..d9e4ce280c68a10 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -2518,6 +2518,15 @@ class m.C "PyObject *" "" p = function.parameters['cls'] self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) + def test_disallow_defining_class_at_module_level(self): + err = "A 'defining_class' parameter cannot be defined at module level." + block = """ + module m + m.func + cls: defining_class + """ + self.expect_failure(block, err, lineno=2) + class ClinicExternalTest(TestCase): maxDiff = None diff --git a/Tools/clinic/libclinic/dsl_parser.py b/Tools/clinic/libclinic/dsl_parser.py index 56c6dca3db3d1d5..cb18374cf07e3c9 100644 --- a/Tools/clinic/libclinic/dsl_parser.py +++ b/Tools/clinic/libclinic/dsl_parser.py @@ -1102,6 +1102,8 @@ def bad_node(self, node: ast.AST) -> None: fail("A 'defining_class' parameter cannot have a default value.") if self.group: fail("A 'defining_class' parameter cannot be in an optional group.") + if self.function.cls is None: + fail("A 'defining_class' parameter cannot be defined at module level.") kind = inspect.Parameter.POSITIONAL_ONLY else: fail("A 'defining_class' parameter, if specified, must either " From 6078f2033ea15a16cf52fe8d644a95a3be72d2e3 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Apr 2024 23:45:35 +0300 Subject: [PATCH 036/127] gh-117968: Add tests for the part of the PyRun family of the C API (GH-117982) Co-authored-by: NGRsoftlab <78017794+NGRsoftlab@users.noreply.github.com> Co-authored-by: Erlend E. Aasland --- Lib/test/test_capi/test_run.py | 104 +++++++++++++++++++++++++++ Modules/Setup.stdlib.in | 2 +- Modules/_testcapi/parts.h | 1 + Modules/_testcapi/run.c | 112 ++++++++++++++++++++++++++++++ Modules/_testcapimodule.c | 13 ++++ PCbuild/_testcapi.vcxproj | 1 + PCbuild/_testcapi.vcxproj.filters | 3 + 7 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 Lib/test/test_capi/test_run.py create mode 100644 Modules/_testcapi/run.c diff --git a/Lib/test/test_capi/test_run.py b/Lib/test/test_capi/test_run.py new file mode 100644 index 000000000000000..bc0ca9dbb7f31e6 --- /dev/null +++ b/Lib/test/test_capi/test_run.py @@ -0,0 +1,104 @@ +import os +import unittest +from collections import UserDict +from test.support import import_helper +from test.support.os_helper import unlink, TESTFN, TESTFN_UNDECODABLE + +NULL = None +_testcapi = import_helper.import_module('_testcapi') +Py_single_input = _testcapi.Py_single_input +Py_file_input = _testcapi.Py_file_input +Py_eval_input = _testcapi.Py_eval_input + + +class CAPITest(unittest.TestCase): + # TODO: Test the following functions: + # + # PyRun_SimpleStringFlags + # PyRun_AnyFileExFlags + # PyRun_SimpleFileExFlags + # PyRun_InteractiveOneFlags + # PyRun_InteractiveOneObject + # PyRun_InteractiveLoopFlags + # PyRun_String (may be a macro) + # PyRun_AnyFile (may be a macro) + # PyRun_AnyFileEx (may be a macro) + # PyRun_AnyFileFlags (may be a macro) + # PyRun_SimpleString (may be a macro) + # PyRun_SimpleFile (may be a macro) + # PyRun_SimpleFileEx (may be a macro) + # PyRun_InteractiveOne (may be a macro) + # PyRun_InteractiveLoop (may be a macro) + # PyRun_File (may be a macro) + # PyRun_FileEx (may be a macro) + # PyRun_FileFlags (may be a macro) + + def test_run_stringflags(self): + # Test PyRun_StringFlags(). + def run(s, *args): + return _testcapi.run_stringflags(s, Py_file_input, *args) + source = b'a\n' + + self.assertIsNone(run(b'a\n', dict(a=1))) + self.assertIsNone(run(b'a\n', dict(a=1), {})) + self.assertIsNone(run(b'a\n', {}, dict(a=1))) + self.assertIsNone(run(b'a\n', {}, UserDict(a=1))) + + self.assertRaises(NameError, run, b'a\n', {}) + self.assertRaises(NameError, run, b'a\n', {}, {}) + self.assertRaises(TypeError, run, b'a\n', dict(a=1), []) + self.assertRaises(TypeError, run, b'a\n', dict(a=1), 1) + + self.assertIsNone(run(b'\xc3\xa4\n', {'\xe4': 1})) + self.assertRaises(SyntaxError, run, b'\xe4\n', {}) + + # CRASHES run(b'a\n', NULL) + # CRASHES run(b'a\n', NULL, {}) + # CRASHES run(b'a\n', NULL, dict(a=1)) + # CRASHES run(b'a\n', UserDict()) + # CRASHES run(b'a\n', UserDict(), {}) + # CRASHES run(b'a\n', UserDict(), dict(a=1)) + + # CRASHES run(NULL, {}) + + def test_run_fileexflags(self): + # Test PyRun_FileExFlags(). + filename = os.fsencode(TESTFN) + with open(filename, 'wb') as fp: + fp.write(b'a\n') + self.addCleanup(unlink, filename) + def run(*args): + return _testcapi.run_fileexflags(filename, Py_file_input, *args) + + self.assertIsNone(run(dict(a=1))) + self.assertIsNone(run(dict(a=1), {})) + self.assertIsNone(run({}, dict(a=1))) + self.assertIsNone(run({}, UserDict(a=1))) + self.assertIsNone(run(dict(a=1), {}, 1)) # closeit = True + + self.assertRaises(NameError, run, {}) + self.assertRaises(NameError, run, {}, {}) + self.assertRaises(TypeError, run, dict(a=1), []) + self.assertRaises(TypeError, run, dict(a=1), 1) + + # CRASHES run(NULL) + # CRASHES run(NULL, {}) + # CRASHES run(NULL, dict(a=1)) + # CRASHES run(UserDict()) + # CRASHES run(UserDict(), {}) + # CRASHES run(UserDict(), dict(a=1)) + + @unittest.skipUnless(TESTFN_UNDECODABLE, 'only works if there are undecodable paths') + def test_run_fileexflags_with_undecodable_filename(self): + run = _testcapi.run_fileexflags + try: + with open(TESTFN_UNDECODABLE, 'wb') as fp: + fp.write(b'a\n') + self.addCleanup(unlink, TESTFN_UNDECODABLE) + except OSError: + self.skipTest('undecodable paths are not supported') + self.assertIsNone(run(TESTFN_UNDECODABLE, Py_file_input, dict(a=1))) + + +if __name__ == '__main__': + unittest.main() diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 26720ef408fe3c4..0b0c1eef0cd8721 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -162,7 +162,7 @@ @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 -@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/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.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 @MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index 2336cc0bc33a856..0e24e44083ea054 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -51,6 +51,7 @@ int _PyTestCapi_Init_Exceptions(PyObject *module); int _PyTestCapi_Init_Code(PyObject *module); int _PyTestCapi_Init_Buffer(PyObject *module); int _PyTestCapi_Init_PyAtomic(PyObject *module); +int _PyTestCapi_Init_Run(PyObject *module); int _PyTestCapi_Init_File(PyObject *module); int _PyTestCapi_Init_Codec(PyObject *module); int _PyTestCapi_Init_Immortal(PyObject *module); diff --git a/Modules/_testcapi/run.c b/Modules/_testcapi/run.c new file mode 100644 index 000000000000000..fa3251c4b5b3100 --- /dev/null +++ b/Modules/_testcapi/run.c @@ -0,0 +1,112 @@ +#include "parts.h" +#include "util.h" + +#include +#include + + +static PyObject * +run_stringflags(PyObject *mod, PyObject *pos_args) +{ + const char *str; + Py_ssize_t size; + int start; + PyObject *globals = NULL; + PyObject *locals = NULL; + PyCompilerFlags flags = _PyCompilerFlags_INIT; + PyCompilerFlags *pflags = NULL; + int cf_flags = 0; + int cf_feature_version = 0; + + if (!PyArg_ParseTuple(pos_args, "z#iO|Oii", + &str, &size, &start, &globals, &locals, + &cf_flags, &cf_feature_version)) { + return NULL; + } + + NULLABLE(globals); + NULLABLE(locals); + if (cf_flags || cf_feature_version) { + flags.cf_flags = cf_flags; + flags.cf_feature_version = cf_feature_version; + pflags = &flags; + } + + return PyRun_StringFlags(str, start, globals, locals, pflags); +} + +static PyObject * +run_fileexflags(PyObject *mod, PyObject *pos_args) +{ + PyObject *result = NULL; + const char *filename = NULL; + Py_ssize_t filename_size; + int start; + PyObject *globals = NULL; + PyObject *locals = NULL; + int closeit = 0; + PyCompilerFlags flags = _PyCompilerFlags_INIT; + PyCompilerFlags *pflags = NULL; + int cf_flags = 0; + int cf_feature_version = 0; + + FILE *fp = NULL; + + if (!PyArg_ParseTuple(pos_args, "z#iO|Oiii", + &filename, &filename_size, &start, &globals, &locals, + &closeit, &cf_flags, &cf_feature_version)) { + return NULL; + } + + NULLABLE(globals); + NULLABLE(locals); + if (cf_flags || cf_feature_version) { + flags.cf_flags = cf_flags; + flags.cf_feature_version = cf_feature_version; + pflags = &flags; + } + + fp = fopen(filename, "r"); + if (fp == NULL) { + PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename); + return NULL; + } + + result = PyRun_FileExFlags(fp, filename, start, globals, locals, closeit, pflags); + +#if !defined(__wasi__) + /* The behavior of fileno() after fclose() is undefined. */ + if (closeit && result && fileno(fp) >= 0) { + PyErr_SetString(PyExc_AssertionError, "File was not closed after excution"); + Py_DECREF(result); + fclose(fp); + return NULL; + } +#endif + if (!closeit && fileno(fp) < 0) { + PyErr_SetString(PyExc_AssertionError, "Bad file descriptor after excution"); + Py_XDECREF(result); + return NULL; + } + + if (!closeit) { + fclose(fp); /* don't need open file any more*/ + } + + return result; +} + +static PyMethodDef test_methods[] = { + {"run_stringflags", run_stringflags, METH_VARARGS}, + {"run_fileexflags", run_fileexflags, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestCapi_Init_Run(PyObject *mod) +{ + if (PyModule_AddFunctions(mod, test_methods) < 0) { + return -1; + } + return 0; +} diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index eff61dd9d833b41..034a30fa47ed30f 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3904,6 +3904,16 @@ PyInit__testcapi(void) PyModule_AddIntConstant(m, "the_number_three", 3); PyModule_AddIntMacro(m, Py_C_RECURSION_LIMIT); + if (PyModule_AddIntMacro(m, Py_single_input)) { + return NULL; + } + if (PyModule_AddIntMacro(m, Py_file_input)) { + return NULL; + } + if (PyModule_AddIntMacro(m, Py_eval_input)) { + return NULL; + } + testcapistate_t *state = get_testcapi_state(m); state->error = PyErr_NewException("_testcapi.error", NULL, NULL); PyModule_AddObject(m, "error", state->error); @@ -3998,6 +4008,9 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_PyAtomic(m) < 0) { return NULL; } + if (_PyTestCapi_Init_Run(m) < 0) { + return NULL; + } if (_PyTestCapi_Init_Hash(m) < 0) { return NULL; } diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index afeb934b71b100b..cc25b6ebd7c6735 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -124,6 +124,7 @@ + diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters index b5bc4f36b2ff852..28c82254d85d4c1 100644 --- a/PCbuild/_testcapi.vcxproj.filters +++ b/PCbuild/_testcapi.vcxproj.filters @@ -105,6 +105,9 @@ Source Files + + Source Files + From b848b944bb4730ab4dcaeb15b0b1713c3f68ec7d Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 18 Apr 2024 09:26:34 +0200 Subject: [PATCH 037/127] gh-117641: Improve the perfornance of posixpath.commonpath() (#117652) --- Lib/posixpath.py | 2 +- .../2024-04-08-19-30-38.gh-issue-117641.oaBGSJ.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-08-19-30-38.gh-issue-117641.oaBGSJ.rst diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 79cda50753e0d20..f1960ddb88e5905 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -550,7 +550,7 @@ def commonpath(paths): split_paths = [path.split(sep) for path in paths] try: - isabs, = set(p[:1] == sep for p in paths) + isabs, = {p.startswith(sep) for p in paths} except ValueError: raise ValueError("Can't mix absolute and relative paths") from None diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-08-19-30-38.gh-issue-117641.oaBGSJ.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-08-19-30-38.gh-issue-117641.oaBGSJ.rst new file mode 100644 index 000000000000000..e313c133b721739 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-08-19-30-38.gh-issue-117641.oaBGSJ.rst @@ -0,0 +1 @@ +Speedup :func:`os.path.commonpath` on Unix. From cd7cf155886cea880c1e80d4313f35f8af210b5e Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Thu, 18 Apr 2024 10:32:32 +0300 Subject: [PATCH 038/127] gh-118023: Fix reference leak (#118025) --- Python/instruction_sequence.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Python/instruction_sequence.c b/Python/instruction_sequence.c index d843d5f16901b89..3a254b2c9def4e8 100644 --- a/Python/instruction_sequence.c +++ b/Python/instruction_sequence.c @@ -158,6 +158,8 @@ _PyInstructionSequence_AddNested(instr_sequence *seq, instr_sequence *nested) void PyInstructionSequence_Fini(instr_sequence *seq) { + Py_XDECREF(seq->s_nested); + PyMem_Free(seq->s_labelmap); seq->s_labelmap = NULL; From 17ed54bc96f0ae2420aa380bab004baa5a18d4d1 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Thu, 18 Apr 2024 10:46:05 +0300 Subject: [PATCH 039/127] Fix two typos in `typeobject.c` (#118024) --- Objects/typeobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index ffd66fd8769e1d7..2f356388785665d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -56,7 +56,7 @@ class object "PyObject *" "&PyBaseObject_Type" #ifdef Py_GIL_DISABLED // There's a global lock for mutation of types. This avoids having to take -// additonal locks while doing various subclass processing which may result +// additional locks while doing various subclass processing which may result // in odd behaviors w.r.t. running with the GIL as the outer type lock could // be released and reacquired during a subclass update if there's contention // on the subclass lock. @@ -10395,7 +10395,7 @@ fixup_slot_dispatchers(PyTypeObject *type) { // This lock isn't strictly necessary because the type has not been // exposed to anyone else yet, but update_ont_slot calls find_name_in_mro - // where we'd like to assert that the tyep is locked. + // where we'd like to assert that the type is locked. BEGIN_TYPE_LOCK() assert(!PyErr_Occurred()); From 468b9aeb922470c26275ce7dda1e6d570a3323f3 Mon Sep 17 00:00:00 2001 From: lyc8503 Date: Thu, 18 Apr 2024 16:45:25 +0800 Subject: [PATCH 040/127] gh-116932: Add note on how to report python documentation theme bugs (GH-117989) --- Doc/bugs.rst | 4 ++++ .../2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst | 1 + 2 files changed, 5 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst diff --git a/Doc/bugs.rst b/Doc/bugs.rst index 908987cf41ff6e4..9aff2f0ff5187df 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -22,6 +22,10 @@ have a suggestion on how to fix it, include that as well. You can also open a discussion item on our `Documentation Discourse forum `_. +If you find a bug in the theme (HTML / CSS / JavaScript) of the +documentation, please submit a bug report on the `python-doc-theme bug +tracker `_. + If you're short on time, you can also email documentation bug reports to docs@python.org (behavioral bugs can be sent to python-list@python.org). 'docs@' is a mailing list run by volunteers; your request will be noticed, diff --git a/Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst b/Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst new file mode 100644 index 000000000000000..41885bcf6634400 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst @@ -0,0 +1 @@ +Add notes on how to report python documentation theme bugs From 1539854c3d03c2d6287a150227ec4bef9de0bc2b Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Thu, 18 Apr 2024 11:01:58 +0200 Subject: [PATCH 041/127] fix formatting of literal in docstring of int.from_bytes and int.to_bytes (#117847) --- Objects/clinic/longobject.c.h | 6 +++--- Objects/longobject.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Objects/clinic/longobject.c.h b/Objects/clinic/longobject.c.h index 4a3d71c6111af57..56bc3864582dcb9 100644 --- a/Objects/clinic/longobject.c.h +++ b/Objects/clinic/longobject.c.h @@ -267,7 +267,7 @@ PyDoc_STRVAR(int_to_bytes__doc__, " the most significant byte is at the beginning of the byte array. If\n" " byteorder is \'little\', the most significant byte is at the end of the\n" " byte array. To request the native byte order of the host system, use\n" -" `sys.byteorder\' as the byte order value. Default is to use \'big\'.\n" +" sys.byteorder as the byte order value. Default is to use \'big\'.\n" " signed\n" " Determines whether two\'s complement is used to represent the integer.\n" " If signed is False and a negative integer is given, an OverflowError\n" @@ -380,7 +380,7 @@ PyDoc_STRVAR(int_from_bytes__doc__, " the most significant byte is at the beginning of the byte array. If\n" " byteorder is \'little\', the most significant byte is at the end of the\n" " byte array. To request the native byte order of the host system, use\n" -" `sys.byteorder\' as the byte order value. Default is to use \'big\'.\n" +" sys.byteorder as the byte order value. Default is to use \'big\'.\n" " signed\n" " Indicates whether two\'s complement is used to represent the integer."); @@ -476,4 +476,4 @@ int_is_integer(PyObject *self, PyObject *Py_UNUSED(ignored)) { return int_is_integer_impl(self); } -/*[clinic end generated code: output=7e6e57246e55911f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2ba2d8dcda9b99da input=a9049054013a1b77]*/ diff --git a/Objects/longobject.c b/Objects/longobject.c index c4ab064d688d674..ce3fd6b711dcd40 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -6291,7 +6291,7 @@ int.to_bytes the most significant byte is at the beginning of the byte array. If byteorder is 'little', the most significant byte is at the end of the byte array. To request the native byte order of the host system, use - `sys.byteorder' as the byte order value. Default is to use 'big'. + sys.byteorder as the byte order value. Default is to use 'big'. * signed as is_signed: bool = False Determines whether two's complement is used to represent the integer. @@ -6304,7 +6304,7 @@ Return an array of bytes representing an integer. static PyObject * int_to_bytes_impl(PyObject *self, Py_ssize_t length, PyObject *byteorder, int is_signed) -/*[clinic end generated code: output=89c801df114050a3 input=d42ecfb545039d71]*/ +/*[clinic end generated code: output=89c801df114050a3 input=a0103d0e9ad85c2b]*/ { int little_endian; PyObject *bytes; @@ -6355,7 +6355,7 @@ int.from_bytes the most significant byte is at the beginning of the byte array. If byteorder is 'little', the most significant byte is at the end of the byte array. To request the native byte order of the host system, use - `sys.byteorder' as the byte order value. Default is to use 'big'. + sys.byteorder as the byte order value. Default is to use 'big'. * signed as is_signed: bool = False Indicates whether two's complement is used to represent the integer. @@ -6366,7 +6366,7 @@ Return the integer represented by the given array of bytes. static PyObject * int_from_bytes_impl(PyTypeObject *type, PyObject *bytes_obj, PyObject *byteorder, int is_signed) -/*[clinic end generated code: output=efc5d68e31f9314f input=33326dccdd655553]*/ +/*[clinic end generated code: output=efc5d68e31f9314f input=2ff527997fe7b0c5]*/ { int little_endian; PyObject *long_obj, *bytes; From f70395786f6da2412d7406606feb64347fc71262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 18 Apr 2024 11:04:20 +0200 Subject: [PATCH 042/127] =?UTF-8?q?gh-90815:=20Document=20bundled=20mimall?= =?UTF-8?q?oc=20in=20What=E2=80=99s=20New=20In=20Python=203.13=20(GH-11781?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Doc/license.rst | 2 ++ Doc/whatsnew/3.13.rst | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/Doc/license.rst b/Doc/license.rst index cbe918bd1acfe30..814b6829f6b2bdc 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -1042,6 +1042,8 @@ https://www.w3.org/TR/xml-c14n2-testcases/ and is distributed under the OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.. _mimalloc-license: + mimalloc -------- diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 86c6a7e93f0a55b..bdde92a2b9f0949 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1621,6 +1621,11 @@ Build Changes * ``wasm32-emscripten`` is no longer a :pep:`11` supported platform. (Contributed by Brett Cannon in :gh:`115192`.) +* Python now bundles the `mimalloc library `__. + It is licensed under the MIT license, see :ref:`mimalloc license `. + The bundled mimalloc has custom changes, see :gh:`113141` for details. + (Contributed by Dino Viehland in :gh:`109914`.) + C API Changes ============= From e32f6e9e4b202ce8759b201f7eafe4982c0eaa41 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 18 Apr 2024 11:09:30 +0100 Subject: [PATCH 043/127] GH-115419: Tidy up tier 2 optimizer. Merge peephole pass into main pass (GH-117997) --- Python/optimizer_analysis.c | 163 +++++++++-------------------------- Python/optimizer_bytecodes.c | 83 ++++++++++++++++-- Python/optimizer_cases.c.h | 55 +++++++++++- 3 files changed, 169 insertions(+), 132 deletions(-) diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index a21679f366a74ed..90444e33568b9d9 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -362,6 +362,30 @@ eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit) } } +/* _PUSH_FRAME/_POP_FRAME's operand can be 0, a PyFunctionObject *, or a + * PyCodeObject *. Retrieve the code object if possible. + */ +static PyCodeObject * +get_code(_PyUOpInstruction *op) +{ + assert(op->opcode == _PUSH_FRAME || op->opcode == _POP_FRAME); + PyCodeObject *co = NULL; + uint64_t operand = op->operand; + if (operand == 0) { + return NULL; + } + if (operand & 1) { + co = (PyCodeObject *)(operand & ~1); + } + else { + PyFunctionObject *func = (PyFunctionObject *)operand; + assert(PyFunction_Check(func)); + co = (PyCodeObject *)func->func_code; + } + assert(PyCode_Check(co)); + return co; +} + /* 1 for success, 0 for not ready, cannot error at the moment. */ static int optimize_uops( @@ -376,6 +400,10 @@ optimize_uops( _Py_UOpsContext context; _Py_UOpsContext *ctx = &context; uint32_t opcode = UINT16_MAX; + int curr_space = 0; + int max_space = 0; + _PyUOpInstruction *first_valid_check_stack = NULL; + _PyUOpInstruction *corresponding_check_stack = NULL; if (_Py_uop_abstractcontext_init(ctx) < 0) { goto out_of_space; @@ -416,8 +444,7 @@ optimize_uops( ctx->frame->stack_pointer = stack_pointer; assert(STACK_LEVEL() >= 0); } - _Py_uop_abstractcontext_fini(ctx); - return trace_len; + Py_UNREACHABLE(); out_of_space: DPRINTF(3, "\n"); @@ -443,9 +470,17 @@ optimize_uops( _Py_uop_abstractcontext_fini(ctx); return 0; done: - /* Cannot optimize further, but there would be no benefit - * in retrying later */ + /* Either reached the end or cannot optimize further, but there + * would be no benefit in retrying later */ _Py_uop_abstractcontext_fini(ctx); + if (first_valid_check_stack != NULL) { + assert(first_valid_check_stack->opcode == _CHECK_STACK_SPACE); + assert(max_space > 0); + assert(max_space <= INT_MAX); + assert(max_space <= INT32_MAX); + first_valid_check_stack->opcode = _CHECK_STACK_SPACE_OPERAND; + first_valid_check_stack->operand = max_space; + } return trace_len; } @@ -532,124 +567,6 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) Py_UNREACHABLE(); } -/* _PUSH_FRAME/_POP_FRAME's operand can be 0, a PyFunctionObject *, or a - * PyCodeObject *. Retrieve the code object if possible. - */ -static PyCodeObject * -get_co(_PyUOpInstruction *op) -{ - assert(op->opcode == _PUSH_FRAME || op->opcode == _POP_FRAME); - PyCodeObject *co = NULL; - uint64_t operand = op->operand; - if (operand == 0) { - return NULL; - } - if (operand & 1) { - co = (PyCodeObject *)(operand & ~1); - } - else { - PyFunctionObject *func = (PyFunctionObject *)operand; - assert(PyFunction_Check(func)); - co = (PyCodeObject *)func->func_code; - } - assert(PyCode_Check(co)); - return co; -} - -static void -peephole_opt(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer, int buffer_size) -{ - PyCodeObject *co = _PyFrame_GetCode(frame); - int curr_space = 0; - int max_space = 0; - _PyUOpInstruction *first_valid_check_stack = NULL; - _PyUOpInstruction *corresponding_check_stack = NULL; - for (int pc = 0; pc < buffer_size; pc++) { - int opcode = buffer[pc].opcode; - switch(opcode) { - case _LOAD_CONST: { - assert(co != NULL); - PyObject *val = PyTuple_GET_ITEM(co->co_consts, buffer[pc].oparg); - buffer[pc].opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE; - buffer[pc].operand = (uintptr_t)val; - break; - } - case _CHECK_PEP_523: { - /* Setting the eval frame function invalidates - * all executors, so no need to check dynamically */ - if (_PyInterpreterState_GET()->eval_frame == NULL) { - buffer[pc].opcode = _NOP; - } - break; - } - case _CHECK_STACK_SPACE: { - assert(corresponding_check_stack == NULL); - corresponding_check_stack = &buffer[pc]; - break; - } - case _PUSH_FRAME: { - assert(corresponding_check_stack != NULL); - co = get_co(&buffer[pc]); - if (co == NULL) { - // should be about to _EXIT_TRACE anyway - goto finish; - } - int framesize = co->co_framesize; - assert(framesize > 0); - curr_space += framesize; - if (curr_space < 0 || curr_space > INT32_MAX) { - // won't fit in signed 32-bit int - goto finish; - } - max_space = curr_space > max_space ? curr_space : max_space; - if (first_valid_check_stack == NULL) { - first_valid_check_stack = corresponding_check_stack; - } - else { - // delete all but the first valid _CHECK_STACK_SPACE - corresponding_check_stack->opcode = _NOP; - } - corresponding_check_stack = NULL; - break; - } - case _POP_FRAME: { - assert(corresponding_check_stack == NULL); - assert(co != NULL); - int framesize = co->co_framesize; - assert(framesize > 0); - assert(framesize <= curr_space); - curr_space -= framesize; - co = get_co(&buffer[pc]); - if (co == NULL) { - // might be impossible, but bailing is still safe - goto finish; - } - break; - } - case _JUMP_TO_TOP: - case _EXIT_TRACE: - goto finish; -#ifdef Py_DEBUG - case _CHECK_STACK_SPACE_OPERAND: { - /* We should never see _CHECK_STACK_SPACE_OPERANDs. - * They are only created at the end of this pass. */ - Py_UNREACHABLE(); - } -#endif - } - } - Py_UNREACHABLE(); -finish: - if (first_valid_check_stack != NULL) { - assert(first_valid_check_stack->opcode == _CHECK_STACK_SPACE); - assert(max_space > 0); - assert(max_space <= INT_MAX); - assert(max_space <= INT32_MAX); - first_valid_check_stack->opcode = _CHECK_STACK_SPACE_OPERAND; - first_valid_check_stack->operand = max_space; - } -} - // 0 - failure, no error raised, just fall back to Tier 1 // -1 - failure, and raise error // > 0 - length of optimized trace @@ -669,8 +586,6 @@ _Py_uop_analyze_and_optimize( return err; } - peephole_opt(frame, buffer, length); - length = optimize_uops( _PyFrame_GetCode(frame), buffer, length, curr_stacklen, dependencies); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index e38428af108893e..f119b8e20719fa9 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -38,12 +38,14 @@ optimize_to_bool( _Py_UopsSymbol **result_ptr); extern void -eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit) +eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit); + +extern PyCodeObject *get_code(_PyUOpInstruction *op); static int dummy_func(void) { - PyCodeObject *code; + PyCodeObject *co; int oparg; _Py_UopsSymbol *flag; _Py_UopsSymbol *left; @@ -54,10 +56,15 @@ dummy_func(void) { _Py_UopsSymbol *top; _Py_UopsSymbol *bottom; _Py_UOpsAbstractFrame *frame; + _Py_UOpsAbstractFrame *new_frame; _Py_UOpsContext *ctx; _PyUOpInstruction *this_instr; _PyBloomFilter *dependencies; int modified; + int curr_space; + int max_space; + _PyUOpInstruction *first_valid_check_stack; + _PyUOpInstruction *corresponding_check_stack; // BEGIN BYTECODES // @@ -393,9 +400,10 @@ dummy_func(void) { } op(_LOAD_CONST, (-- value)) { - // There should be no LOAD_CONST. It should be all - // replaced by peephole_opt. - Py_UNREACHABLE(); + PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg); + int opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE; + REPLACE_OP(this_instr, opcode, 0, (uintptr_t)val); + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, val)); } op(_LOAD_CONST_INLINE, (ptr/4 -- value)) { @@ -590,6 +598,32 @@ dummy_func(void) { frame_pop(ctx); stack_pointer = ctx->frame->stack_pointer; res = retval; + + /* Stack space handling */ + assert(corresponding_check_stack == NULL); + assert(co != NULL); + int framesize = co->co_framesize; + assert(framesize > 0); + assert(framesize <= curr_space); + curr_space -= framesize; + + co = get_code(this_instr); + if (co == NULL) { + // might be impossible, but bailing is still safe + goto done; + } + } + + op(_CHECK_STACK_SPACE, ( --)) { + assert(corresponding_check_stack == NULL); + corresponding_check_stack = this_instr; + } + + op (_CHECK_STACK_SPACE_OPERAND, ( -- )) { + (void)framesize; + /* We should never see _CHECK_STACK_SPACE_OPERANDs. + * They are only created at the end of this pass. */ + Py_UNREACHABLE(); } op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- unused if (0))) { @@ -598,6 +632,29 @@ dummy_func(void) { ctx->frame = new_frame; ctx->curr_frame_depth++; stack_pointer = new_frame->stack_pointer; + co = get_code(this_instr); + if (co == NULL) { + // should be about to _EXIT_TRACE anyway + goto done; + } + + /* Stack space handling */ + int framesize = co->co_framesize; + assert(framesize > 0); + curr_space += framesize; + if (curr_space < 0 || curr_space > INT32_MAX) { + // won't fit in signed 32-bit int + goto done; + } + max_space = curr_space > max_space ? curr_space : max_space; + if (first_valid_check_stack == NULL) { + first_valid_check_stack = corresponding_check_stack; + } + else { + // delete all but the first valid _CHECK_STACK_SPACE + corresponding_check_stack->opcode = _NOP; + } + corresponding_check_stack = NULL; } op(_UNPACK_SEQUENCE, (seq -- values[oparg])) { @@ -662,6 +719,22 @@ dummy_func(void) { } } + op(_CHECK_PEP_523, (--)) { + /* Setting the eval frame function invalidates + * all executors, so no need to check dynamically */ + if (_PyInterpreterState_GET()->eval_frame == NULL) { + REPLACE_OP(this_instr, _NOP, 0 ,0); + } + } + + op(_JUMP_TO_TOP, (--)) { + goto done; + } + + op(_EXIT_TRACE, (--)) { + goto done; + } + // END BYTECODES // diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 209be370c4aa383..50f335e0c8a0a2e 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -46,9 +46,10 @@ case _LOAD_CONST: { _Py_UopsSymbol *value; - // There should be no LOAD_CONST. It should be all - // replaced by peephole_opt. - Py_UNREACHABLE(); + PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg); + int opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE; + REPLACE_OP(this_instr, opcode, 0, (uintptr_t)val); + OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, val)); stack_pointer[0] = value; stack_pointer += 1; break; @@ -597,6 +598,18 @@ frame_pop(ctx); stack_pointer = ctx->frame->stack_pointer; res = retval; + /* Stack space handling */ + assert(corresponding_check_stack == NULL); + assert(co != NULL); + int framesize = co->co_framesize; + assert(framesize > 0); + assert(framesize <= curr_space); + curr_space -= framesize; + co = get_code(this_instr); + if (co == NULL) { + // might be impossible, but bailing is still safe + goto done; + } stack_pointer[0] = res; stack_pointer += 1; break; @@ -1529,6 +1542,11 @@ } case _CHECK_PEP_523: { + /* Setting the eval frame function invalidates + * all executors, so no need to check dynamically */ + if (_PyInterpreterState_GET()->eval_frame == NULL) { + REPLACE_OP(this_instr, _NOP, 0 ,0); + } break; } @@ -1547,6 +1565,8 @@ } case _CHECK_STACK_SPACE: { + assert(corresponding_check_stack == NULL); + corresponding_check_stack = this_instr; break; } @@ -1610,6 +1630,28 @@ ctx->frame = new_frame; ctx->curr_frame_depth++; stack_pointer = new_frame->stack_pointer; + co = get_code(this_instr); + if (co == NULL) { + // should be about to _EXIT_TRACE anyway + goto done; + } + /* Stack space handling */ + int framesize = co->co_framesize; + assert(framesize > 0); + curr_space += framesize; + if (curr_space < 0 || curr_space > INT32_MAX) { + // won't fit in signed 32-bit int + goto done; + } + max_space = curr_space > max_space ? curr_space : max_space; + if (first_valid_check_stack == NULL) { + first_valid_check_stack = corresponding_check_stack; + } + else { + // delete all but the first valid _CHECK_STACK_SPACE + corresponding_check_stack->opcode = _NOP; + } + corresponding_check_stack = NULL; break; } @@ -1899,6 +1941,7 @@ } case _JUMP_TO_TOP: { + goto done; break; } @@ -1907,6 +1950,11 @@ } case _CHECK_STACK_SPACE_OPERAND: { + uint32_t framesize = (uint32_t)this_instr->operand; + (void)framesize; + /* We should never see _CHECK_STACK_SPACE_OPERANDs. + * They are only created at the end of this pass. */ + Py_UNREACHABLE(); break; } @@ -1915,6 +1963,7 @@ } case _EXIT_TRACE: { + goto done; break; } From 0a0756c5edd8c32783a39ef00c47fe4a54deecbc Mon Sep 17 00:00:00 2001 From: lyc8503 Date: Thu, 18 Apr 2024 20:22:18 +0800 Subject: [PATCH 044/127] gh-116932: Remove redundant NEWS entry (#118040) --- .../Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst diff --git a/Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst b/Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst deleted file mode 100644 index 41885bcf6634400..000000000000000 --- a/Misc/NEWS.d/next/Documentation/2024-04-17-22-16-19.gh-issue-116932.lETyxa.rst +++ /dev/null @@ -1 +0,0 @@ -Add notes on how to report python documentation theme bugs From 340a02b590681d4753eef0ff63037d0ecb512271 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 18 Apr 2024 15:20:38 +0200 Subject: [PATCH 045/127] gh-117987: Restore several functions removed in Python 3.13 alpha 1 (GH-117993) Restore these functions removed in Python 3.13 alpha 1: * Py_SetPythonHome() * Py_SetProgramName() * PySys_SetArgvEx() * PySys_SetArgv() --- Doc/c-api/init.rst | 130 ++++++++++++++++++ Doc/data/stable_abi.dat | 4 + Doc/whatsnew/3.13.rst | 14 +- Include/pylifecycle.h | 4 + Include/sysmodule.h | 3 + ...-04-17-16-48-17.gh-issue-117987.zsvNL1.rst | 8 ++ Misc/stable_abi.toml | 4 - Programs/_testembed.c | 2 - Python/pathconfig.c | 6 +- Python/sysmodule.c | 6 +- 10 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2024-04-17-16-48-17.gh-issue-117987.zsvNL1.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 9b98e71ae533ecf..cbc03bfd18ea3c4 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -29,6 +29,8 @@ The following functions can be safely called before Python is initialized: * :c:func:`PyMem_SetAllocator` * :c:func:`PyMem_SetupDebugHooks` * :c:func:`PyObject_SetArenaAllocator` + * :c:func:`Py_SetProgramName` + * :c:func:`Py_SetPythonHome` * :c:func:`PySys_ResetWarnOptions` * Informative functions: @@ -426,6 +428,34 @@ Process-wide parameters ======================= +.. c:function:: void Py_SetProgramName(const wchar_t *name) + + .. index:: + single: Py_Initialize() + single: main() + single: Py_GetPath() + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.program_name` should be used instead, see :ref:`Python + Initialization Configuration `. + + This function should be called before :c:func:`Py_Initialize` is called for + the first time, if it is called at all. It tells the interpreter the value + of the ``argv[0]`` argument to the :c:func:`main` function of the program + (converted to wide characters). + This is used by :c:func:`Py_GetPath` and some other functions below to find + the Python run-time libraries relative to the interpreter executable. The + default value is ``'python'``. The argument should point to a + zero-terminated wide character string in static storage whose contents will not + change for the duration of the program's execution. No code in the Python + interpreter will change the contents of this storage. + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_*` string. + + .. deprecated:: 3.11 + + .. c:function:: wchar_t* Py_GetProgramName() Return the program name set with :c:member:`PyConfig.program_name`, or the default. @@ -627,6 +657,106 @@ Process-wide parameters ``sys.version``. +.. c:function:: void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) + + .. index:: + single: main() + single: Py_FatalError() + single: argv (in module sys) + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.argv`, :c:member:`PyConfig.parse_argv` and + :c:member:`PyConfig.safe_path` should be used instead, see :ref:`Python + Initialization Configuration `. + + Set :data:`sys.argv` based on *argc* and *argv*. These parameters are + similar to those passed to the program's :c:func:`main` function with the + difference that the first entry should refer to the script file to be + executed rather than the executable hosting the Python interpreter. If there + isn't a script that will be run, the first entry in *argv* can be an empty + string. If this function fails to initialize :data:`sys.argv`, a fatal + condition is signalled using :c:func:`Py_FatalError`. + + If *updatepath* is zero, this is all the function does. If *updatepath* + is non-zero, the function also modifies :data:`sys.path` according to the + following algorithm: + + - If the name of an existing script is passed in ``argv[0]``, the absolute + path of the directory where the script is located is prepended to + :data:`sys.path`. + - Otherwise (that is, if *argc* is ``0`` or ``argv[0]`` doesn't point + to an existing file name), an empty string is prepended to + :data:`sys.path`, which is the same as prepending the current working + directory (``"."``). + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_*` string. + + See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` + members of the :ref:`Python Initialization Configuration `. + + .. note:: + It is recommended that applications embedding the Python interpreter + for purposes other than executing a single script pass ``0`` as *updatepath*, + and update :data:`sys.path` themselves if desired. + See `CVE-2008-5983 `_. + + On versions before 3.1.3, you can achieve the same effect by manually + popping the first :data:`sys.path` element after having called + :c:func:`PySys_SetArgv`, for example using:: + + PyRun_SimpleString("import sys; sys.path.pop(0)\n"); + + .. versionadded:: 3.1.3 + + .. XXX impl. doesn't seem consistent in allowing ``0``/``NULL`` for the params; + check w/ Guido. + + .. deprecated:: 3.11 + + +.. c:function:: void PySys_SetArgv(int argc, wchar_t **argv) + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.argv` and :c:member:`PyConfig.parse_argv` should be used + instead, see :ref:`Python Initialization Configuration `. + + This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set + to ``1`` unless the :program:`python` interpreter was started with the + :option:`-I`. + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_*` string. + + See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` + members of the :ref:`Python Initialization Configuration `. + + .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. + + .. deprecated:: 3.11 + + +.. c:function:: void Py_SetPythonHome(const wchar_t *home) + + This API is kept for backward compatibility: setting + :c:member:`PyConfig.home` should be used instead, see :ref:`Python + Initialization Configuration `. + + Set the default "home" directory, that is, the location of the standard + Python libraries. See :envvar:`PYTHONHOME` for the meaning of the + argument string. + + The argument should point to a zero-terminated character string in static + storage whose contents will not change for the duration of the program's + execution. No code in the Python interpreter will change the contents of + this storage. + + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:expr:`wchar_*` string. + + .. deprecated:: 3.11 + + .. c:function:: wchar_t* Py_GetPythonHome() Return the default "home", that is, the value set by diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index aa9022357841941..8c8a378f52bd5d5 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -618,6 +618,8 @@ function,PySys_FormatStdout,3.2,, function,PySys_GetObject,3.2,, function,PySys_GetXOptions,3.7,, function,PySys_ResetWarnOptions,3.2,, +function,PySys_SetArgv,3.2,, +function,PySys_SetArgvEx,3.2,, function,PySys_SetObject,3.2,, function,PySys_WriteStderr,3.2,, function,PySys_WriteStdout,3.2,, @@ -869,6 +871,8 @@ function,Py_NewInterpreter,3.2,, function,Py_NewRef,3.10,, function,Py_ReprEnter,3.2,, function,Py_ReprLeave,3.2,, +function,Py_SetProgramName,3.2,, +function,Py_SetPythonHome,3.2,, function,Py_SetRecursionLimit,3.2,, type,Py_UCS4,3.2,, macro,Py_UNBLOCK_THREADS,3.2,, diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index bdde92a2b9f0949..0ea27a081b2d2df 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -2011,12 +2011,8 @@ Removed * ``PySys_AddWarnOption()``: use :c:member:`PyConfig.warnoptions` instead. * ``PySys_AddXOption()``: use :c:member:`PyConfig.xoptions` instead. * ``PySys_HasWarnOptions()``: use :c:member:`PyConfig.xoptions` instead. - * ``PySys_SetArgvEx()``: set :c:member:`PyConfig.argv` instead. - * ``PySys_SetArgv()``: set :c:member:`PyConfig.argv` instead. * ``PySys_SetPath()``: set :c:member:`PyConfig.module_search_paths` instead. * ``Py_SetPath()``: set :c:member:`PyConfig.module_search_paths` instead. - * ``Py_SetProgramName()``: set :c:member:`PyConfig.program_name` instead. - * ``Py_SetPythonHome()``: set :c:member:`PyConfig.home` instead. * ``Py_SetStandardStreamEncoding()``: set :c:member:`PyConfig.stdio_encoding` instead, and set also maybe :c:member:`PyConfig.legacy_windows_stdio` (on Windows). @@ -2073,6 +2069,16 @@ Pending Removal in Python 3.14 * Creating immutable types (:c:macro:`Py_TPFLAGS_IMMUTABLETYPE`) with mutable bases using the C API. +* Functions to configure the Python initialization, deprecated in Python 3.11: + + * ``PySys_SetArgvEx()``: set :c:member:`PyConfig.argv` instead. + * ``PySys_SetArgv()``: set :c:member:`PyConfig.argv` instead. + * ``Py_SetProgramName()``: set :c:member:`PyConfig.program_name` instead. + * ``Py_SetPythonHome()``: set :c:member:`PyConfig.home` instead. + + The :c:func:`Py_InitializeFromConfig` API should be used with + :c:type:`PyConfig` instead. + * Global configuration variables: * :c:var:`Py_DebugFlag`: use :c:member:`PyConfig.parser_debug` diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index c1e2bc5e3233584..de1bcb1d2cb632b 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -34,8 +34,12 @@ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); /* In pathconfig.c */ +Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); Py_DEPRECATED(3.13) PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); + +Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); Py_DEPRECATED(3.13) PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void); + Py_DEPRECATED(3.13) PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void); Py_DEPRECATED(3.13) PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); Py_DEPRECATED(3.13) PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); diff --git a/Include/sysmodule.h b/Include/sysmodule.h index 7b14f72ee2e4945..5a0af2e1578eb70 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -7,6 +7,9 @@ extern "C" { PyAPI_FUNC(PyObject *) PySys_GetObject(const char *); PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); +Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); + PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) Py_GCC_ATTRIBUTE((format(printf, 1, 2))); PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...) diff --git a/Misc/NEWS.d/next/C API/2024-04-17-16-48-17.gh-issue-117987.zsvNL1.rst b/Misc/NEWS.d/next/C API/2024-04-17-16-48-17.gh-issue-117987.zsvNL1.rst new file mode 100644 index 000000000000000..b4cca946906c70f --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-04-17-16-48-17.gh-issue-117987.zsvNL1.rst @@ -0,0 +1,8 @@ +Restore functions removed in Python 3.13 alpha 1: + +* :c:func:`Py_SetPythonHome` +* :c:func:`Py_SetProgramName` +* :c:func:`PySys_SetArgvEx` +* :c:func:`PySys_SetArgv` + +Patch by Victor Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index ad6f0ee3a5c2123..5c29e98705aeaf0 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -1336,10 +1336,8 @@ added = '3.2' [function.PySys_SetArgv] added = '3.2' - abi_only = true [function.PySys_SetArgvEx] added = '3.2' - abi_only = true [function.PySys_SetObject] added = '3.2' [function.PySys_SetPath] @@ -1672,10 +1670,8 @@ added = '3.2' [function.Py_SetProgramName] added = '3.2' - abi_only = true [function.Py_SetPythonHome] added = '3.2' - abi_only = true [function.Py_SetRecursionLimit] added = '3.2' [function.Py_VaBuildValue] diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 30998bf80f9ce44..d149b6a0c5cd21d 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -16,11 +16,9 @@ // These functions were removed from Python 3.13 API but are still exported // for the stable ABI. We want to test them in this program. -extern void Py_SetProgramName(const wchar_t *program_name); extern void PySys_AddWarnOption(const wchar_t *s); extern void PySys_AddXOption(const wchar_t *s); extern void Py_SetPath(const wchar_t *path); -extern void Py_SetPythonHome(const wchar_t *home); int main_argc; diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 50c60093cd4e329..33abaddc1b5df43 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -251,8 +251,7 @@ Py_SetPath(const wchar_t *path) } -// Removed in Python 3.13 API, but kept for the stable ABI -PyAPI_FUNC(void) +void Py_SetPythonHome(const wchar_t *home) { int has_value = home && home[0]; @@ -275,8 +274,7 @@ Py_SetPythonHome(const wchar_t *home) } -// Removed in Python 3.13 API, but kept for the stable ABI -PyAPI_FUNC(void) +void Py_SetProgramName(const wchar_t *program_name) { int has_value = program_name && program_name[0]; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 7b4a643bccd1ddd..05ee4051a20e18d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -3872,8 +3872,7 @@ make_sys_argv(int argc, wchar_t * const * argv) return list; } -// Removed in Python 3.13 API, but kept for the stable ABI -PyAPI_FUNC(void) +void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) { wchar_t* empty_argv[1] = {L""}; @@ -3917,8 +3916,7 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) } } -// Removed in Python 3.13 API, but kept for the stable ABI -PyAPI_FUNC(void) +void PySys_SetArgv(int argc, wchar_t **argv) { _Py_COMP_DIAG_PUSH From 81a926bd20a8c66646e51b66ef1cfb309b73ebe7 Mon Sep 17 00:00:00 2001 From: Shreyan Avigyan Date: Thu, 18 Apr 2024 20:27:37 +0530 Subject: [PATCH 046/127] gh-87969: Align docs and docstrings with implementation for ctypes' [w]string_at() (#25384) The implementation uses 'ptr' for the name of the first parameter of ctypes.string_at() and ctypes.wstring_at(). Align docs and docstrings with the naming used in the implementation. Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Co-authored-by: Erlend E. Aasland --- Doc/library/ctypes.rst | 16 ++++++++-------- Lib/ctypes/__init__.py | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 9f7d6456e623a22..1deaa3a0f3899f2 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -2077,13 +2077,13 @@ Utility functions Does the same as the C ``sizeof`` operator. -.. function:: string_at(address, size=-1) +.. function:: string_at(ptr, size=-1) - This function returns the C string starting at memory address *address* as a bytes - object. If size is specified, it is used as size, otherwise the string is assumed + Return the byte string at *void \*ptr*. + If *size* is specified, it is used as size, otherwise the string is assumed to be zero-terminated. - .. audit-event:: ctypes.string_at address,size ctypes.string_at + .. audit-event:: ctypes.string_at ptr,size ctypes.string_at .. function:: WinError(code=None, descr=None) @@ -2099,14 +2099,14 @@ Utility functions alias of :exc:`OSError`. -.. function:: wstring_at(address, size=-1) +.. function:: wstring_at(ptr, size=-1) - This function returns the wide character string starting at memory address - *address* as a string. If *size* is specified, it is used as the number of + Return the wide-character string at *void \*ptr*. + If *size* is specified, it is used as the number of characters of the string, otherwise the string is assumed to be zero-terminated. - .. audit-event:: ctypes.wstring_at address,size ctypes.wstring_at + .. audit-event:: ctypes.wstring_at ptr,size ctypes.wstring_at .. _ctypes-data-types: diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index 36b2af7f2a0d667..b7ee46d664ab08f 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -534,9 +534,9 @@ def cast(obj, typ): _string_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr) def string_at(ptr, size=-1): - """string_at(addr[, size]) -> string + """string_at(ptr[, size]) -> string - Return the string at addr.""" + Return the byte string at void *ptr.""" return _string_at(ptr, size) try: @@ -546,9 +546,9 @@ def string_at(ptr, size=-1): else: _wstring_at = PYFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr) def wstring_at(ptr, size=-1): - """wstring_at(addr[, size]) -> string + """wstring_at(ptr[, size]) -> string - Return the string at addr.""" + Return the wide-character string at void *ptr.""" return _wstring_at(ptr, size) From 40f4d641a93b1cba89be4bc7b26cdb481e0450d5 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Thu, 18 Apr 2024 07:59:02 -0700 Subject: [PATCH 047/127] GH-118036: Fix a bug with CALL_STAT_INC (#117933) We were under-counting calls in `_PyEvalFramePushAndInit` because the `CALL_STAT_INC` macro was redefined to a no-op for the Tier 2 interpreter. The fix is not to `#undef` it at all. This results in ~37% more "Frames pushed" reported under "Call stats". --- Python/ceval.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index c0783f7377a8ee1..b88e555ded5c2ee 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -978,8 +978,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int #define STAT_INC(opname, name) ((void)0) #undef STAT_DEC #define STAT_DEC(opname, name) ((void)0) -#undef CALL_STAT_INC -#define CALL_STAT_INC(name) ((void)0) #endif #undef ENABLE_SPECIALIZATION From 94444ea45a86ae46e0c11d1917c43c4c271018cd Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Fri, 19 Apr 2024 00:18:22 +0900 Subject: [PATCH 048/127] gh-112069: Add _PySet_NextEntryRef to be thread-safe. (gh-117990) --- Include/internal/pycore_setobject.h | 9 +++++++- Modules/_abc.c | 2 +- Modules/_pickle.c | 33 +++++++++++++++++------------ Modules/_testinternalcapi/set.c | 10 ++++++--- Objects/dictobject.c | 5 +++-- Objects/listobject.c | 3 +-- Objects/setobject.c | 18 +++++++++++++++- Python/marshal.c | 29 +++++++++++++++---------- Python/pylifecycle.c | 1 + 9 files changed, 76 insertions(+), 34 deletions(-) diff --git a/Include/internal/pycore_setobject.h b/Include/internal/pycore_setobject.h index c4ec3ceb17eba6b..41b351ead25dd18 100644 --- a/Include/internal/pycore_setobject.h +++ b/Include/internal/pycore_setobject.h @@ -8,13 +8,20 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -// Export for '_pickle' shared extension +// Export for '_abc' shared extension PyAPI_FUNC(int) _PySet_NextEntry( PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash); +// Export for '_pickle' shared extension +PyAPI_FUNC(int) _PySet_NextEntryRef( + PyObject *set, + Py_ssize_t *pos, + PyObject **key, + Py_hash_t *hash); + // Export for '_pickle' shared extension PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); diff --git a/Modules/_abc.c b/Modules/_abc.c index ad28035843fd321..f2a523e6f2fc273 100644 --- a/Modules/_abc.c +++ b/Modules/_abc.c @@ -862,7 +862,7 @@ subclasscheck_check_registry(_abc_data *impl, PyObject *subclass, // Make a local copy of the registry to protect against concurrent // modifications of _abc_registry. - PyObject *registry = PySet_New(registry_shared); + PyObject *registry = PyFrozenSet_New(registry_shared); if (registry == NULL) { return -1; } diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 0d83261168185d9..d7ffb04c28c2ac3 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -9,15 +9,16 @@ #endif #include "Python.h" -#include "pycore_bytesobject.h" // _PyBytesWriter -#include "pycore_ceval.h" // _Py_EnterRecursiveCall() -#include "pycore_long.h" // _PyLong_AsByteArray() -#include "pycore_moduleobject.h" // _PyModule_GetState() -#include "pycore_object.h" // _PyNone_Type -#include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_runtime.h" // _Py_ID() -#include "pycore_setobject.h" // _PySet_NextEntry() -#include "pycore_sysmodule.h" // _PySys_GetAttr() +#include "pycore_bytesobject.h" // _PyBytesWriter +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION() +#include "pycore_long.h" // _PyLong_AsByteArray() +#include "pycore_moduleobject.h" // _PyModule_GetState() +#include "pycore_object.h" // _PyNone_Type +#include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_runtime.h" // _Py_ID() +#include "pycore_setobject.h" // _PySet_NextEntry() +#include "pycore_sysmodule.h" // _PySys_GetAttr() #include // strtol() @@ -3413,15 +3414,21 @@ save_set(PickleState *state, PicklerObject *self, PyObject *obj) i = 0; if (_Pickler_Write(self, &mark_op, 1) < 0) return -1; - while (_PySet_NextEntry(obj, &ppos, &item, &hash)) { - Py_INCREF(item); - int err = save(state, self, item, 0); + + int err = 0; + Py_BEGIN_CRITICAL_SECTION(obj); + while (_PySet_NextEntryRef(obj, &ppos, &item, &hash)) { + err = save(state, self, item, 0); Py_CLEAR(item); if (err < 0) - return -1; + break; if (++i == BATCHSIZE) break; } + Py_END_CRITICAL_SECTION(); + if (err < 0) { + return -1; + } if (_Pickler_Write(self, &additems_op, 1) < 0) return -1; if (PySet_GET_SIZE(obj) != set_size) { diff --git a/Modules/_testinternalcapi/set.c b/Modules/_testinternalcapi/set.c index 0305a7885d217c8..01aab03cc109ed4 100644 --- a/Modules/_testinternalcapi/set.c +++ b/Modules/_testinternalcapi/set.c @@ -1,6 +1,7 @@ #include "parts.h" #include "../_testcapi/util.h" // NULLABLE, RETURN_INT +#include "pycore_critical_section.h" #include "pycore_setobject.h" @@ -27,10 +28,13 @@ set_next_entry(PyObject *self, PyObject *args) return NULL; } NULLABLE(set); - - rc = _PySet_NextEntry(set, &pos, &item, &hash); + Py_BEGIN_CRITICAL_SECTION(set); + rc = _PySet_NextEntryRef(set, &pos, &item, &hash); + Py_END_CRITICAL_SECTION(); if (rc == 1) { - return Py_BuildValue("innO", rc, pos, hash, item); + PyObject *ret = Py_BuildValue("innO", rc, pos, hash, item); + Py_DECREF(item); + return ret; } assert(item == UNINITIALIZED_PTR); assert(hash == (Py_hash_t)UNINITIALIZED_SIZE); diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 003a03fd7417025..58f34c32a87ea94 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -2979,8 +2979,9 @@ dict_set_fromkeys(PyInterpreterState *interp, PyDictObject *mp, return NULL; } - while (_PySet_NextEntry(iterable, &pos, &key, &hash)) { - if (insertdict(interp, mp, Py_NewRef(key), hash, Py_NewRef(value))) { + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(iterable); + while (_PySet_NextEntryRef(iterable, &pos, &key, &hash)) { + if (insertdict(interp, mp, key, hash, Py_NewRef(value))) { Py_DECREF(mp); return NULL; } diff --git a/Objects/listobject.c b/Objects/listobject.c index 472c471d9968a46..4eaf20033fa2627 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1287,8 +1287,7 @@ list_extend_set(PyListObject *self, PySetObject *other) Py_hash_t hash; PyObject *key; PyObject **dest = self->ob_item + m; - while (_PySet_NextEntry((PyObject *)other, &setpos, &key, &hash)) { - Py_INCREF(key); + while (_PySet_NextEntryRef((PyObject *)other, &setpos, &key, &hash)) { FT_ATOMIC_STORE_PTR_RELEASE(*dest, key); dest++; } diff --git a/Objects/setobject.c b/Objects/setobject.c index 66ca80e8fc25f96..7af0ae166f9da31 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -2661,7 +2661,6 @@ PySet_Add(PyObject *anyset, PyObject *key) return rv; } -// TODO: Make thread-safe in free-threaded builds int _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash) { @@ -2678,6 +2677,23 @@ _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash return 1; } +int +_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash) +{ + setentry *entry; + + if (!PyAnySet_Check(set)) { + PyErr_BadInternalCall(); + return -1; + } + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set); + if (set_next((PySetObject *)set, pos, &entry) == 0) + return 0; + *key = Py_NewRef(entry->key); + *hash = entry->hash; + return 1; +} + PyObject * PySet_Pop(PyObject *set) { diff --git a/Python/marshal.c b/Python/marshal.c index 21d242bbb9757e8..4274f90206b2405 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -7,12 +7,13 @@ and sharing. */ #include "Python.h" -#include "pycore_call.h" // _PyObject_CallNoArgs() -#include "pycore_code.h" // _PyCode_New() -#include "pycore_hashtable.h" // _Py_hashtable_t -#include "pycore_long.h" // _PyLong_DigitCount -#include "pycore_setobject.h" // _PySet_NextEntry() -#include "marshal.h" // Py_MARSHAL_VERSION +#include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_code.h" // _PyCode_New() +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION() +#include "pycore_hashtable.h" // _Py_hashtable_t +#include "pycore_long.h" // _PyLong_DigitCount +#include "pycore_setobject.h" // _PySet_NextEntry() +#include "marshal.h" // Py_MARSHAL_VERSION #ifdef __APPLE__ # include "TargetConditionals.h" @@ -531,23 +532,29 @@ w_complex_object(PyObject *v, char flag, WFILE *p) return; } Py_ssize_t i = 0; - while (_PySet_NextEntry(v, &pos, &value, &hash)) { + Py_BEGIN_CRITICAL_SECTION(v); + while (_PySet_NextEntryRef(v, &pos, &value, &hash)) { PyObject *dump = _PyMarshal_WriteObjectToString(value, p->version, p->allow_code); if (dump == NULL) { p->error = WFERR_UNMARSHALLABLE; - Py_DECREF(pairs); - return; + Py_DECREF(value); + break; } PyObject *pair = PyTuple_Pack(2, dump, value); Py_DECREF(dump); + Py_DECREF(value); if (pair == NULL) { p->error = WFERR_NOMEMORY; - Py_DECREF(pairs); - return; + break; } PyList_SET_ITEM(pairs, i++, pair); } + Py_END_CRITICAL_SECTION(); + if (p->error == WFERR_UNMARSHALLABLE || p->error == WFERR_NOMEMORY) { + Py_DECREF(pairs); + return; + } assert(i == n); if (PyList_Sort(pairs)) { p->error = WFERR_NOMEMORY; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index efb25878312d852..cc1824634e7a7f5 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2910,6 +2910,7 @@ _Py_DumpExtensionModules(int fd, PyInterpreterState *interp) Py_ssize_t i = 0; PyObject *item; Py_hash_t hash; + // if stdlib_module_names is not NULL, it is always a frozenset. while (_PySet_NextEntry(stdlib_module_names, &i, &item, &hash)) { if (PyUnicode_Check(item) && PyUnicode_Compare(key, item) == 0) From ccdcd1d95a9d6eda4df86811c4539f204beef817 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 18 Apr 2024 19:59:52 +0300 Subject: [PATCH 049/127] gh-117503: Fix test for posixpath.expanduser() when pw_dir ends with / (GH-118056) --- Lib/test/test_posixpath.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py index 604af5bafa7f136..32a20efbb64e1d1 100644 --- a/Lib/test/test_posixpath.py +++ b/Lib/test/test_posixpath.py @@ -351,6 +351,7 @@ def test_expanduser_pwd2(self): for e in pwd.getpwall(): name = e.pw_name home = e.pw_dir + home = home.rstrip('/') or '/' self.assertEqual(posixpath.expanduser('~' + name), home) self.assertEqual(posixpath.expanduser(os.fsencode('~' + name)), os.fsencode(home)) From 8f25cc992021d6ffc62bb110545b97a92f7cb295 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 18 Apr 2024 19:01:55 +0200 Subject: [PATCH 050/127] gh-102402: Fix logging test_relativeCreated_has_higher_precision() leak (#117985) Fix a reference leak in test_relativeCreated_has_higher_precision() of test_logging: don't reimport the logging the logging module. --- Lib/test/test_logging.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 826b7381686dcb9..d8ae607d1d8d014 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -4598,27 +4598,25 @@ def test_msecs_has_no_floating_point_precision_loss(self): self.assertEqual(record.msecs, want) self.assertEqual(record.created, ns / 1e9) + # The test overrides a private attribute + @support.cpython_only def test_relativeCreated_has_higher_precision(self): # See issue gh-102402 ns = 1_677_903_920_000_998_503 # approx. 2023-03-04 04:25:20 UTC offsets_ns = (200, 500, 12_354, 99_999, 1_677_903_456_999_123_456) - orig_modules = import_helper._save_and_remove_modules(['logging']) - try: - with patch("time.time_ns") as patched_ns: - # mock for module import - patched_ns.return_value = ns - import logging - for offset_ns in offsets_ns: - new_ns = ns + offset_ns - # mock for log record creation - patched_ns.return_value = new_ns - record = logging.makeLogRecord({'msg': 'test'}) - self.assertAlmostEqual(record.created, new_ns / 1e9, places=6) - # After PR gh-102412, precision (places) increases from 3 to 7 - self.assertAlmostEqual(record.relativeCreated, offset_ns / 1e6, places=7) - finally: - import_helper._save_and_remove_modules(['logging']) - sys.modules.update(orig_modules) + + with (patch("time.time_ns") as time_ns_mock, + support.swap_attr(logging, '_startTime', ns)): + for offset_ns in offsets_ns: + # mock for log record creation + new_ns = ns + offset_ns + time_ns_mock.return_value = new_ns + + record = logging.makeLogRecord({'msg': 'test'}) + self.assertAlmostEqual(record.created, new_ns / 1e9, places=6) + + # After PR gh-102412, precision (places) increases from 3 to 7 + self.assertAlmostEqual(record.relativeCreated, offset_ns / 1e6, places=7) class TestBufferingFormatter(logging.BufferingFormatter): From 710c01be94ca7b2c96407f41f0e37e24701008b4 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Fri, 19 Apr 2024 06:40:28 +0900 Subject: [PATCH 051/127] gh-112069: Make PySet_GET_SIZE to be atomic safe. (gh-118053) gh-112069: Make PySet_GET_SIZE to be atomic operation --- Include/cpython/setobject.h | 4 ++++ Objects/setobject.c | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Include/cpython/setobject.h b/Include/cpython/setobject.h index 1778c778a05324c..89565cb29212fc1 100644 --- a/Include/cpython/setobject.h +++ b/Include/cpython/setobject.h @@ -62,6 +62,10 @@ typedef struct { (assert(PyAnySet_Check(so)), _Py_CAST(PySetObject*, so)) static inline Py_ssize_t PySet_GET_SIZE(PyObject *so) { +#ifdef Py_GIL_DISABLED + return _Py_atomic_load_ssize_relaxed(&(_PySet_CAST(so)->used)); +#else return _PySet_CAST(so)->used; +#endif } #define PySet_GET_SIZE(so) PySet_GET_SIZE(_PyObject_CAST(so)) diff --git a/Objects/setobject.c b/Objects/setobject.c index 7af0ae166f9da31..d5030cec2d62069 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -2080,7 +2080,6 @@ set_issuperset_impl(PySetObject *so, PyObject *other) Py_RETURN_TRUE; } -// TODO: Make thread-safe in free-threaded builds static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { From 398abdd6fa5b6b15c0570c75321cd7df9573a5b7 Mon Sep 17 00:00:00 2001 From: Rafael Fontenelle Date: Fri, 19 Apr 2024 00:28:12 -0300 Subject: [PATCH 052/127] Use "Contributed by" in a couple of occurrences of 3.12 whatsnew (#118070) --- Doc/whatsnew/3.12.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index f2ef4efcb378bc3..ce3d9ec6a29de8e 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -726,7 +726,7 @@ inspect * Add :func:`inspect.markcoroutinefunction` to mark sync functions that return a :term:`coroutine` for use with :func:`inspect.iscoroutinefunction`. - (Contributed Carlton Gibson in :gh:`99247`.) + (Contributed by Carlton Gibson in :gh:`99247`.) * Add :func:`inspect.getasyncgenstate` and :func:`inspect.getasyncgenlocals` for determining the current state of asynchronous generators. @@ -751,8 +751,8 @@ math (Contributed by Raymond Hettinger in :gh:`100485`.) * Extend :func:`math.nextafter` to include a *steps* argument - for moving up or down multiple steps at a time. - (By Matthias Goergens, Mark Dickinson, and Raymond Hettinger in :gh:`94906`.) + for moving up or down multiple steps at a time. (Contributed by + Matthias Goergens, Mark Dickinson, and Raymond Hettinger in :gh:`94906`.) os -- From a09e47299217fe98615aec8318e13a744307d52a Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Thu, 18 Apr 2024 20:50:09 -0700 Subject: [PATCH 053/127] gh-117535: Change unknown filename of warnings from `sys` to `` (#118018) --- Lib/test/test_warnings/__init__.py | 4 ++-- Lib/warnings.py | 4 ++-- .../Library/2024-04-18-00-35-11.gh-issue-117535.0m6SIM.rst | 1 + Python/_warnings.c | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-18-00-35-11.gh-issue-117535.0m6SIM.rst diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 50b0f3fff04c57b..b768631846e2408 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -489,7 +489,7 @@ def test_stacklevel(self): warning_tests.inner("spam7", stacklevel=9999) self.assertEqual(os.path.basename(w[-1].filename), - "sys") + "") def test_stacklevel_import(self): # Issue #24305: With stacklevel=2, module-level warnings should work. @@ -1388,7 +1388,7 @@ def test_late_resource_warning(self): # Issue #21925: Emitting a ResourceWarning late during the Python # shutdown must be logged. - expected = b"sys:1: ResourceWarning: unclosed file " + expected = b":0: ResourceWarning: unclosed file " # don't import the warnings module # (_warnings will try to import it) diff --git a/Lib/warnings.py b/Lib/warnings.py index 4ad6ad027192e89..20a39d54bf7e6a5 100644 --- a/Lib/warnings.py +++ b/Lib/warnings.py @@ -332,8 +332,8 @@ def warn(message, category=None, stacklevel=1, source=None, raise ValueError except ValueError: globals = sys.__dict__ - filename = "sys" - lineno = 1 + filename = "" + lineno = 0 else: globals = frame.f_globals filename = frame.f_code.co_filename diff --git a/Misc/NEWS.d/next/Library/2024-04-18-00-35-11.gh-issue-117535.0m6SIM.rst b/Misc/NEWS.d/next/Library/2024-04-18-00-35-11.gh-issue-117535.0m6SIM.rst new file mode 100644 index 000000000000000..72423506ccc07ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-18-00-35-11.gh-issue-117535.0m6SIM.rst @@ -0,0 +1 @@ +Change the unknown filename of :mod:`warnings` from ``sys`` to ```` to clarify that it's not a real filename. diff --git a/Python/_warnings.c b/Python/_warnings.c index 4c520252aa12a89..2ba704dcaa79b20 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -894,8 +894,8 @@ setup_context(Py_ssize_t stack_level, if (f == NULL) { globals = interp->sysdict; - *filename = PyUnicode_FromString("sys"); - *lineno = 1; + *filename = PyUnicode_FromString(""); + *lineno = 0; } else { globals = f->f_frame->f_globals; From 60787b8a4e80b9a3e67de781e6803364410ab285 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 18 Apr 2024 21:31:53 -0700 Subject: [PATCH 054/127] Docs: Fix CVE link (#118077) --- Doc/c-api/init.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index cbc03bfd18ea3c4..8725ce085145aad 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -699,7 +699,7 @@ Process-wide parameters It is recommended that applications embedding the Python interpreter for purposes other than executing a single script pass ``0`` as *updatepath*, and update :data:`sys.path` themselves if desired. - See `CVE-2008-5983 `_. + See :cve:`2008-5983`. On versions before 3.1.3, you can achieve the same effect by manually popping the first :data:`sys.path` element after having called From 6099fdf733c2d67c05f0f64c9980fb621741baed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:23:49 -0700 Subject: [PATCH 055/127] build(deps): bump hypothesis from 6.98.15 to 6.100.0 in /Tools (#117416) Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.98.15 to 6.100.0. - [Release notes](https://github.com/HypothesisWorks/hypothesis/releases) - [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.98.15...hypothesis-python-6.100.0) --- updated-dependencies: - dependency-name: hypothesis dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Tools/requirements-hypothesis.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/requirements-hypothesis.txt b/Tools/requirements-hypothesis.txt index 1a45d1c431dd11e..8cfa0df523dd168 100644 --- a/Tools/requirements-hypothesis.txt +++ b/Tools/requirements-hypothesis.txt @@ -1,4 +1,4 @@ # Requirements file for hypothesis that # we use to run our property-based tests in CI. -hypothesis==6.98.15 +hypothesis==6.100.0 From fefd5d97111364afa027ae580c3244f427dda59d Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Fri, 19 Apr 2024 07:36:24 +0200 Subject: [PATCH 056/127] gh-64588: Clarify the difference between mu and xbar in statistics docs (#117333) Thanks Davin Potts for the clarification idea. --- Doc/library/statistics.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst index 873ccd650f45cd0..cc72396964342e5 100644 --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -501,9 +501,9 @@ However, for reading convenience, most of the examples show sorted sequences. variance indicates that the data is spread out; a small variance indicates it is clustered closely around the mean. - If the optional second argument *mu* is given, it is typically the mean of - the *data*. It can also be used to compute the second moment around a - point that is not the mean. If it is missing or ``None`` (the default), + If the optional second argument *mu* is given, it should be the *population* + mean of the *data*. It can also be used to compute the second moment around + a point that is not the mean. If it is missing or ``None`` (the default), the arithmetic mean is automatically calculated. Use this function to calculate the variance from the entire population. To @@ -573,8 +573,8 @@ However, for reading convenience, most of the examples show sorted sequences. the data is spread out; a small variance indicates it is clustered closely around the mean. - If the optional second argument *xbar* is given, it should be the mean of - *data*. If it is missing or ``None`` (the default), the mean is + If the optional second argument *xbar* is given, it should be the *sample* + mean of *data*. If it is missing or ``None`` (the default), the mean is automatically calculated. Use this function when your data is a sample from a population. To calculate @@ -590,8 +590,8 @@ However, for reading convenience, most of the examples show sorted sequences. >>> variance(data) 1.3720238095238095 - If you have already calculated the mean of your data, you can pass it as the - optional second argument *xbar* to avoid recalculation: + If you have already calculated the sample mean of your data, you can pass it + as the optional second argument *xbar* to avoid recalculation: .. doctest:: From d3bd6b5f3f48731715e21fe132b8e65a4e5f6ce8 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 19 Apr 2024 09:25:07 +0100 Subject: [PATCH 057/127] GH-115419: Improve list of escaping functions (GH-118054) --- Include/internal/pycore_opcode_metadata.h | 24 +++++++++++------------ Include/internal/pycore_uop_metadata.h | 24 +++++++++++------------ Python/optimizer_analysis.c | 4 +++- Tools/cases_generator/analyzer.py | 10 ++++++++++ 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index aa87dc413876f07..e75de9d12e0c557 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -984,8 +984,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [CACHE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_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 }, - [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, - [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, + [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_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 }, [CALL_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1000,8 +1000,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, - [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [CALL_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_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_ESCAPES_FLAG }, [CALL_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, @@ -1009,7 +1009,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CLEANUP_THROW] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [COMPARE_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EXIT_FLAG }, [COMPARE_OP_INT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [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_ESCAPES_FLAG }, @@ -1035,7 +1035,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [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 }, - [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, @@ -1103,7 +1103,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [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_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_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_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 }, @@ -1124,18 +1124,18 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [RESERVED] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, - [RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_ESCAPES_FLAG }, + [RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, + [RETURN_VALUE] = { true, INSTR_FMT_IX, 0 }, [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_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 | HAS_ESCAPES_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_DEOPT_FLAG | HAS_EXIT_FLAG }, - [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_EXIT_FLAG }, [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [STORE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG }, [STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, @@ -1146,7 +1146,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [STORE_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [STORE_SUBSCR] = { true, INSTR_FMT_IXC, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [STORE_SUBSCR_DICT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [STORE_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [STORE_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, [SWAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_PURE_FLAG }, [TO_BOOL] = { true, INSTR_FMT_IXC00, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [TO_BOOL_ALWAYS_TRUE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index e5a99421c241e0a..481d7415d19ad1d 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -78,12 +78,12 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_LIST_APPEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG, [_SET_ADD] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_STORE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_STORE_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_STORE_SUBSCR_LIST_INT] = HAS_DEOPT_FLAG, [_STORE_SUBSCR_DICT] = HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DELETE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_POP_FRAME] = HAS_ESCAPES_FLAG, + [_POP_FRAME] = 0, [_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, @@ -109,7 +109,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_LOAD_GLOBAL_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_LOAD_GLOBAL_BUILTINS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_DELETE_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_MAKE_CELL] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_MAKE_CELL] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_DELETE_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_LOAD_FROM_DICT_OR_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_LOAD_DEREF] = HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -147,9 +147,9 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_LOAD_ATTR_CLASS] = HAS_ARG_FLAG | HAS_OPARG_AND_1_FLAG, [_GUARD_DORV_NO_DICT] = HAS_DEOPT_FLAG, [_STORE_ATTR_INSTANCE_VALUE] = 0, - [_STORE_ATTR_SLOT] = HAS_ESCAPES_FLAG, + [_STORE_ATTR_SLOT] = 0, [_COMPARE_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_COMPARE_OP_FLOAT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_COMPARE_OP_FLOAT] = HAS_ARG_FLAG, [_COMPARE_OP_INT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_COMPARE_OP_STR] = HAS_ARG_FLAG, [_IS_OP] = HAS_ARG_FLAG, @@ -192,18 +192,18 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_PEP_523] = HAS_DEOPT_FLAG, [_CHECK_FUNCTION_EXACT_ARGS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_CHECK_STACK_SPACE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, - [_INIT_CALL_PY_EXACT_ARGS_0] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, - [_INIT_CALL_PY_EXACT_ARGS_1] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, - [_INIT_CALL_PY_EXACT_ARGS_2] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, - [_INIT_CALL_PY_EXACT_ARGS_3] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, - [_INIT_CALL_PY_EXACT_ARGS_4] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, - [_INIT_CALL_PY_EXACT_ARGS] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG | HAS_PURE_FLAG, + [_INIT_CALL_PY_EXACT_ARGS_0] = HAS_PURE_FLAG, + [_INIT_CALL_PY_EXACT_ARGS_1] = HAS_PURE_FLAG, + [_INIT_CALL_PY_EXACT_ARGS_2] = HAS_PURE_FLAG, + [_INIT_CALL_PY_EXACT_ARGS_3] = HAS_PURE_FLAG, + [_INIT_CALL_PY_EXACT_ARGS_4] = HAS_PURE_FLAG, + [_INIT_CALL_PY_EXACT_ARGS] = HAS_ARG_FLAG | HAS_PURE_FLAG, [_PUSH_FRAME] = 0, [_CALL_TYPE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_CALL_STR_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_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, + [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_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, diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 90444e33568b9d9..efc5b3c39b6e761 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -543,7 +543,9 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) return pc + 1; default: { - bool needs_ip = false; + /* _PUSH_FRAME doesn't escape or error, but it + * does need the IP for the return address */ + bool needs_ip = opcode == _PUSH_FRAME; if (_PyUop_Flags[opcode] & HAS_ESCAPES_FLAG) { needs_ip = true; may_have_escaped = true; diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index e38ab3c90470397..d17b2b9b024b999 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -358,6 +358,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool: "_PyObject_InlineValues", "_PyDictValues_AddToInsertionOrder", "Py_DECREF", + "Py_XDECREF", "_Py_DECREF_SPECIALIZED", "DECREF_INPUTS_AND_REUSE_FLOAT", "PyUnicode_Append", @@ -365,6 +366,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool: "Py_SIZE", "Py_TYPE", "PyList_GET_ITEM", + "PyList_SET_ITEM", "PyTuple_GET_ITEM", "PyList_GET_SIZE", "PyTuple_GET_SIZE", @@ -400,8 +402,14 @@ def has_error_without_pop(op: parser.InstDef) -> bool: "PySlice_New", "_Py_LeaveRecursiveCallPy", "CALL_STAT_INC", + "STAT_INC", "maybe_lltrace_resume_frame", "_PyUnicode_JoinArray", + "_PyEval_FrameClearAndPop", + "_PyFrame_StackPush", + "PyCell_New", + "PyFloat_AS_DOUBLE", + "_PyFrame_PushUnchecked", ) ESCAPING_FUNCTIONS = ( @@ -427,6 +435,8 @@ def makes_escaping_api_call(instr: parser.InstDef) -> bool: continue if tkn.text in ESCAPING_FUNCTIONS: return True + if tkn.text == "tp_vectorcall": + return True if not tkn.text.startswith("Py") and not tkn.text.startswith("_Py"): continue if tkn.text.endswith("Check"): From 7e6fa5fceddc3f4721c036116c7a11533c8b23b3 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Fri, 19 Apr 2024 09:26:42 +0100 Subject: [PATCH 058/127] GH-116202: Incorporate invalidation check into _START_EXECUTOR. (GH-118044) --- Include/internal/pycore_uop_metadata.h | 2 +- Python/bytecodes.c | 1 + Python/executor_cases.c.h | 4 ++++ Python/optimizer.c | 4 +--- Python/optimizer_analysis.c | 3 +++ 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 481d7415d19ad1d..44ede3e77c68e1e 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -240,7 +240,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_FUNCTION] = HAS_DEOPT_FLAG, [_INTERNAL_INCREMENT_OPT_COUNTER] = 0, [_COLD_EXIT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, - [_START_EXECUTOR] = 0, + [_START_EXECUTOR] = HAS_DEOPT_FLAG, [_FATAL_ERROR] = HAS_ESCAPES_FLAG, [_CHECK_VALIDITY_AND_SET_IP] = HAS_DEOPT_FLAG, [_DEOPT] = 0, diff --git a/Python/bytecodes.c b/Python/bytecodes.c index d6fb66a7be34acd..c34d702f06418e8 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4181,6 +4181,7 @@ dummy_func( #ifndef _Py_JIT current_executor = (_PyExecutorObject*)executor; #endif + DEOPT_IF(!((_PyExecutorObject *)executor)->vm_data.valid); } tier2 op(_FATAL_ERROR, (--)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index a3447da00477ca0..fccff24a4185861 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4137,6 +4137,10 @@ #ifndef _Py_JIT current_executor = (_PyExecutorObject*)executor; #endif + if (!((_PyExecutorObject *)executor)->vm_data.valid) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } break; } diff --git a/Python/optimizer.c b/Python/optimizer.c index 5c69d9d5de92eb8..bb537c9111a51f3 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -1109,8 +1109,6 @@ make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFil assert(next_exit == -1); assert(dest == executor->trace); assert(dest->opcode == _START_EXECUTOR); - dest->oparg = 0; - dest->target = 0; _Py_ExecutorInit(executor, dependencies); #ifdef Py_DEBUG char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); @@ -1314,7 +1312,7 @@ counter_optimize( } _Py_CODEUNIT *target = instr + 1 + _PyOpcode_Caches[JUMP_BACKWARD] - oparg; _PyUOpInstruction buffer[5] = { - { .opcode = _START_EXECUTOR }, + { .opcode = _START_EXECUTOR, .jump_target = 4, .format=UOP_FORMAT_JUMP }, { .opcode = _LOAD_CONST_INLINE_BORROW, .operand = (uintptr_t)self }, { .opcode = _INTERNAL_INCREMENT_OPT_COUNTER }, { .opcode = _EXIT_TRACE, .jump_target = 4, .format=UOP_FORMAT_JUMP }, diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index efc5b3c39b6e761..155f7026b041b0a 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -497,6 +497,9 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) for (int pc = 0; pc < buffer_size; pc++) { int opcode = buffer[pc].opcode; switch (opcode) { + case _START_EXECUTOR: + may_have_escaped = false; + break; case _SET_IP: buffer[pc].opcode = _NOP; last_set_ip = pc; From 4605a197bd84da1a232bd835d8e8e654f2fef220 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 19 Apr 2024 10:41:37 +0200 Subject: [PATCH 059/127] gh-117518: Clarify PyTuple_GetItem() borrowed reference in the doc (GH-117920) --- Doc/c-api/tuple.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst index b3710560ebe7ac9..0d68a360f347f85 100644 --- a/Doc/c-api/tuple.rst +++ b/Doc/c-api/tuple.rst @@ -59,6 +59,12 @@ Tuple Objects Return the object at position *pos* in the tuple pointed to by *p*. If *pos* is negative or out of bounds, return ``NULL`` and set an :exc:`IndexError` exception. + The returned reference is borrowed from the tuple *p* + (that is: it is only valid as long as you hold a reference to *p*). + To get a :term:`strong reference`, use + :c:func:`Py_NewRef(PyTuple_GetItem(...)) ` + or :c:func:`PySequence_GetItem`. + .. c:function:: PyObject* PyTuple_GET_ITEM(PyObject *p, Py_ssize_t pos) From 5d544365742a117027747306e2d4473f3b73d921 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 19 Apr 2024 02:29:23 -0700 Subject: [PATCH 060/127] gh-116935: Document that heap types need to support garbage collection (GH-118021) --- Doc/c-api/typeobj.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index e66ab01878cac05..1105b9433250773 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1034,7 +1034,8 @@ and :c:data:`PyType_Type` effectively act as defaults.) the type, and the type object is INCREF'ed when a new instance is created, and DECREF'ed when an instance is destroyed (this does not apply to instances of subtypes; only the type referenced by the instance's ob_type gets INCREF'ed or - DECREF'ed). + DECREF'ed). Heap types should also :ref:`support garbage collection ` + as they can form a reference cycle with their own module object. **Inheritance:** From 8a01fd7b9bb27c7d284e2f0152713a8619fd34a3 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 19 Apr 2024 11:57:31 +0100 Subject: [PATCH 061/127] gh-115775: Add whatsnew entry about __static_attributes__ (GH-117909) Co-authored-by: Kirill Podoprigora Co-authored-by: Petr Viktorin Co-authored-by: Jelle Zijlstra --- Doc/library/stdtypes.rst | 7 +++++++ Doc/reference/datamodel.rst | 5 +++++ Doc/whatsnew/3.13.rst | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index fc613d4dbe1b5cd..6c13bd015d5691f 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -5542,6 +5542,13 @@ types, where they are relevant. Some of these are not reported by the [, , , ] +.. attribute:: class.__static_attributes__ + + A tuple containing names of attributes of this class which are accessed + through ``self.X`` from any function in its body. + + .. versionadded:: 3.13 + .. _int_max_str_digits: Integer string conversion length limitation diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 6d6395a21f65d27..5e1558362ffaa03 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -970,6 +970,7 @@ A class object can be called (see above) to yield a class instance (see below). single: __doc__ (class attribute) single: __annotations__ (class attribute) single: __type_params__ (class attribute) + single: __static_attributes__ (class attribute) Special attributes: @@ -1000,6 +1001,10 @@ Special attributes: A tuple containing the :ref:`type parameters ` of a :ref:`generic class `. + :attr:`~class.__static_attributes__` + A tuple containing names of attributes of this class which are accessed + through ``self.X`` from any function in its body. + Class instances --------------- diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 0ea27a081b2d2df..cf9853f94872c31 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -115,6 +115,11 @@ Improved Error Messages ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'? +* Classes have a new :attr:`~class.__static_attributes__` attribute, populated by the compiler, + with a tuple of names of attributes of this class which are accessed + through ``self.X`` from any function in its body. (Contributed by Irit Katriel + in :gh:`115775`.) + Incremental Garbage Collection ------------------------------ From 7c6cc00211772cc2afe0bc5e996b6d28f925d133 Mon Sep 17 00:00:00 2001 From: lit Date: Fri, 19 Apr 2024 19:28:46 +0800 Subject: [PATCH 062/127] gh-88035: update doc-string of `epoch` in timemodule.c (GH-118076) Follow #88035, update doc-string of epoch in timemodule.c The epoch is `January 1st, 1970 on all platforms`, according to current documentation. --- Modules/timemodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 2ec5aff235c2936..3211c7530da0b2f 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1896,8 +1896,8 @@ PyDoc_STRVAR(module_doc, There are two standard representations of time. One is the number\n\ of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\ or a floating point number (to represent fractions of seconds).\n\ -The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\ -The actual value can be retrieved by calling gmtime(0).\n\ +The epoch is the point where the time starts, the return value of time.gmtime(0).\n\ +It is January 1, 1970, 00:00:00 (UTC) on all platforms.\n\ \n\ The other representation is a tuple of 9 integers giving local time.\n\ The tuple items are:\n\ From 3e7d990a09f0928050b2b0c85f724c2bce13fcbb Mon Sep 17 00:00:00 2001 From: Rostyslav Lobov <90602764+Motorenger@users.noreply.github.com> Date: Fri, 19 Apr 2024 07:33:13 -0400 Subject: [PATCH 063/127] setobject: remove out of date docstring info (GH-118048) --- Objects/setobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/setobject.c b/Objects/setobject.c index d5030cec2d62069..0d88f4ff922d249 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -2,7 +2,7 @@ /* set object implementation Written and maintained by Raymond D. Hettinger - Derived from Lib/sets.py and Objects/dictobject.c. + Derived from Objects/dictobject.c. The basic lookup function used by all operations. This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4. From 15b3555e4a47ec925c965778a415dc11f0f981fd Mon Sep 17 00:00:00 2001 From: lyc8503 Date: Fri, 19 Apr 2024 19:41:51 +0800 Subject: [PATCH 064/127] gh-116931: Add fileobj parameter check for Tarfile.addfile (GH-117988) Tarfile.addfile now throws an ValueError when the user passes in a non-zero size tarinfo but does not provide a fileobj, instead of writing an incomplete entry. --- Doc/library/tarfile.rst | 10 +++++++--- Lib/tarfile.py | 11 +++++++---- Lib/test/test_tarfile.py | 12 ++++++++++-- .../2024-04-17-21-28-24.gh-issue-116931._AS09h.rst | 1 + 4 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-17-21-28-24.gh-issue-116931._AS09h.rst diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 2134293a0bb0de1..afcad9bf7229341 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -637,11 +637,15 @@ be finalized; only the internally used file object will be closed. See the .. method:: TarFile.addfile(tarinfo, fileobj=None) - Add the :class:`TarInfo` object *tarinfo* to the archive. If *fileobj* is given, - it should be a :term:`binary file`, and - ``tarinfo.size`` bytes are read from it and added to the archive. You can + Add the :class:`TarInfo` object *tarinfo* to the archive. If *tarinfo* represents + a non zero-size regular file, the *fileobj* argument should be a :term:`binary file`, + and ``tarinfo.size`` bytes are read from it and added to the archive. You can create :class:`TarInfo` objects directly, or by using :meth:`gettarinfo`. + .. versionchanged:: 3.13 + + *fileobj* must be given for non-zero-sized regular files. + .. method:: TarFile.gettarinfo(name=None, arcname=None, fileobj=None) diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 149b1c3b1bda285..78bb10c80820d71 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -2214,13 +2214,16 @@ def add(self, name, arcname=None, recursive=True, *, filter=None): self.addfile(tarinfo) def addfile(self, tarinfo, fileobj=None): - """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is - given, it should be a binary file, and tarinfo.size bytes are read - from it and added to the archive. You can create TarInfo objects - directly, or by using gettarinfo(). + """Add the TarInfo object `tarinfo' to the archive. If `tarinfo' represents + a non zero-size regular file, the `fileobj' argument should be a binary file, + and tarinfo.size bytes are read from it and added to the archive. + You can create TarInfo objects directly, or by using gettarinfo(). """ self._check("awx") + if fileobj is None and tarinfo.isreg() and tarinfo.size != 0: + raise ValueError("fileobj not provided for non zero-size regular file") + tarinfo = copy.copy(tarinfo) buf = tarinfo.tobuf(self.format, self.encoding, self.errors) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index f18dcc02b23856f..c2abc7ef9698fb8 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1612,6 +1612,12 @@ def write(self, data): pax_headers={'non': 'empty'}) self.assertFalse(f.closed) + def test_missing_fileobj(self): + with tarfile.open(tmpname, self.mode) as tar: + tarinfo = tar.gettarinfo(tarname) + with self.assertRaises(ValueError): + tar.addfile(tarinfo) + class GzipWriteTest(GzipTest, WriteTest): pass @@ -3283,7 +3289,8 @@ def test_add(self): tar = tarfile.open(fileobj=bio, mode='w', format=tarformat) tarinfo = tar.gettarinfo(tarname) try: - tar.addfile(tarinfo) + with open(tarname, 'rb') as f: + tar.addfile(tarinfo, f) except Exception: if tarformat == tarfile.USTAR_FORMAT: # In the old, limited format, adding might fail for @@ -3298,7 +3305,8 @@ def test_add(self): replaced = tarinfo.replace(**{attr_name: None}) with self.assertRaisesRegex(ValueError, f"{attr_name}"): - tar.addfile(replaced) + with open(tarname, 'rb') as f: + tar.addfile(replaced, f) def test_list(self): # Change some metadata to None, then compare list() output diff --git a/Misc/NEWS.d/next/Library/2024-04-17-21-28-24.gh-issue-116931._AS09h.rst b/Misc/NEWS.d/next/Library/2024-04-17-21-28-24.gh-issue-116931._AS09h.rst new file mode 100644 index 000000000000000..98df8f59f71b762 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-17-21-28-24.gh-issue-116931._AS09h.rst @@ -0,0 +1 @@ +Add parameter *fileobj* check for :func:`tarfile.addfile()` From 1e3e7ce11e3b0fc76e981db85d27019d6d210bbc Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 19 Apr 2024 14:03:44 +0100 Subject: [PATCH 065/127] gh-114053: Fix bad interaction of PEP-695, PEP-563 and ``get_type_hints`` (#118009) Co-authored-by: Jelle Zijlstra --- Doc/library/typing.rst | 4 ++- Lib/test/test_typing.py | 26 +++++++++++++- Lib/test/typinganndata/ann_module695.py | 22 ++++++++++++ Lib/typing.py | 35 ++++++++++++++----- ...-04-17-22-00-15.gh-issue-114053._JBV4D.rst | 4 +++ 5 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 Lib/test/typinganndata/ann_module695.py create mode 100644 Misc/NEWS.d/next/Library/2024-04-17-22-00-15.gh-issue-114053._JBV4D.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 31cf225ebf8fab3..2e71be7eaf8d03d 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -3024,7 +3024,9 @@ Introspection helpers This is often the same as ``obj.__annotations__``. In addition, forward references encoded as string literals are handled by evaluating - them in ``globals`` and ``locals`` namespaces. For a class ``C``, return + them in ``globals``, ``locals`` and (where applicable) + :ref:`type parameter ` namespaces. + For a class ``C``, return a dictionary constructed by merging all the ``__annotations__`` along ``C.__mro__`` in reverse order. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index bae0a8480b994f8..58781e52aca6d83 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -46,7 +46,7 @@ import types from test.support import captured_stderr, cpython_only, infinite_recursion -from test.typinganndata import mod_generics_cache, _typed_dict_helper +from test.typinganndata import ann_module695, mod_generics_cache, _typed_dict_helper CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes' @@ -4641,6 +4641,30 @@ def f(x: X): ... {'x': list[list[ForwardRef('X')]]} ) + def test_pep695_generic_with_future_annotations(self): + hints_for_A = get_type_hints(ann_module695.A) + A_type_params = ann_module695.A.__type_params__ + self.assertIs(hints_for_A["x"], A_type_params[0]) + self.assertEqual(hints_for_A["y"].__args__[0], Unpack[A_type_params[1]]) + self.assertIs(hints_for_A["z"].__args__[0], A_type_params[2]) + + hints_for_B = get_type_hints(ann_module695.B) + self.assertEqual(hints_for_B.keys(), {"x", "y", "z"}) + self.assertEqual( + set(hints_for_B.values()) ^ set(ann_module695.B.__type_params__), + set() + ) + + hints_for_generic_function = get_type_hints(ann_module695.generic_function) + func_t_params = ann_module695.generic_function.__type_params__ + self.assertEqual( + hints_for_generic_function.keys(), {"x", "y", "z", "zz", "return"} + ) + self.assertIs(hints_for_generic_function["x"], func_t_params[0]) + self.assertEqual(hints_for_generic_function["y"], Unpack[func_t_params[1]]) + self.assertIs(hints_for_generic_function["z"].__origin__, func_t_params[2]) + self.assertIs(hints_for_generic_function["zz"].__origin__, func_t_params[2]) + def test_extended_generic_rules_subclassing(self): class T1(Tuple[T, KT]): ... class T2(Tuple[T, ...]): ... diff --git a/Lib/test/typinganndata/ann_module695.py b/Lib/test/typinganndata/ann_module695.py new file mode 100644 index 000000000000000..2ede9fe382564f1 --- /dev/null +++ b/Lib/test/typinganndata/ann_module695.py @@ -0,0 +1,22 @@ +from __future__ import annotations +from typing import Callable + + +class A[T, *Ts, **P]: + x: T + y: tuple[*Ts] + z: Callable[P, str] + + +class B[T, *Ts, **P]: + T = int + Ts = str + P = bytes + x: T + y: Ts + z: P + + +def generic_function[T, *Ts, **P]( + x: T, *y: *Ts, z: P.args, zz: P.kwargs +) -> None: ... diff --git a/Lib/typing.py b/Lib/typing.py index 231492cdcc01cfe..a0b68f593ca0d91 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -399,7 +399,8 @@ def inner(*args, **kwds): return decorator -def _eval_type(t, globalns, localns, recursive_guard=frozenset()): + +def _eval_type(t, globalns, localns, type_params, *, recursive_guard=frozenset()): """Evaluate all forward references in the given type t. For use of globalns and localns see the docstring for get_type_hints(). @@ -407,7 +408,7 @@ def _eval_type(t, globalns, localns, recursive_guard=frozenset()): ForwardRef. """ if isinstance(t, ForwardRef): - return t._evaluate(globalns, localns, recursive_guard) + return t._evaluate(globalns, localns, type_params, recursive_guard=recursive_guard) if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)): if isinstance(t, GenericAlias): args = tuple( @@ -421,7 +422,13 @@ def _eval_type(t, globalns, localns, recursive_guard=frozenset()): t = t.__origin__[args] if is_unpacked: t = Unpack[t] - ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__args__) + + ev_args = tuple( + _eval_type( + a, globalns, localns, type_params, recursive_guard=recursive_guard + ) + for a in t.__args__ + ) if ev_args == t.__args__: return t if isinstance(t, GenericAlias): @@ -974,7 +981,7 @@ def __init__(self, arg, is_argument=True, module=None, *, is_class=False): self.__forward_is_class__ = is_class self.__forward_module__ = module - def _evaluate(self, globalns, localns, recursive_guard): + def _evaluate(self, globalns, localns, type_params, *, recursive_guard): if self.__forward_arg__ in recursive_guard: return self if not self.__forward_evaluated__ or localns is not globalns: @@ -988,14 +995,25 @@ def _evaluate(self, globalns, localns, recursive_guard): globalns = getattr( sys.modules.get(self.__forward_module__, None), '__dict__', globalns ) + if type_params: + # "Inject" type parameters into the local namespace + # (unless they are shadowed by assignments *in* the local namespace), + # as a way of emulating annotation scopes when calling `eval()` + locals_to_pass = {param.__name__: param for param in type_params} | localns + else: + locals_to_pass = localns type_ = _type_check( - eval(self.__forward_code__, globalns, localns), + eval(self.__forward_code__, globalns, locals_to_pass), "Forward references must evaluate to types.", is_argument=self.__forward_is_argument__, allow_special_forms=self.__forward_is_class__, ) self.__forward_value__ = _eval_type( - type_, globalns, localns, recursive_guard | {self.__forward_arg__} + type_, + globalns, + localns, + type_params, + recursive_guard=(recursive_guard | {self.__forward_arg__}), ) self.__forward_evaluated__ = True return self.__forward_value__ @@ -2334,7 +2352,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): value = type(None) if isinstance(value, str): value = ForwardRef(value, is_argument=False, is_class=True) - value = _eval_type(value, base_globals, base_locals) + value = _eval_type(value, base_globals, base_locals, base.__type_params__) hints[name] = value return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()} @@ -2360,6 +2378,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): raise TypeError('{!r} is not a module, class, method, ' 'or function.'.format(obj)) hints = dict(hints) + type_params = getattr(obj, "__type_params__", ()) for name, value in hints.items(): if value is None: value = type(None) @@ -2371,7 +2390,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): is_argument=not isinstance(obj, types.ModuleType), is_class=False, ) - hints[name] = _eval_type(value, globalns, localns) + hints[name] = _eval_type(value, globalns, localns, type_params) return hints if include_extras else {k: _strip_annotations(t) for k, t in hints.items()} diff --git a/Misc/NEWS.d/next/Library/2024-04-17-22-00-15.gh-issue-114053._JBV4D.rst b/Misc/NEWS.d/next/Library/2024-04-17-22-00-15.gh-issue-114053._JBV4D.rst new file mode 100644 index 000000000000000..827b2d656b4d385 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-17-22-00-15.gh-issue-114053._JBV4D.rst @@ -0,0 +1,4 @@ +Fix erroneous :exc:`NameError` when calling :func:`typing.get_type_hints` on +a class that made use of :pep:`695` type parameters in a module that had +``from __future__ import annotations`` at the top of the file. Patch by Alex +Waygood. From 8d4a244f1516dcde23becc2a273d30c202237598 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Fri, 19 Apr 2024 18:38:13 +0300 Subject: [PATCH 066/127] gh-118079: Fix ``requires_singlephase_init`` helper (#118081) Before this PR tests decorated with a `requires_singlephase_init` helper did not run because of an incorrect call to the `requires_gil_enabled` helper. --- Lib/test/test_import/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 4726619b08edc4f..469d1fbe59aaa2d 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -159,9 +159,8 @@ def meth(self, _meth=meth): finally: restore__testsinglephase() meth = cpython_only(meth) - # gh-117649: free-threaded build does not currently support single-phase - # init modules in subinterpreters. - meth = requires_gil_enabled(meth) + msg = "gh-117694: free-threaded build does not currently support single-phase init modules in sub-interpreters" + meth = requires_gil_enabled(msg)(meth) return unittest.skipIf(_testsinglephase is None, 'test requires _testsinglephase module')(meth) From 1e4a4c4897d0f45b1f594bc429284c82efe49188 Mon Sep 17 00:00:00 2001 From: Dino Viehland Date: Fri, 19 Apr 2024 09:25:08 -0700 Subject: [PATCH 067/127] gh-117657: use relaxed loads for checking dict keys immortality (#118067) Use relaxed load to check if dictkeys are immortal --- Objects/dictobject.c | 4 ++-- Tools/tsan/suppressions_free_threading.txt | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 58f34c32a87ea94..c3516dff9737455 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -441,7 +441,7 @@ static void free_keys_object(PyDictKeysObject *keys, bool use_qsbr); static inline void dictkeys_incref(PyDictKeysObject *dk) { - if (dk->dk_refcnt == _Py_IMMORTAL_REFCNT) { + if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_IMMORTAL_REFCNT) { return; } #ifdef Py_REF_DEBUG @@ -453,7 +453,7 @@ dictkeys_incref(PyDictKeysObject *dk) static inline void dictkeys_decref(PyInterpreterState *interp, PyDictKeysObject *dk, bool use_qsbr) { - if (dk->dk_refcnt == _Py_IMMORTAL_REFCNT) { + if (FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_refcnt) == _Py_IMMORTAL_REFCNT) { return; } assert(dk->dk_refcnt > 0); diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt index 80191d6c2484e6f..1408103ba80f96f 100644 --- a/Tools/tsan/suppressions_free_threading.txt +++ b/Tools/tsan/suppressions_free_threading.txt @@ -29,8 +29,6 @@ race:_PyType_HasFeature race:assign_version_tag race:compare_unicode_unicode race:delitem_common -race:dictkeys_decref -race:dictkeys_incref race:dictresize race:gc_collect_main race:gc_restore_tid From 2aa11cca115add03f39cb6cd7299135ecf4d4d82 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Fri, 19 Apr 2024 21:25:54 +0300 Subject: [PATCH 068/127] gh-118100: Improve links in `ast.rst` (#118101) Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Doc/library/ast.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index d10f3f275c0eafe..8d407321092eef1 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -2536,7 +2536,8 @@ to stdout. Otherwise, the content is read from stdin. code that generated them. This is helpful for tools that make source code transformations. - `leoAst.py `_ unifies the + `leoAst.py `_ + unifies the token-based and parse-tree-based views of python programs by inserting two-way links between tokens and ast nodes. @@ -2548,4 +2549,4 @@ to stdout. Otherwise, the content is read from stdin. `Parso `_ is a Python parser that supports error recovery and round-trip parsing for different Python versions (in multiple Python versions). Parso is also able to list multiple syntax errors - in your python file. + in your Python file. From ab99438900c26bdbbdfb411be43d1493f3b00ab7 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sat, 20 Apr 2024 02:56:33 +0800 Subject: [PATCH 069/127] gh-114099: Modify preprocessor symbol usage to support older macOS SDKs (GH-118073) Co-authored-by: Joshua Root jmr@macports.org --- .../macOS/2024-04-19-08-40-00.gh-issue-114099._iDfrQ.rst | 1 + Misc/platform_triplet.c | 8 +++++--- Modules/_testexternalinspection.c | 4 ++++ Python/marshal.c | 3 ++- 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/macOS/2024-04-19-08-40-00.gh-issue-114099._iDfrQ.rst diff --git a/Misc/NEWS.d/next/macOS/2024-04-19-08-40-00.gh-issue-114099._iDfrQ.rst b/Misc/NEWS.d/next/macOS/2024-04-19-08-40-00.gh-issue-114099._iDfrQ.rst new file mode 100644 index 000000000000000..f9af0629ed94344 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2024-04-19-08-40-00.gh-issue-114099._iDfrQ.rst @@ -0,0 +1 @@ +iOS preprocessor symbol usage was made compatible with older macOS SDKs. diff --git a/Misc/platform_triplet.c b/Misc/platform_triplet.c index 06b03bfa9a266a3..ec0857a4a998c0b 100644 --- a/Misc/platform_triplet.c +++ b/Misc/platform_triplet.c @@ -246,8 +246,9 @@ PLATFORM_TRIPLET=i386-gnu # endif #elif defined(__APPLE__) # include "TargetConditionals.h" -# if TARGET_OS_IOS -# if TARGET_OS_SIMULATOR +// Older macOS SDKs do not define TARGET_OS_* +# if defined(TARGET_OS_IOS) && TARGET_OS_IOS +# if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR # if __x86_64__ PLATFORM_TRIPLET=x86_64-iphonesimulator # else @@ -256,7 +257,8 @@ PLATFORM_TRIPLET=arm64-iphonesimulator # else PLATFORM_TRIPLET=arm64-iphoneos # endif -# elif TARGET_OS_OSX +// Older macOS SDKs do not define TARGET_OS_OSX +# elif !defined(TARGET_OS_OSX) || TARGET_OS_OSX PLATFORM_TRIPLET=darwin # else # error unknown Apple platform diff --git a/Modules/_testexternalinspection.c b/Modules/_testexternalinspection.c index bd77f0cd0f1fc79..e2f96cdad5c58ef 100644 --- a/Modules/_testexternalinspection.c +++ b/Modules/_testexternalinspection.c @@ -17,6 +17,10 @@ #if defined(__APPLE__) # include +// Older macOS SDKs do not define TARGET_OS_OSX +# if !defined(TARGET_OS_OSX) +# define TARGET_OS_OSX 1 +# endif # if TARGET_OS_OSX # include # include diff --git a/Python/marshal.c b/Python/marshal.c index 4274f90206b2405..4bd8bb1d3a9308f 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -42,7 +42,8 @@ module marshal #elif defined(__wasi__) # define MAX_MARSHAL_STACK_DEPTH 1500 // TARGET_OS_IPHONE covers any non-macOS Apple platform. -#elif defined(__APPLE__) && TARGET_OS_IPHONE +// It won't be defined on older macOS SDKs +#elif defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE # define MAX_MARSHAL_STACK_DEPTH 1500 #else # define MAX_MARSHAL_STACK_DEPTH 2000 From b624490deedc37d02e5f29d19ff5e222df3a64dd Mon Sep 17 00:00:00 2001 From: Noah Kim Date: Fri, 19 Apr 2024 15:19:12 -0400 Subject: [PATCH 070/127] Fix a typo in dictobject.c documentation (#117515) --- Objects/dictobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/dictobject.c b/Objects/dictobject.c index c3516dff9737455..4e696419eb5eb0a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1876,7 +1876,7 @@ actually be smaller than the old one. If a table is split (its keys and hashes are shared, its values are not), then the values are temporarily copied into the table, it is resized as a combined table, then the me_value slots in the old table are NULLed out. -After resizing a table is always combined. +After resizing, a table is always combined. This function supports: - Unicode split -> Unicode combined or Generic From b45af00bad3449b85c8f54ba7a9474ca1f52de69 Mon Sep 17 00:00:00 2001 From: Dino Viehland Date: Fri, 19 Apr 2024 14:21:01 -0700 Subject: [PATCH 071/127] [gh-117657] _Py_MergeZeroLocalRefcount isn't loading ob_ref_shared with strong enough semantics (#118111) Use acquire for load of ob_ref_shared --- Objects/object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/object.c b/Objects/object.c index 214e7c5b567928f..73a1927263cdcbd 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -374,7 +374,7 @@ _Py_MergeZeroLocalRefcount(PyObject *op) assert(op->ob_ref_local == 0); _Py_atomic_store_uintptr_relaxed(&op->ob_tid, 0); - Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared); + Py_ssize_t shared = _Py_atomic_load_ssize_acquire(&op->ob_ref_shared); if (shared == 0) { // Fast-path: shared refcount is zero (including flags) _Py_Dealloc(op); From 07525c9a85e7fa04db565c6e6e6605ff6099dcb7 Mon Sep 17 00:00:00 2001 From: Dino Viehland Date: Fri, 19 Apr 2024 14:47:42 -0700 Subject: [PATCH 072/127] gh-116818: Make `sys.settrace`, `sys.setprofile`, and monitoring thread-safe (#116775) Makes sys.settrace, sys.setprofile, and monitoring generally thread-safe. Mostly uses a stop-the-world approach and synchronization around the code object's _co_instrumentation_version. There may be a little bit of extra synchronization around the monitoring data that's required to be TSAN clean. --- Include/cpython/pyatomic.h | 8 + Include/cpython/pyatomic_gcc.h | 8 + Include/cpython/pyatomic_msc.h | 25 ++ Include/cpython/pyatomic_std.h | 16 ++ Include/internal/pycore_ceval_state.h | 1 + Include/internal/pycore_gc.h | 2 +- .../internal/pycore_pyatomic_ft_wrappers.h | 14 ++ Lib/test/test_free_threading/__init__.py | 7 + .../test_free_threading/test_monitoring.py | 232 ++++++++++++++++++ Makefile.pre.in | 1 + Python/bytecodes.c | 17 +- Python/ceval.c | 1 + Python/executor_cases.c.h | 2 +- Python/generated_cases.c.h | 18 +- Python/instrumentation.c | 141 +++++++++-- Python/legacy_tracing.c | 94 ++++--- Python/pystate.c | 1 + Tools/jit/template.c | 1 + 18 files changed, 528 insertions(+), 61 deletions(-) create mode 100644 Lib/test/test_free_threading/__init__.py create mode 100644 Lib/test/test_free_threading/test_monitoring.py diff --git a/Include/cpython/pyatomic.h b/Include/cpython/pyatomic.h index c3e132d3877ca51..69083f1d9dd0c23 100644 --- a/Include/cpython/pyatomic.h +++ b/Include/cpython/pyatomic.h @@ -465,10 +465,16 @@ _Py_atomic_store_ullong_relaxed(unsigned long long *obj, static inline void * _Py_atomic_load_ptr_acquire(const void *obj); +static inline uintptr_t +_Py_atomic_load_uintptr_acquire(const uintptr_t *obj); + // Stores `*obj = value` (release operation) static inline void _Py_atomic_store_ptr_release(void *obj, void *value); +static inline void +_Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value); + static inline void _Py_atomic_store_ssize_release(Py_ssize_t *obj, Py_ssize_t value); @@ -491,6 +497,8 @@ static inline Py_ssize_t _Py_atomic_load_ssize_acquire(const Py_ssize_t *obj); + + // --- _Py_atomic_fence ------------------------------------------------------ // Sequential consistency fence. C11 fences have complex semantics. When diff --git a/Include/cpython/pyatomic_gcc.h b/Include/cpython/pyatomic_gcc.h index 0b40f81bd8736de..af78a94c736545f 100644 --- a/Include/cpython/pyatomic_gcc.h +++ b/Include/cpython/pyatomic_gcc.h @@ -492,10 +492,18 @@ static inline void * _Py_atomic_load_ptr_acquire(const void *obj) { return (void *)__atomic_load_n((void **)obj, __ATOMIC_ACQUIRE); } +static inline uintptr_t +_Py_atomic_load_uintptr_acquire(const uintptr_t *obj) +{ return (uintptr_t)__atomic_load_n((uintptr_t *)obj, __ATOMIC_ACQUIRE); } + static inline void _Py_atomic_store_ptr_release(void *obj, void *value) { __atomic_store_n((void **)obj, value, __ATOMIC_RELEASE); } +static inline void +_Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); } + static inline void _Py_atomic_store_int_release(int *obj, int value) { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } diff --git a/Include/cpython/pyatomic_msc.h b/Include/cpython/pyatomic_msc.h index 3205e253b285466..212cd7817d01c52 100644 --- a/Include/cpython/pyatomic_msc.h +++ b/Include/cpython/pyatomic_msc.h @@ -914,6 +914,18 @@ _Py_atomic_load_ptr_acquire(const void *obj) #endif } +static inline uintptr_t +_Py_atomic_load_uintptr_acquire(const uintptr_t *obj) +{ +#if defined(_M_X64) || defined(_M_IX86) + return *(uintptr_t volatile *)obj; +#elif defined(_M_ARM64) + return (uintptr_t)__ldar64((unsigned __int64 volatile *)obj); +#else +# error "no implementation of _Py_atomic_load_uintptr_acquire" +#endif +} + static inline void _Py_atomic_store_ptr_release(void *obj, void *value) { @@ -926,6 +938,19 @@ _Py_atomic_store_ptr_release(void *obj, void *value) #endif } +static inline void +_Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value) +{ +#if defined(_M_X64) || defined(_M_IX86) + *(uintptr_t volatile *)obj = value; +#elif defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(unsigned __int64); + __stlr64((unsigned __int64 volatile *)obj, (unsigned __int64)value); +#else +# error "no implementation of _Py_atomic_store_uintptr_release" +#endif +} + static inline void _Py_atomic_store_int_release(int *obj, int value) { diff --git a/Include/cpython/pyatomic_std.h b/Include/cpython/pyatomic_std.h index ef34bb0b77dfe55..6a77eae536d8dde 100644 --- a/Include/cpython/pyatomic_std.h +++ b/Include/cpython/pyatomic_std.h @@ -863,6 +863,14 @@ _Py_atomic_load_ptr_acquire(const void *obj) memory_order_acquire); } +static inline uintptr_t +_Py_atomic_load_uintptr_acquire(const uintptr_t *obj) +{ + _Py_USING_STD; + return atomic_load_explicit((const _Atomic(uintptr_t)*)obj, + memory_order_acquire); +} + static inline void _Py_atomic_store_ptr_release(void *obj, void *value) { @@ -871,6 +879,14 @@ _Py_atomic_store_ptr_release(void *obj, void *value) memory_order_release); } +static inline void +_Py_atomic_store_uintptr_release(uintptr_t *obj, uintptr_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(uintptr_t)*)obj, value, + memory_order_release); +} + static inline void _Py_atomic_store_int_release(int *obj, int value) { diff --git a/Include/internal/pycore_ceval_state.h b/Include/internal/pycore_ceval_state.h index b453328f15649eb..168295534e036ca 100644 --- a/Include/internal/pycore_ceval_state.h +++ b/Include/internal/pycore_ceval_state.h @@ -63,6 +63,7 @@ struct _ceval_runtime_state { } perf; /* Pending calls to be made only on the main thread. */ struct _pending_calls pending_mainthread; + PyMutex sys_trace_profile_mutex; }; #ifdef PY_HAVE_PERF_TRAMPOLINE diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index 60020b5c01f8a6c..9e465fdd86279f3 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -93,7 +93,7 @@ static inline void _PyObject_GC_SET_SHARED(PyObject *op) { * threads and needs special purpose when freeing due to * the possibility of in-flight lock-free reads occurring. * Objects with this bit that are GC objects will automatically - * delay-freed by PyObject_GC_Del. */ + * delay-freed by PyObject_GC_Del. */ static inline int _PyObject_GC_IS_SHARED_INLINE(PyObject *op) { return (op->ob_gc_bits & _PyGC_BITS_SHARED_INLINE) != 0; } diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index 2514f51f1b00862..fed5d6e0ec2c54e 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -26,20 +26,34 @@ extern "C" { _Py_atomic_load_ssize_relaxed(&value) #define FT_ATOMIC_STORE_PTR(value, new_value) \ _Py_atomic_store_ptr(&value, new_value) +#define FT_ATOMIC_LOAD_PTR_ACQUIRE(value) \ + _Py_atomic_load_ptr_acquire(&value) +#define FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(value) \ + _Py_atomic_load_uintptr_acquire(&value) #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) \ _Py_atomic_store_ptr_relaxed(&value, new_value) #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) \ _Py_atomic_store_ptr_release(&value, new_value) +#define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) \ + _Py_atomic_store_uintptr_release(&value, new_value) #define FT_ATOMIC_STORE_SSIZE_RELAXED(value, new_value) \ _Py_atomic_store_ssize_relaxed(&value, new_value) +#define FT_ATOMIC_STORE_UINT8_RELAXED(value, new_value) \ + _Py_atomic_store_uint8_relaxed(&value, new_value) + #else #define FT_ATOMIC_LOAD_PTR(value) value #define FT_ATOMIC_LOAD_SSIZE(value) value #define FT_ATOMIC_LOAD_SSIZE_RELAXED(value) value #define FT_ATOMIC_STORE_PTR(value, new_value) value = new_value +#define FT_ATOMIC_LOAD_PTR_ACQUIRE(value) value +#define FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(value) value #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value +#define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) value = new_value #define FT_ATOMIC_STORE_SSIZE_RELAXED(value, new_value) value = new_value +#define FT_ATOMIC_STORE_UINT8_RELAXED(value, new_value) value = new_value + #endif #ifdef __cplusplus diff --git a/Lib/test/test_free_threading/__init__.py b/Lib/test/test_free_threading/__init__.py new file mode 100644 index 000000000000000..9a89d27ba9f979d --- /dev/null +++ b/Lib/test/test_free_threading/__init__.py @@ -0,0 +1,7 @@ +import os + +from test import support + + +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_free_threading/test_monitoring.py b/Lib/test/test_free_threading/test_monitoring.py new file mode 100644 index 000000000000000..e170840ca3cb277 --- /dev/null +++ b/Lib/test/test_free_threading/test_monitoring.py @@ -0,0 +1,232 @@ +"""Tests monitoring, sys.settrace, and sys.setprofile in a multi-threaded +environmenet to verify things are thread-safe in a free-threaded build""" + +import sys +import time +import unittest +import weakref + +from sys import monitoring +from test.support import is_wasi +from threading import Thread +from unittest import TestCase + + +class InstrumentationMultiThreadedMixin: + if not hasattr(sys, "gettotalrefcount"): + thread_count = 50 + func_count = 1000 + fib = 15 + else: + # Run a little faster in debug builds... + thread_count = 25 + func_count = 500 + fib = 15 + + def after_threads(self): + """Runs once after all the threads have started""" + pass + + def during_threads(self): + """Runs repeatedly while the threads are still running""" + pass + + def work(self, n, funcs): + """Fibonacci function which also calls a bunch of random functions""" + for func in funcs: + func() + if n < 2: + return n + return self.work(n - 1, funcs) + self.work(n - 2, funcs) + + def start_work(self, n, funcs): + # With the GIL builds we need to make sure that the hooks have + # a chance to run as it's possible to run w/o releasing the GIL. + time.sleep(1) + self.work(n, funcs) + + def after_test(self): + """Runs once after the test is done""" + pass + + def test_instrumentation(self): + # Setup a bunch of functions which will need instrumentation... + funcs = [] + for i in range(self.func_count): + x = {} + exec("def f(): pass", x) + funcs.append(x["f"]) + + threads = [] + for i in range(self.thread_count): + # Each thread gets a copy of the func list to avoid contention + t = Thread(target=self.start_work, args=(self.fib, list(funcs))) + t.start() + threads.append(t) + + self.after_threads() + + while True: + any_alive = False + for t in threads: + if t.is_alive(): + any_alive = True + break + + if not any_alive: + break + + self.during_threads() + + self.after_test() + + +class MonitoringTestMixin: + def setUp(self): + for i in range(6): + if monitoring.get_tool(i) is None: + self.tool_id = i + monitoring.use_tool_id(i, self.__class__.__name__) + break + + def tearDown(self): + monitoring.free_tool_id(self.tool_id) + + +@unittest.skipIf(is_wasi, "WASI has no threads.") +class SetPreTraceMultiThreaded(InstrumentationMultiThreadedMixin, TestCase): + """Sets tracing one time after the threads have started""" + + def setUp(self): + super().setUp() + self.called = False + + def after_test(self): + self.assertTrue(self.called) + + def trace_func(self, frame, event, arg): + self.called = True + return self.trace_func + + def after_threads(self): + sys.settrace(self.trace_func) + + +@unittest.skipIf(is_wasi, "WASI has no threads.") +class MonitoringMultiThreaded( + MonitoringTestMixin, InstrumentationMultiThreadedMixin, TestCase +): + """Uses sys.monitoring and repeatedly toggles instrumentation on and off""" + + def setUp(self): + super().setUp() + self.set = False + self.called = False + monitoring.register_callback( + self.tool_id, monitoring.events.LINE, self.callback + ) + + def tearDown(self): + monitoring.set_events(self.tool_id, 0) + super().tearDown() + + def callback(self, *args): + self.called = True + + def after_test(self): + self.assertTrue(self.called) + + def during_threads(self): + if self.set: + monitoring.set_events( + self.tool_id, monitoring.events.CALL | monitoring.events.LINE + ) + else: + monitoring.set_events(self.tool_id, 0) + self.set = not self.set + + +@unittest.skipIf(is_wasi, "WASI has no threads.") +class SetTraceMultiThreaded(InstrumentationMultiThreadedMixin, TestCase): + """Uses sys.settrace and repeatedly toggles instrumentation on and off""" + + def setUp(self): + self.set = False + self.called = False + + def after_test(self): + self.assertTrue(self.called) + + def tearDown(self): + sys.settrace(None) + + def trace_func(self, frame, event, arg): + self.called = True + return self.trace_func + + def during_threads(self): + if self.set: + sys.settrace(self.trace_func) + else: + sys.settrace(None) + self.set = not self.set + + +@unittest.skipIf(is_wasi, "WASI has no threads.") +class SetProfileMultiThreaded(InstrumentationMultiThreadedMixin, TestCase): + """Uses sys.setprofile and repeatedly toggles instrumentation on and off""" + thread_count = 25 + func_count = 200 + fib = 15 + + def setUp(self): + self.set = False + self.called = False + + def after_test(self): + self.assertTrue(self.called) + + def tearDown(self): + sys.setprofile(None) + + def trace_func(self, frame, event, arg): + self.called = True + return self.trace_func + + def during_threads(self): + if self.set: + sys.setprofile(self.trace_func) + else: + sys.setprofile(None) + self.set = not self.set + + +@unittest.skipIf(is_wasi, "WASI has no threads.") +class MonitoringMisc(MonitoringTestMixin, TestCase): + def register_callback(self): + def callback(*args): + pass + + for i in range(200): + monitoring.register_callback(self.tool_id, monitoring.events.LINE, callback) + + self.refs.append(weakref.ref(callback)) + + def test_register_callback(self): + self.refs = [] + threads = [] + for i in range(50): + t = Thread(target=self.register_callback) + t.start() + threads.append(t) + + for thread in threads: + thread.join() + + monitoring.register_callback(self.tool_id, monitoring.events.LINE, None) + for ref in self.refs: + self.assertEqual(ref(), None) + + +if __name__ == "__main__": + unittest.main() diff --git a/Makefile.pre.in b/Makefile.pre.in index fd8678cdaf82074..f7c21a380caa99f 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2366,6 +2366,7 @@ TESTSUBDIRS= idlelib/idle_test \ test/test_doctest \ test/test_email \ test/test_email/data \ + test/test_free_threading \ test/test_future_stmt \ test/test_gdb \ test/test_import \ diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c34d702f06418e8..c1fbd3c7d26e01e 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -20,6 +20,7 @@ #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_opcode_metadata.h" // uop names #include "pycore_opcode_utils.h" // MAKE_FUNCTION_* +#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_ACQUIRE #include "pycore_pyerrors.h" // _PyErr_GetRaisedException() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_range.h" // _PyRangeIterObject @@ -150,10 +151,11 @@ dummy_func( uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK; - uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + PyCodeObject *code = _PyFrame_GetCode(frame); + uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version); assert((code_version & 255) == 0); if (code_version != global_version) { - int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); + int err = _Py_Instrument(code, tstate->interp); ERROR_IF(err, error); next_instr = this_instr; } @@ -171,14 +173,14 @@ dummy_func( _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + uintptr_t version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); assert((version & _PY_EVAL_EVENTS_MASK) == 0); DEOPT_IF(eval_breaker != version); } inst(INSTRUMENTED_RESUME, (--)) { uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK; - uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); if (code_version != global_version) { if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { ERROR_NO_POP(); @@ -2377,7 +2379,14 @@ dummy_func( }; tier1 inst(ENTER_EXECUTOR, (--)) { + int prevoparg = oparg; CHECK_EVAL_BREAKER(); + if (this_instr->op.code != ENTER_EXECUTOR || + this_instr->op.arg != prevoparg) { + next_instr = this_instr; + DISPATCH(); + } + PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; assert(executor->vm_data.index == INSTR_OFFSET() - 1); diff --git a/Python/ceval.c b/Python/ceval.c index b88e555ded5c2ee..2f217c5f33c6cef 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -20,6 +20,7 @@ #include "pycore_opcode_metadata.h" // EXTRA_CASES #include "pycore_optimizer.h" // _PyUOpExecutor_Type #include "pycore_opcode_utils.h" // MAKE_FUNCTION_* +#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_ACQUIRE #include "pycore_pyerrors.h" // _PyErr_GetRaisedException() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_range.h" // _PyRangeIterObject diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index fccff24a4185861..df87f9178f17cfc 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -21,7 +21,7 @@ _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + uintptr_t version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); assert((version & _PY_EVAL_EVENTS_MASK) == 0); if (eval_breaker != version) { UOP_STAT_INC(uopcode, miss); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index a7764b0ec12e108..a426d9e208492ec 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2498,10 +2498,17 @@ } TARGET(ENTER_EXECUTOR) { - frame->instr_ptr = next_instr; + _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; + (void)this_instr; next_instr += 1; INSTRUCTION_STATS(ENTER_EXECUTOR); + int prevoparg = oparg; CHECK_EVAL_BREAKER(); + if (this_instr->op.code != ENTER_EXECUTOR || + this_instr->op.arg != prevoparg) { + next_instr = this_instr; + DISPATCH(); + } PyCodeObject *code = _PyFrame_GetCode(frame); _PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; assert(executor->vm_data.index == INSTR_OFFSET() - 1); @@ -3267,7 +3274,7 @@ next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_RESUME); uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK; - uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); if (code_version != global_version) { if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { goto error; @@ -4927,10 +4934,11 @@ uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK; - uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + PyCodeObject *code = _PyFrame_GetCode(frame); + uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version); assert((code_version & 255) == 0); if (code_version != global_version) { - int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); + int err = _Py_Instrument(code, tstate->interp); if (err) goto error; next_instr = this_instr; } @@ -4953,7 +4961,7 @@ _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING; #endif uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker); - uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version; + uintptr_t version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); assert((version & _PY_EVAL_EVENTS_MASK) == 0); DEOPT_IF(eval_breaker != version, RESUME); DISPATCH(); diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 3866144a19bf747..71efeff077633d9 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -6,6 +6,7 @@ #include "pycore_call.h" #include "pycore_ceval.h" // _PY_EVAL_EVENTS_BITS #include "pycore_code.h" // _PyCode_Clear_Executors() +#include "pycore_critical_section.h" #include "pycore_frame.h" #include "pycore_interp.h" #include "pycore_long.h" @@ -13,12 +14,43 @@ #include "pycore_namespace.h" #include "pycore_object.h" #include "pycore_opcode_metadata.h" // IS_VALID_OPCODE, _PyOpcode_Caches +#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_UINTPTR_RELEASE #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyInterpreterState_GET() /* Uncomment this to dump debugging output when assertions fail */ // #define INSTRUMENT_DEBUG 1 +#if defined(Py_DEBUG) && defined(Py_GIL_DISABLED) + +#define ASSERT_WORLD_STOPPED_OR_LOCKED(obj) \ + if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) { \ + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj); \ + } +#define ASSERT_WORLD_STOPPED() assert(_PyInterpreterState_GET()->stoptheworld.world_stopped); + +#else + +#define ASSERT_WORLD_STOPPED_OR_LOCKED(obj) +#define ASSERT_WORLD_STOPPED() + +#endif + +#ifdef Py_GIL_DISABLED + +#define LOCK_CODE(code) \ + assert(!_PyInterpreterState_GET()->stoptheworld.world_stopped); \ + Py_BEGIN_CRITICAL_SECTION(code) + +#define UNLOCK_CODE() Py_END_CRITICAL_SECTION() + +#else + +#define LOCK_CODE(code) +#define UNLOCK_CODE() + +#endif + PyObject _PyInstrumentation_DISABLE = _PyObject_HEAD_INIT(&PyBaseObject_Type); PyObject _PyInstrumentation_MISSING = _PyObject_HEAD_INIT(&PyBaseObject_Type); @@ -278,6 +310,8 @@ compute_line(PyCodeObject *code, int offset, int8_t line_delta) int _PyInstruction_GetLength(PyCodeObject *code, int offset) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + int opcode = _PyCode_CODE(code)[offset].op.code; assert(opcode != 0); assert(opcode != RESERVED); @@ -424,6 +458,7 @@ dump_instrumentation_data(PyCodeObject *code, int star, FILE*out) } #define CHECK(test) do { \ + ASSERT_WORLD_STOPPED_OR_LOCKED(code); \ if (!(test)) { \ dump_instrumentation_data(code, i, stderr); \ } \ @@ -449,6 +484,8 @@ valid_opcode(int opcode) static void sanity_check_instrumentation(PyCodeObject *code) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + _PyCoMonitoringData *data = code->_co_monitoring; if (data == NULL) { return; @@ -718,6 +755,7 @@ instrument_per_instruction(PyCodeObject *code, int i) static void remove_tools(PyCodeObject * code, int offset, int event, int tools) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); assert(event != PY_MONITORING_EVENT_LINE); assert(event != PY_MONITORING_EVENT_INSTRUCTION); assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); @@ -752,6 +790,8 @@ tools_is_subset_for_event(PyCodeObject * code, int event, int tools) static void remove_line_tools(PyCodeObject * code, int offset, int tools) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + assert(code->_co_monitoring); if (code->_co_monitoring->line_tools) { @@ -774,6 +814,7 @@ remove_line_tools(PyCodeObject * code, int offset, int tools) static void add_tools(PyCodeObject * code, int offset, int event, int tools) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); assert(event != PY_MONITORING_EVENT_LINE); assert(event != PY_MONITORING_EVENT_INSTRUCTION); assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); @@ -794,6 +835,8 @@ add_tools(PyCodeObject * code, int offset, int event, int tools) static void add_line_tools(PyCodeObject * code, int offset, int tools) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + assert(tools_is_subset_for_event(code, PY_MONITORING_EVENT_LINE, tools)); assert(code->_co_monitoring); if (code->_co_monitoring->line_tools) { @@ -810,6 +853,8 @@ add_line_tools(PyCodeObject * code, int offset, int tools) static void add_per_instruction_tools(PyCodeObject * code, int offset, int tools) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + assert(tools_is_subset_for_event(code, PY_MONITORING_EVENT_INSTRUCTION, tools)); assert(code->_co_monitoring); if (code->_co_monitoring->per_instruction_tools) { @@ -826,6 +871,8 @@ add_per_instruction_tools(PyCodeObject * code, int offset, int tools) static void remove_per_instruction_tools(PyCodeObject * code, int offset, int tools) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + assert(code->_co_monitoring); if (code->_co_monitoring->per_instruction_tools) { uint8_t *toolsptr = &code->_co_monitoring->per_instruction_tools[offset]; @@ -1056,7 +1103,9 @@ call_instrumentation_vector( break; } else { + LOCK_CODE(code); remove_tools(code, offset, event, 1 << tool); + UNLOCK_CODE(); } } } @@ -1189,6 +1238,7 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, goto done; } } + uint8_t tools = code->_co_monitoring->line_tools != NULL ? code->_co_monitoring->line_tools[i] : (interp->monitors.tools[PY_MONITORING_EVENT_LINE] | @@ -1249,7 +1299,9 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, } else { /* DISABLE */ + LOCK_CODE(code); remove_line_tools(code, i, 1 << tool); + UNLOCK_CODE(); } } while (tools); Py_DECREF(line_obj); @@ -1305,7 +1357,9 @@ _Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* } else { /* DISABLE */ + LOCK_CODE(code); remove_per_instruction_tools(code, offset, 1 << tool); + UNLOCK_CODE(); } } Py_DECREF(offset_obj); @@ -1320,15 +1374,18 @@ _PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj) PyInterpreterState *is = _PyInterpreterState_GET(); assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); assert(0 <= event_id && event_id < _PY_MONITORING_EVENTS); - PyObject *callback = is->monitoring_callables[tool_id][event_id]; - is->monitoring_callables[tool_id][event_id] = Py_XNewRef(obj); + PyObject *callback = _Py_atomic_exchange_ptr(&is->monitoring_callables[tool_id][event_id], + Py_XNewRef(obj)); + return callback; } static void initialize_tools(PyCodeObject *code) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); uint8_t* tools = code->_co_monitoring->tools; + assert(tools != NULL); int code_len = (int)Py_SIZE(code); for (int i = 0; i < code_len; i++) { @@ -1384,7 +1441,9 @@ initialize_tools(PyCodeObject *code) static void initialize_lines(PyCodeObject *code) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines; + assert(line_data != NULL); int code_len = (int)Py_SIZE(code); PyCodeAddressRange range; @@ -1501,7 +1560,9 @@ initialize_lines(PyCodeObject *code) static void initialize_line_tools(PyCodeObject *code, _Py_LocalMonitors *all_events) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); uint8_t *line_tools = code->_co_monitoring->line_tools; + assert(line_tools != NULL); int code_len = (int)Py_SIZE(code); for (int i = 0; i < code_len; i++) { @@ -1512,6 +1573,7 @@ initialize_line_tools(PyCodeObject *code, _Py_LocalMonitors *all_events) static int allocate_instrumentation_data(PyCodeObject *code) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); if (code->_co_monitoring == NULL) { code->_co_monitoring = PyMem_Malloc(sizeof(_PyCoMonitoringData)); @@ -1533,6 +1595,8 @@ allocate_instrumentation_data(PyCodeObject *code) static int update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + int code_len = (int)Py_SIZE(code); if (allocate_instrumentation_data(code)) { return -1; @@ -1594,9 +1658,11 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) return 0; } -int -_Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) +static int +instrument_lock_held(PyCodeObject *code, PyInterpreterState *interp) { + ASSERT_WORLD_STOPPED_OR_LOCKED(code); + if (is_version_up_to_date(code, interp)) { assert( interp->ceval.instrumentation_version == 0 || @@ -1636,12 +1702,8 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) assert(monitors_are_empty(monitors_and(new_events, removed_events))); } code->_co_monitoring->active_monitors = active_events; - code->_co_instrumentation_version = global_version(interp); if (monitors_are_empty(new_events) && monitors_are_empty(removed_events)) { -#ifdef INSTRUMENT_DEBUG - sanity_check_instrumentation(code); -#endif - return 0; + goto done; } /* Insert instrumentation */ for (int i = code->_co_firsttraceable; i < code_len; i+= _PyInstruction_GetLength(code, i)) { @@ -1730,12 +1792,26 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) i += _PyInstruction_GetLength(code, i); } } +done: + FT_ATOMIC_STORE_UINTPTR_RELEASE(code->_co_instrumentation_version, + global_version(interp)); + #ifdef INSTRUMENT_DEBUG sanity_check_instrumentation(code); #endif return 0; } +int +_Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) +{ + int res; + LOCK_CODE(code); + res = instrument_lock_held(code, interp); + UNLOCK_CODE(); + return res; +} + #define C_RETURN_EVENTS \ ((1 << PY_MONITORING_EVENT_C_RETURN) | \ (1 << PY_MONITORING_EVENT_C_RAISE)) @@ -1746,6 +1822,8 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp) static int instrument_all_executing_code_objects(PyInterpreterState *interp) { + ASSERT_WORLD_STOPPED(); + _PyRuntimeState *runtime = &_PyRuntime; HEAD_LOCK(runtime); PyThreadState* ts = PyInterpreterState_ThreadHead(interp); @@ -1754,7 +1832,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) { _PyInterpreterFrame *frame = ts->current_frame; while (frame) { if (frame->owner != FRAME_OWNED_BY_CSTACK) { - if (_Py_Instrument(_PyFrame_GetCode(frame), interp)) { + if (instrument_lock_held(_PyFrame_GetCode(frame), interp)) { return -1; } } @@ -1817,19 +1895,27 @@ _PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events) if (check_tool(interp, tool_id)) { return -1; } + + int res; + _PyEval_StopTheWorld(interp); uint32_t existing_events = get_events(&interp->monitors, tool_id); if (existing_events == events) { - return 0; + res = 0; + goto done; } set_events(&interp->monitors, tool_id, events); uint32_t new_version = global_version(interp) + MONITORING_VERSION_INCREMENT; if (new_version == 0) { PyErr_Format(PyExc_OverflowError, "events set too many times"); - return -1; + res = -1; + goto done; } set_global_version(tstate, new_version); _Py_Executors_InvalidateAll(interp, 1); - return instrument_all_executing_code_objects(interp); + res = instrument_all_executing_code_objects(interp); +done: + _PyEval_StartTheWorld(interp); + return res; } int @@ -1845,24 +1931,33 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent if (check_tool(interp, tool_id)) { return -1; } + + int res; + LOCK_CODE(code); if (allocate_instrumentation_data(code)) { - return -1; + res = -1; + goto done; } + _Py_LocalMonitors *local = &code->_co_monitoring->local_monitors; uint32_t existing_events = get_local_events(local, tool_id); if (existing_events == events) { - return 0; + res = 0; + goto done; } set_local_events(local, tool_id, events); if (is_version_up_to_date(code, interp)) { /* Force instrumentation update */ code->_co_instrumentation_version -= MONITORING_VERSION_INCREMENT; } + _Py_Executors_InvalidateDependency(interp, code, 1); - if (_Py_Instrument(code, interp)) { - return -1; - } - return 0; + + res = instrument_lock_held(code, interp); + +done: + UNLOCK_CODE(); + return res; } int @@ -2158,15 +2253,21 @@ monitoring_restart_events_impl(PyObject *module) */ PyThreadState *tstate = _PyThreadState_GET(); PyInterpreterState *interp = tstate->interp; + + _PyEval_StopTheWorld(interp); uint32_t restart_version = global_version(interp) + MONITORING_VERSION_INCREMENT; uint32_t new_version = restart_version + MONITORING_VERSION_INCREMENT; if (new_version <= MONITORING_VERSION_INCREMENT) { + _PyEval_StartTheWorld(interp); PyErr_Format(PyExc_OverflowError, "events set too many times"); return NULL; } interp->last_restart_version = restart_version; set_global_version(tstate, new_version); - if (instrument_all_executing_code_objects(interp)) { + int res = instrument_all_executing_code_objects(interp); + _PyEval_StartTheWorld(interp); + + if (res) { return NULL; } Py_RETURN_NONE; diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c index ccbb3eb3f7c82a2..d7aae7d2343ac2a 100644 --- a/Python/legacy_tracing.c +++ b/Python/legacy_tracing.c @@ -16,6 +16,13 @@ typedef struct _PyLegacyEventHandler { int event; } _PyLegacyEventHandler; +#ifdef Py_GIL_DISABLED +#define LOCK_SETUP() PyMutex_Lock(&_PyRuntime.ceval.sys_trace_profile_mutex); +#define UNLOCK_SETUP() PyMutex_Unlock(&_PyRuntime.ceval.sys_trace_profile_mutex); +#else +#define LOCK_SETUP() +#define UNLOCK_SETUP() +#endif /* The Py_tracefunc function expects the following arguments: * obj: the trace object (PyObject *) * frame: the current frame (PyFrameObject *) @@ -414,19 +421,10 @@ is_tstate_valid(PyThreadState *tstate) } #endif -int -_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) +static Py_ssize_t +setup_profile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg, PyObject **old_profileobj) { - assert(is_tstate_valid(tstate)); - /* The caller must hold the GIL */ - assert(PyGILState_Check()); - - /* Call _PySys_Audit() in the context of the current thread state, - even if tstate is not the current thread state. */ - PyThreadState *current_tstate = _PyThreadState_GET(); - if (_PySys_Audit(current_tstate, "sys.setprofile", NULL) < 0) { - return -1; - } + *old_profileobj = NULL; /* Setup PEP 669 monitoring callbacks and events. */ if (!tstate->interp->sys_profile_initialized) { tstate->interp->sys_profile_initialized = true; @@ -469,25 +467,15 @@ _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) int delta = (func != NULL) - (tstate->c_profilefunc != NULL); tstate->c_profilefunc = func; - PyObject *old_profileobj = tstate->c_profileobj; + *old_profileobj = tstate->c_profileobj; tstate->c_profileobj = Py_XNewRef(arg); - Py_XDECREF(old_profileobj); tstate->interp->sys_profiling_threads += delta; assert(tstate->interp->sys_profiling_threads >= 0); - - uint32_t events = 0; - if (tstate->interp->sys_profiling_threads) { - events = - (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) | - (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) | - (1 << PY_MONITORING_EVENT_CALL) | (1 << PY_MONITORING_EVENT_PY_UNWIND) | - (1 << PY_MONITORING_EVENT_PY_THROW); - } - return _PyMonitoring_SetEvents(PY_MONITORING_SYS_PROFILE_ID, events); + return tstate->interp->sys_profiling_threads; } int -_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) +_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) { assert(is_tstate_valid(tstate)); /* The caller must hold the GIL */ @@ -496,11 +484,32 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) /* Call _PySys_Audit() in the context of the current thread state, even if tstate is not the current thread state. */ PyThreadState *current_tstate = _PyThreadState_GET(); - if (_PySys_Audit(current_tstate, "sys.settrace", NULL) < 0) { + if (_PySys_Audit(current_tstate, "sys.setprofile", NULL) < 0) { return -1; } - assert(tstate->interp->sys_tracing_threads >= 0); + // needs to be decref'd outside of the lock + PyObject *old_profileobj; + LOCK_SETUP(); + Py_ssize_t profiling_threads = setup_profile(tstate, func, arg, &old_profileobj); + UNLOCK_SETUP(); + Py_XDECREF(old_profileobj); + + uint32_t events = 0; + if (profiling_threads) { + events = + (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) | + (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) | + (1 << PY_MONITORING_EVENT_CALL) | (1 << PY_MONITORING_EVENT_PY_UNWIND) | + (1 << PY_MONITORING_EVENT_PY_THROW); + } + return _PyMonitoring_SetEvents(PY_MONITORING_SYS_PROFILE_ID, events); +} + +static Py_ssize_t +setup_tracing(PyThreadState *tstate, Py_tracefunc func, PyObject *arg, PyObject **old_traceobj) +{ + *old_traceobj = NULL; /* Setup PEP 669 monitoring callbacks and events. */ if (!tstate->interp->sys_trace_initialized) { tstate->interp->sys_trace_initialized = true; @@ -553,14 +562,39 @@ _PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) int delta = (func != NULL) - (tstate->c_tracefunc != NULL); tstate->c_tracefunc = func; - PyObject *old_traceobj = tstate->c_traceobj; + *old_traceobj = tstate->c_traceobj; tstate->c_traceobj = Py_XNewRef(arg); - Py_XDECREF(old_traceobj); tstate->interp->sys_tracing_threads += delta; assert(tstate->interp->sys_tracing_threads >= 0); + return tstate->interp->sys_tracing_threads; +} + +int +_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg) +{ + assert(is_tstate_valid(tstate)); + /* The caller must hold the GIL */ + assert(PyGILState_Check()); + + /* Call _PySys_Audit() in the context of the current thread state, + even if tstate is not the current thread state. */ + PyThreadState *current_tstate = _PyThreadState_GET(); + if (_PySys_Audit(current_tstate, "sys.settrace", NULL) < 0) { + return -1; + } + assert(tstate->interp->sys_tracing_threads >= 0); + // needs to be decref'd outside of the lock + PyObject *old_traceobj; + LOCK_SETUP(); + Py_ssize_t tracing_threads = setup_tracing(tstate, func, arg, &old_traceobj); + UNLOCK_SETUP(); + Py_XDECREF(old_traceobj); + if (tracing_threads < 0) { + return -1; + } uint32_t events = 0; - if (tstate->interp->sys_tracing_threads) { + if (tracing_threads) { events = (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) | (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) | diff --git a/Python/pystate.c b/Python/pystate.c index 37480df88aeb726..06806bd75fbcb27 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -399,6 +399,7 @@ _Py_COMP_DIAG_POP &(runtime)->unicode_state.ids.mutex, \ &(runtime)->imports.extensions.mutex, \ &(runtime)->ceval.pending_mainthread.mutex, \ + &(runtime)->ceval.sys_trace_profile_mutex, \ &(runtime)->atexit.mutex, \ &(runtime)->audit_hooks.mutex, \ &(runtime)->allocators.mutex, \ diff --git a/Tools/jit/template.c b/Tools/jit/template.c index b195aff377b3b5a..228dc83254d678c 100644 --- a/Tools/jit/template.c +++ b/Tools/jit/template.c @@ -12,6 +12,7 @@ #include "pycore_opcode_metadata.h" #include "pycore_opcode_utils.h" #include "pycore_optimizer.h" +#include "pycore_pyatomic_ft_wrappers.h" #include "pycore_range.h" #include "pycore_setobject.h" #include "pycore_sliceobject.h" From d8f350309ded3130c43f0d2809dcb8ec13112320 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 19 Apr 2024 15:30:52 -0700 Subject: [PATCH 073/127] GH-115874: Fix segfault in FutureIter_dealloc (GH-117741) --- ...4-04-13-18-59-25.gh-issue-115874.c3xG-E.rst | 1 + Modules/_asynciomodule.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst new file mode 100644 index 000000000000000..5a6fa4cedd9fe46 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-13-18-59-25.gh-issue-115874.c3xG-E.rst @@ -0,0 +1 @@ +Fixed a possible segfault during garbage collection of ``_asyncio.FutureIter`` objects diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index b886051186de9c4..0873d32a9ec1a5b 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1601,11 +1601,25 @@ static void FutureIter_dealloc(futureiterobject *it) { PyTypeObject *tp = Py_TYPE(it); - asyncio_state *state = get_asyncio_state_by_def((PyObject *)it); + + // FutureIter is a heap type so any subclass must also be a heap type. + assert(_PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)); + + PyObject *module = ((PyHeapTypeObject*)tp)->ht_module; + asyncio_state *state = NULL; + PyObject_GC_UnTrack(it); tp->tp_clear((PyObject *)it); - if (state->fi_freelist_len < FI_FREELIST_MAXLEN) { + // GH-115874: We can't use PyType_GetModuleByDef here as the type might have + // already been cleared, which is also why we must check if ht_module != NULL. + // Due to this restriction, subclasses that belong to a different module + // will not be able to use the free list. + if (module && _PyModule_GetDef(module) == &_asynciomodule) { + state = get_asyncio_state(module); + } + + if (state && state->fi_freelist_len < FI_FREELIST_MAXLEN) { state->fi_freelist_len++; it->future = (FutureObj*) state->fi_freelist; state->fi_freelist = it; From 15fbd53ba96be4b6a5abd94ceada684493c36bdd Mon Sep 17 00:00:00 2001 From: Barney Gale Date: Sat, 20 Apr 2024 17:46:52 +0100 Subject: [PATCH 074/127] GH-112855: Speed up `pathlib.PurePath` pickling (#112856) The second item in the tuple returned from `__reduce__()` is a tuple of arguments to supply to path constructor. Previously we returned the `parts` tuple here, which entailed joining, parsing and normalising the path object, and produced a compact pickle representation. With this patch, we instead return a tuple of paths that were originally given to the path constructor. This makes pickling much faster (at the expense of compactness). It's worth noting that, in the olden times, pathlib performed this parsing/normalization up-front in every case, and so using `parts` for pickling was almost free. Nowadays pathlib only parses/normalises paths when it's necessary or advantageous to do so (e.g. computing a path parent, or iterating over a directory, respectively). --- Lib/pathlib/__init__.py | 4 +--- .../Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst diff --git a/Lib/pathlib/__init__.py b/Lib/pathlib/__init__.py index a4721fbe8139622..f03f317ef6c16a3 100644 --- a/Lib/pathlib/__init__.py +++ b/Lib/pathlib/__init__.py @@ -169,9 +169,7 @@ def __rtruediv__(self, key): return NotImplemented def __reduce__(self): - # Using the parts tuple helps share interned path parts - # when pickling related paths. - return (self.__class__, self.parts) + return self.__class__, tuple(self._raw_paths) def __repr__(self): return "{}({!r})".format(self.__class__.__name__, self.as_posix()) diff --git a/Misc/NEWS.d/next/Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst b/Misc/NEWS.d/next/Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst new file mode 100644 index 000000000000000..6badc7a9dc1c94f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-07-20-05-54.gh-issue-112855.ph4ehh.rst @@ -0,0 +1,2 @@ +Speed up pickling of :class:`pathlib.PurePath` objects. Patch by Barney +Gale. From 1558d993166636f371c1003107ec979db6744f21 Mon Sep 17 00:00:00 2001 From: Quazi Irfan Date: Sat, 20 Apr 2024 21:42:51 -0400 Subject: [PATCH 075/127] Clarifying nonlocal doc: SyntaxError is raised if nearest enclosing scope is global (#114009) Co-authored-by: Jelle Zijlstra --- Doc/reference/executionmodel.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst index cea3a56ba516447..ed50faed6c940d7 100644 --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -139,8 +139,9 @@ namespace. Names are resolved in the top-level namespace by searching the global namespace, i.e. the namespace of the module containing the code block, and the builtins namespace, the namespace of the module :mod:`builtins`. The global namespace is searched first. If the names are not found there, the -builtins namespace is searched. The :keyword:`!global` statement must precede -all uses of the listed names. +builtins namespace is searched next. If the names are also not found in the +builtins namespace, new variables are created in the global namespace. +The global statement must precede all uses of the listed names. The :keyword:`global` statement has the same scope as a name binding operation in the same block. If the nearest enclosing scope for a free variable contains From 92c84ef831c8276d591130f1c2c51289e2ba203a Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Sun, 21 Apr 2024 05:25:39 +0300 Subject: [PATCH 076/127] ``Objects/typeobject.c``: Fix typo (#118126) --- Objects/typeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2f356388785665d..970c82d2a17ada6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5671,7 +5671,7 @@ type_clear(PyObject *self) the dict, so that other objects caught in a reference cycle don't start calling destroyed methods. - Otherwise, the we need to clear tp_mro, which is + Otherwise, we need to clear tp_mro, which is part of a hard cycle (its first element is the class itself) that won't be broken otherwise (it's a tuple and tuples don't have a tp_clear handler). From df987331d896031799f33cb0f3a7b5c5712cb4e7 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 21 Apr 2024 11:04:08 +0800 Subject: [PATCH 077/127] gh-114099: Formalize Tier 3 status of iOS (GH-118020) --- Doc/whatsnew/3.13.rst | 16 ++++++++++++++++ Misc/ACKS | 1 + 2 files changed, 17 insertions(+) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index cf9853f94872c31..0f0fca5d23597b6 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -127,6 +127,22 @@ Incremental Garbage Collection This means that maximum pause times are reduced by an order of magnitude or more for larger heaps. +Support For Mobile Platforms +---------------------------- + +* iOS is now a :pep:`11` supported platform. ``arm64-apple-ios`` + (iPhone and iPad devices released after 2013) and + ``arm64-apple-ios-simulator`` (Xcode iOS simulator running on Apple Silicon + hardware) are now tier 3 platforms. + + ``x86_64-apple-ios-simulator`` (Xcode iOS simulator running on older x86_64 + hardware) is not a tier 3 supported platform, but will be supported on a + best-effort basis. + + See :pep:`730`: for more details. + + (PEP written and implementation contributed by Russell Keith-Magee in + :gh:`114099`.) Other Language Changes ====================== diff --git a/Misc/ACKS b/Misc/ACKS index 76d30b257b46932..eaa7453aaade3e4 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -930,6 +930,7 @@ Hiroaki Kawai Dmitry Kazakov Brian Kearns Sebastien Keim +Russell Keith-Magee Ryan Kelly Hugo van Kemenade Dan Kenigsberg From 5fa5b7facbcd1f725e51daf31c321e02b7db3f02 Mon Sep 17 00:00:00 2001 From: Andrew Cassidy Date: Sat, 20 Apr 2024 23:52:58 -0700 Subject: [PATCH 078/127] gh-91629 Use conf.d configs and fish_add_path to set the PATH when installing for the Fish shell. (GH-91630) Co-authored-by: Erlend E. Aasland --- Mac/BuildScript/scripts/postflight.patch-profile | 13 +++++++------ .../2022-04-17-01-07-42.gh-issue-91629.YBGAAt.rst | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/macOS/2022-04-17-01-07-42.gh-issue-91629.YBGAAt.rst diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile index 68b8e4bb044e100..9caf62211ddd16c 100755 --- a/Mac/BuildScript/scripts/postflight.patch-profile +++ b/Mac/BuildScript/scripts/postflight.patch-profile @@ -77,16 +77,17 @@ bash) fi ;; fish) - CONFIG_DIR="${HOME}/.config/fish" - RC="${CONFIG_DIR}/config.fish" + CONFIG_DIR="${HOME}/.config/fish/conf.d/" + RC="${CONFIG_DIR}/python-${PYVER}.fish" mkdir -p "$CONFIG_DIR" if [ -f "${RC}" ]; then cp -fp "${RC}" "${RC}.pysave" fi - echo "" >> "${RC}" - echo "# Setting PATH for Python ${PYVER}" >> "${RC}" - echo "# The original version is saved in ${RC}.pysave" >> "${RC}" - echo "set -x PATH \"${PYTHON_ROOT}/bin\" \"\$PATH\"" >> "${RC}" + echo "# Setting PATH for Python ${PYVER}" > "${RC}" + if [ -f "${RC}.pysave" ]; then + echo "# The original version is saved in ${RC}.pysave" >> "${RC}" + fi + echo "fish_add_path -g \"${PYTHON_ROOT}/bin\"" >> "${RC}" if [ `id -ur` = 0 ]; then chown "${USER}" "${RC}" fi diff --git a/Misc/NEWS.d/next/macOS/2022-04-17-01-07-42.gh-issue-91629.YBGAAt.rst b/Misc/NEWS.d/next/macOS/2022-04-17-01-07-42.gh-issue-91629.YBGAAt.rst new file mode 100644 index 000000000000000..13f3336c4a6ed8c --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2022-04-17-01-07-42.gh-issue-91629.YBGAAt.rst @@ -0,0 +1 @@ +Use :file:`~/.config/fish/conf.d` configs and :program:`fish_add_path` to set :envvar:`PATH` when installing for the Fish shell. From ccda73828473576c57d1bb31774f56542d6e8964 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 21 Apr 2024 10:08:32 +0300 Subject: [PATCH 079/127] gh-118121: Fix `test_doctest.test_look_in_unwrapped` (#118122) --- Lib/test/test_doctest/test_doctest.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index f71d62cc174d6b9..cba4b16d544a204 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -2545,7 +2545,7 @@ def __call__(self, *args, **kwargs): self.func(*args, **kwargs) @Wrapper -def test_look_in_unwrapped(): +def wrapped(): """ Docstrings in wrapped functions must be detected as well. @@ -2553,6 +2553,21 @@ def test_look_in_unwrapped(): 'one other test' """ +def test_look_in_unwrapped(): + """ + Ensure that wrapped doctests work correctly. + + >>> import doctest + >>> doctest.run_docstring_examples( + ... wrapped, {}, name=wrapped.__name__, verbose=True) + Finding tests in wrapped + Trying: + 'one other test' + Expecting: + 'one other test' + ok + """ + @doctest_skip_if(support.check_impl_detail(cpython=False)) def test_wrapped_c_func(): """ From 51ef89cd9acbfbfa7fd8d82f0c6baa388bb650c9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 21 Apr 2024 11:46:39 +0300 Subject: [PATCH 080/127] gh-115961: Add name and mode attributes for compressed file-like objects (GH-116036) * Add name and mode attributes for compressed and archived file-like objects in modules bz2, lzma, tarfile and zipfile. * Change the value of the mode attribute of GzipFile from integer (1 or 2) to string ('rb' or 'wb'). * Change the value of the mode attribute of ZipExtFile from 'r' to 'rb'. --- Doc/library/bz2.rst | 15 +++- Doc/library/gzip.rst | 15 ++-- Doc/library/lzma.rst | 16 ++++- Doc/library/tarfile.rst | 4 ++ Doc/library/zipfile.rst | 10 +++ Doc/whatsnew/3.13.rst | 11 +++ Lib/bz2.py | 18 +++-- Lib/gzip.py | 3 +- Lib/lzma.py | 18 +++-- Lib/tarfile.py | 4 ++ Lib/test/test_bz2.py | 72 +++++++++++++++++-- Lib/test/test_gzip.py | 2 + Lib/test/test_lzma.py | 55 +++++++++++++- Lib/test/test_tarfile.py | 12 ++-- Lib/test/test_zipfile/test_core.py | 9 ++- Lib/zipfile/__init__.py | 12 +++- ...-02-28-10-41-24.gh-issue-115961.P-_DU0.rst | 7 ++ 17 files changed, 246 insertions(+), 37 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-02-28-10-41-24.gh-issue-115961.P-_DU0.rst diff --git a/Doc/library/bz2.rst b/Doc/library/bz2.rst index 5e0aa3e493f2249..eaf0a096455fadb 100644 --- a/Doc/library/bz2.rst +++ b/Doc/library/bz2.rst @@ -91,7 +91,7 @@ The :mod:`bz2` module contains: and :meth:`~io.IOBase.truncate`. Iteration and the :keyword:`with` statement are supported. - :class:`BZ2File` also provides the following methods: + :class:`BZ2File` also provides the following methods and attributes: .. method:: peek([n]) @@ -148,6 +148,19 @@ The :mod:`bz2` module contains: .. versionadded:: 3.3 + .. attribute:: mode + + ``'rb'`` for reading and ``'wb'`` for writing. + + .. versionadded:: 3.13 + + .. attribute:: name + + The bzip2 file name. Equivalent to the :attr:`~io.FileIO.name` + attribute of the underlying :term:`file object`. + + .. versionadded:: 3.13 + .. versionchanged:: 3.1 Support for the :keyword:`with` statement was added. diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst index 044be8c1c1bf418..e6106e72a83d258 100644 --- a/Doc/library/gzip.rst +++ b/Doc/library/gzip.rst @@ -133,6 +133,13 @@ The module defines the following items: .. versionadded:: 3.2 + .. attribute:: mode + + ``'rb'`` for reading and ``'wb'`` for writing. + + .. versionchanged:: 3.13 + In previous versions it was an integer ``1`` or ``2``. + .. attribute:: mtime When decompressing, this attribute is set to the last timestamp in the most @@ -168,14 +175,14 @@ The module defines the following items: .. versionchanged:: 3.6 Accepts a :term:`path-like object`. - .. versionchanged:: 3.12 - Remove the ``filename`` attribute, use the :attr:`~GzipFile.name` - attribute instead. - .. deprecated:: 3.9 Opening :class:`GzipFile` for writing without specifying the *mode* argument is deprecated. + .. versionchanged:: 3.12 + Remove the ``filename`` attribute, use the :attr:`~GzipFile.name` + attribute instead. + .. function:: compress(data, compresslevel=9, *, mtime=None) diff --git a/Doc/library/lzma.rst b/Doc/library/lzma.rst index 0d69c3bc01d1e24..74bf2670f9def68 100644 --- a/Doc/library/lzma.rst +++ b/Doc/library/lzma.rst @@ -104,7 +104,7 @@ Reading and writing compressed files and :meth:`~io.IOBase.truncate`. Iteration and the :keyword:`with` statement are supported. - The following method is also provided: + The following method and attributes are also provided: .. method:: peek(size=-1) @@ -117,6 +117,20 @@ Reading and writing compressed files file object (e.g. if the :class:`LZMAFile` was constructed by passing a file object for *filename*). + .. attribute:: mode + + ``'rb'`` for reading and ``'wb'`` for writing. + + .. versionadded:: 3.13 + + .. attribute:: name + + The lzma file name. Equivalent to the :attr:`~io.FileIO.name` + attribute of the underlying :term:`file object`. + + .. versionadded:: 3.13 + + .. versionchanged:: 3.4 Added support for the ``"x"`` and ``"xb"`` modes. diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index afcad9bf7229341..cf21dee83e6e7ab 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -565,6 +565,10 @@ be finalized; only the internally used file object will be closed. See the .. versionchanged:: 3.3 Return an :class:`io.BufferedReader` object. + .. versionchanged:: 3.13 + The returned :class:`io.BufferedReader` object has the :attr:`!mode` + attribute which is always equal to ``'rb'``. + .. attribute:: TarFile.errorlevel :type: int diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index ee53f162ac90804..6192689c3a1194d 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -301,6 +301,10 @@ ZipFile Objects attempting to read or write other files in the ZIP file will raise a :exc:`ValueError`. + In both cases the file-like object has also attributes :attr:`!name`, + which is equivalent to the name of a file within the archive, and + :attr:`!mode`, which is ``'rb'`` or ``'wb'`` depending on the input mode. + When writing a file, if the file size is not known in advance but may exceed 2 GiB, pass ``force_zip64=True`` to ensure that the header format is capable of supporting large files. If the file size is known in advance, @@ -325,6 +329,12 @@ ZipFile Objects Calling :meth:`.open` on a closed ZipFile will raise a :exc:`ValueError`. Previously, a :exc:`RuntimeError` was raised. + .. versionchanged:: 3.13 + Added attributes :attr:`!name` and :attr:`!mode` for the writeable + file-like object. + The value of the :attr:`!mode` attribute for the readable file-like + object was changed from ``'r'`` to ``'rb'``. + .. method:: ZipFile.extract(member, path=None, pwd=None) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 0f0fca5d23597b6..5be562030b507b2 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -206,6 +206,11 @@ Other Language Changes (Contributed by Victor Stinner in :gh:`114570`.) +* Added :attr:`!name` and :attr:`!mode` attributes for compressed + and archived file-like objects in modules :mod:`bz2`, :mod:`lzma`, + :mod:`tarfile` and :mod:`zipfile`. + (Contributed by Serhiy Storchaka in :gh:`115961`.) + * Allow controlling Expat >=2.6.0 reparse deferral (:cve:`2023-52425`) by adding five new methods: @@ -1605,6 +1610,12 @@ Changes in the Python API than directories only. Users may add a trailing slash to match only directories. +* The value of the :attr:`!mode` attribute of :class:`gzip.GzipFile` was + changed from integer (``1`` or ``2``) to string (``'rb'`` or ``'wb'``). + The value of the :attr:`!mode` attribute of the readable file-like object + returned by :meth:`zipfile.ZipFile.open` was changed from ``'r'`` to ``'rb'``. + (Contributed by Serhiy Storchaka in :gh:`115961`.) + * :c:func:`!PyCode_GetFirstFree` is an unstable API now and has been renamed to :c:func:`PyUnstable_Code_GetFirstFree`. (Contributed by Bogdan Romanyuk in :gh:`115781`.) diff --git a/Lib/bz2.py b/Lib/bz2.py index fabe4f73c8d8085..2420cd019069b4f 100644 --- a/Lib/bz2.py +++ b/Lib/bz2.py @@ -17,7 +17,7 @@ from _bz2 import BZ2Compressor, BZ2Decompressor -_MODE_CLOSED = 0 +# Value 0 no longer used _MODE_READ = 1 # Value 2 no longer used _MODE_WRITE = 3 @@ -54,7 +54,7 @@ def __init__(self, filename, mode="r", *, compresslevel=9): """ self._fp = None self._closefp = False - self._mode = _MODE_CLOSED + self._mode = None if not (1 <= compresslevel <= 9): raise ValueError("compresslevel must be between 1 and 9") @@ -100,7 +100,7 @@ def close(self): May be called more than once without error. Once the file is closed, any other operation on it will raise a ValueError. """ - if self._mode == _MODE_CLOSED: + if self.closed: return try: if self._mode == _MODE_READ: @@ -115,13 +115,21 @@ def close(self): finally: self._fp = None self._closefp = False - self._mode = _MODE_CLOSED self._buffer = None @property def closed(self): """True if this file is closed.""" - return self._mode == _MODE_CLOSED + return self._fp is None + + @property + def name(self): + self._check_not_closed() + return self._fp.name + + @property + def mode(self): + return 'wb' if self._mode == _MODE_WRITE else 'rb' def fileno(self): """Return the file descriptor for the underlying file.""" diff --git a/Lib/gzip.py b/Lib/gzip.py index 1d6faaa82c6a681..0d19c84c59cfa70 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -15,7 +15,8 @@ FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16 -READ, WRITE = 1, 2 +READ = 'rb' +WRITE = 'wb' _COMPRESS_LEVEL_FAST = 1 _COMPRESS_LEVEL_TRADEOFF = 6 diff --git a/Lib/lzma.py b/Lib/lzma.py index 800f52198fbb794..c1e3d33deb69a14 100644 --- a/Lib/lzma.py +++ b/Lib/lzma.py @@ -29,7 +29,7 @@ import _compression -_MODE_CLOSED = 0 +# Value 0 no longer used _MODE_READ = 1 # Value 2 no longer used _MODE_WRITE = 3 @@ -92,7 +92,7 @@ def __init__(self, filename=None, mode="r", *, """ self._fp = None self._closefp = False - self._mode = _MODE_CLOSED + self._mode = None if mode in ("r", "rb"): if check != -1: @@ -137,7 +137,7 @@ def close(self): May be called more than once without error. Once the file is closed, any other operation on it will raise a ValueError. """ - if self._mode == _MODE_CLOSED: + if self.closed: return try: if self._mode == _MODE_READ: @@ -153,12 +153,20 @@ def close(self): finally: self._fp = None self._closefp = False - self._mode = _MODE_CLOSED @property def closed(self): """True if this file is closed.""" - return self._mode == _MODE_CLOSED + return self._fp is None + + @property + def name(self): + self._check_not_closed() + return self._fp.name + + @property + def mode(self): + return 'wb' if self._mode == _MODE_WRITE else 'rb' def fileno(self): """Return the file descriptor for the underlying file.""" diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 78bb10c80820d71..5fc6183ffcf93c3 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -636,6 +636,10 @@ def __init__(self, fileobj, offset, size, name, blockinfo=None): def flush(self): pass + @property + def mode(self): + return 'rb' + def readable(self): return True diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index 772f0eacce28f52..e4d1381be5f340a 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -540,40 +540,54 @@ def testMultiStreamOrdering(self): def testOpenFilename(self): with BZ2File(self.filename, "wb") as f: f.write(b'content') + self.assertEqual(f.name, self.filename) self.assertIsInstance(f.fileno(), int) + self.assertEqual(f.mode, 'wb') self.assertIs(f.readable(), False) self.assertIs(f.writable(), True) self.assertIs(f.seekable(), False) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'wb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) with BZ2File(self.filename, "ab") as f: f.write(b'appendix') + self.assertEqual(f.name, self.filename) self.assertIsInstance(f.fileno(), int) + self.assertEqual(f.mode, 'wb') self.assertIs(f.readable(), False) self.assertIs(f.writable(), True) self.assertIs(f.seekable(), False) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'wb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) with BZ2File(self.filename, 'rb') as f: self.assertEqual(f.read(), b'contentappendix') + self.assertEqual(f.name, self.filename) self.assertIsInstance(f.fileno(), int) + self.assertEqual(f.mode, 'rb') self.assertIs(f.readable(), True) self.assertIs(f.writable(), False) self.assertIs(f.seekable(), True) self.assertIs(f.closed, False) self.assertIs(f.closed, True) with self.assertRaises(ValueError): - f.fileno() + f.name + self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'rb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -582,13 +596,18 @@ def testOpenFileWithName(self): with open(self.filename, 'wb') as raw: with BZ2File(raw, 'wb') as f: f.write(b'content') + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'wb') self.assertIs(f.readable(), False) self.assertIs(f.writable(), True) self.assertIs(f.seekable(), False) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'wb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -596,13 +615,18 @@ def testOpenFileWithName(self): with open(self.filename, 'ab') as raw: with BZ2File(raw, 'ab') as f: f.write(b'appendix') + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'wb') self.assertIs(f.readable(), False) self.assertIs(f.writable(), True) self.assertIs(f.seekable(), False) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'wb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -610,14 +634,18 @@ def testOpenFileWithName(self): with open(self.filename, 'rb') as raw: with BZ2File(raw, 'rb') as f: self.assertEqual(f.read(), b'contentappendix') + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'rb') self.assertIs(f.readable(), True) self.assertIs(f.writable(), False) self.assertIs(f.seekable(), True) self.assertIs(f.closed, False) self.assertIs(f.closed, True) with self.assertRaises(ValueError): - f.fileno() + f.name + self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'rb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -626,61 +654,91 @@ def testOpenFileWithoutName(self): bio = BytesIO() with BZ2File(bio, 'wb') as f: f.write(b'content') + with self.assertRaises(AttributeError): + f.name self.assertRaises(io.UnsupportedOperation, f.fileno) + self.assertEqual(f.mode, 'wb') + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) with BZ2File(bio, 'ab') as f: f.write(b'appendix') + with self.assertRaises(AttributeError): + f.name self.assertRaises(io.UnsupportedOperation, f.fileno) + self.assertEqual(f.mode, 'wb') + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) bio.seek(0) with BZ2File(bio, 'rb') as f: self.assertEqual(f.read(), b'contentappendix') + with self.assertRaises(AttributeError): + f.name self.assertRaises(io.UnsupportedOperation, f.fileno) + self.assertEqual(f.mode, 'rb') with self.assertRaises(ValueError): - f.fileno() + f.name + self.assertRaises(ValueError, f.fileno) def testOpenFileWithIntName(self): fd = os.open(self.filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) with open(fd, 'wb') as raw: with BZ2File(raw, 'wb') as f: f.write(b'content') + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'wb') + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) fd = os.open(self.filename, os.O_WRONLY | os.O_CREAT | os.O_APPEND) with open(fd, 'ab') as raw: with BZ2File(raw, 'ab') as f: f.write(b'appendix') + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'wb') + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) fd = os.open(self.filename, os.O_RDONLY) with open(fd, 'rb') as raw: with BZ2File(raw, 'rb') as f: self.assertEqual(f.read(), b'contentappendix') + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'rb') with self.assertRaises(ValueError): - f.fileno() + f.name + self.assertRaises(ValueError, f.fileno) def testOpenBytesFilename(self): str_filename = self.filename bytes_filename = os.fsencode(str_filename) with BZ2File(bytes_filename, "wb") as f: f.write(self.DATA) + self.assertEqual(f.name, bytes_filename) with BZ2File(bytes_filename, "rb") as f: self.assertEqual(f.read(), self.DATA) + self.assertEqual(f.name, bytes_filename) # Sanity check that we are actually operating on the right file. with BZ2File(str_filename, "rb") as f: self.assertEqual(f.read(), self.DATA) + self.assertEqual(f.name, str_filename) def testOpenPathLikeFilename(self): filename = FakePath(self.filename) with BZ2File(filename, "wb") as f: f.write(self.DATA) + self.assertEqual(f.name, self.filename) with BZ2File(filename, "rb") as f: self.assertEqual(f.read(), self.DATA) + self.assertEqual(f.name, self.filename) def testDecompressLimited(self): """Decompressed data buffering should be limited""" @@ -701,6 +759,9 @@ def testReadBytesIO(self): with BZ2File(bio) as bz2f: self.assertRaises(TypeError, bz2f.read, float()) self.assertEqual(bz2f.read(), self.TEXT) + with self.assertRaises(AttributeError): + bz2.name + self.assertEqual(bz2f.mode, 'rb') self.assertFalse(bio.closed) def testPeekBytesIO(self): @@ -716,6 +777,9 @@ def testWriteBytesIO(self): with BZ2File(bio, "w") as bz2f: self.assertRaises(TypeError, bz2f.write) bz2f.write(self.TEXT) + with self.assertRaises(AttributeError): + bz2.name + self.assertEqual(bz2f.mode, 'wb') self.assertEqual(ext_decompress(bio.getvalue()), self.TEXT) self.assertFalse(bio.closed) diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index d220c7d06e50c97..cf801278da9e9bd 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -587,6 +587,8 @@ def test_fileobj_from_fdopen(self): self.assertRaises(AttributeError, f.fileno) def test_fileobj_mode(self): + self.assertEqual(gzip.READ, 'rb') + self.assertEqual(gzip.WRITE, 'wb') gzip.GzipFile(self.filename, "wb").close() with open(self.filename, "r+b") as f: with gzip.GzipFile(fileobj=f, mode='r') as g: diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index db290e139327e02..22478c14fb4a65e 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -551,19 +551,25 @@ def test_init_with_PathLike_filename(self): with TempFile(filename, COMPRESSED_XZ): with LZMAFile(filename) as f: self.assertEqual(f.read(), INPUT) + self.assertEqual(f.name, TESTFN) with LZMAFile(filename, "a") as f: f.write(INPUT) + self.assertEqual(f.name, TESTFN) with LZMAFile(filename) as f: self.assertEqual(f.read(), INPUT * 2) + self.assertEqual(f.name, TESTFN) def test_init_with_filename(self): with TempFile(TESTFN, COMPRESSED_XZ): with LZMAFile(TESTFN) as f: - pass + self.assertEqual(f.name, TESTFN) + self.assertEqual(f.mode, 'rb') with LZMAFile(TESTFN, "w") as f: - pass + self.assertEqual(f.name, TESTFN) + self.assertEqual(f.mode, 'wb') with LZMAFile(TESTFN, "a") as f: - pass + self.assertEqual(f.name, TESTFN) + self.assertEqual(f.mode, 'wb') def test_init_mode(self): with TempFile(TESTFN): @@ -586,6 +592,7 @@ def test_init_with_x_mode(self): unlink(TESTFN) with LZMAFile(TESTFN, mode) as f: pass + self.assertEqual(f.mode, 'wb') with self.assertRaises(FileExistsError): LZMAFile(TESTFN, mode) @@ -865,13 +872,18 @@ def test_read_from_file(self): with LZMAFile(TESTFN) as f: self.assertEqual(f.read(), INPUT) self.assertEqual(f.read(), b"") + self.assertEqual(f.name, TESTFN) self.assertIsInstance(f.fileno(), int) + self.assertEqual(f.mode, 'rb') self.assertIs(f.readable(), True) self.assertIs(f.writable(), False) self.assertIs(f.seekable(), True) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'rb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -882,6 +894,7 @@ def test_read_from_file_with_bytes_filename(self): with LZMAFile(bytes_filename) as f: self.assertEqual(f.read(), INPUT) self.assertEqual(f.read(), b"") + self.assertEqual(f.name, bytes_filename) def test_read_from_fileobj(self): with TempFile(TESTFN, COMPRESSED_XZ): @@ -889,13 +902,18 @@ def test_read_from_fileobj(self): with LZMAFile(raw) as f: self.assertEqual(f.read(), INPUT) self.assertEqual(f.read(), b"") + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'rb') self.assertIs(f.readable(), True) self.assertIs(f.writable(), False) self.assertIs(f.seekable(), True) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'rb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -907,13 +925,18 @@ def test_read_from_fileobj_with_int_name(self): with LZMAFile(raw) as f: self.assertEqual(f.read(), INPUT) self.assertEqual(f.read(), b"") + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'rb') self.assertIs(f.readable(), True) self.assertIs(f.writable(), False) self.assertIs(f.seekable(), True) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'rb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -1045,6 +1068,8 @@ def test_write(self): with BytesIO() as dst: with LZMAFile(dst, "w") as f: f.write(INPUT) + with self.assertRaises(AttributeError): + f.name expected = lzma.compress(INPUT) self.assertEqual(dst.getvalue(), expected) with BytesIO() as dst: @@ -1081,23 +1106,31 @@ def test_write_append(self): with BytesIO() as dst: with LZMAFile(dst, "w") as f: f.write(part1) + self.assertEqual(f.mode, 'wb') with LZMAFile(dst, "a") as f: f.write(part2) + self.assertEqual(f.mode, 'wb') with LZMAFile(dst, "a") as f: f.write(part3) + self.assertEqual(f.mode, 'wb') self.assertEqual(dst.getvalue(), expected) def test_write_to_file(self): try: with LZMAFile(TESTFN, "w") as f: f.write(INPUT) + self.assertEqual(f.name, TESTFN) self.assertIsInstance(f.fileno(), int) + self.assertEqual(f.mode, 'wb') self.assertIs(f.readable(), False) self.assertIs(f.writable(), True) self.assertIs(f.seekable(), False) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'wb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -1113,6 +1146,7 @@ def test_write_to_file_with_bytes_filename(self): try: with LZMAFile(bytes_filename, "w") as f: f.write(INPUT) + self.assertEqual(f.name, bytes_filename) expected = lzma.compress(INPUT) with open(TESTFN, "rb") as f: self.assertEqual(f.read(), expected) @@ -1124,13 +1158,18 @@ def test_write_to_fileobj(self): with open(TESTFN, "wb") as raw: with LZMAFile(raw, "w") as f: f.write(INPUT) + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'wb') self.assertIs(f.readable(), False) self.assertIs(f.writable(), True) self.assertIs(f.seekable(), False) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'wb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -1147,13 +1186,18 @@ def test_write_to_fileobj_with_int_name(self): with open(fd, 'wb') as raw: with LZMAFile(raw, "w") as f: f.write(INPUT) + self.assertEqual(f.name, raw.name) self.assertEqual(f.fileno(), raw.fileno()) + self.assertEqual(f.mode, 'wb') self.assertIs(f.readable(), False) self.assertIs(f.writable(), True) self.assertIs(f.seekable(), False) self.assertIs(f.closed, False) self.assertIs(f.closed, True) + with self.assertRaises(ValueError): + f.name self.assertRaises(ValueError, f.fileno) + self.assertEqual(f.mode, 'wb') self.assertRaises(ValueError, f.readable) self.assertRaises(ValueError, f.writable) self.assertRaises(ValueError, f.seekable) @@ -1172,10 +1216,13 @@ def test_write_append_to_file(self): try: with LZMAFile(TESTFN, "w") as f: f.write(part1) + self.assertEqual(f.mode, 'wb') with LZMAFile(TESTFN, "a") as f: f.write(part2) + self.assertEqual(f.mode, 'wb') with LZMAFile(TESTFN, "a") as f: f.write(part3) + self.assertEqual(f.mode, 'wb') with open(TESTFN, "rb") as f: self.assertEqual(f.read(), expected) finally: @@ -1373,11 +1420,13 @@ def test_with_pathlike_filename(self): with TempFile(filename): with lzma.open(filename, "wb") as f: f.write(INPUT) + self.assertEqual(f.name, TESTFN) with open(filename, "rb") as f: file_data = lzma.decompress(f.read()) self.assertEqual(file_data, INPUT) with lzma.open(filename, "rb") as f: self.assertEqual(f.read(), INPUT) + self.assertEqual(f.name, TESTFN) def test_bad_params(self): # Test invalid parameter combinations. diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index c2abc7ef9698fb8..c9c1097963a885e 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -513,6 +513,7 @@ def test_extractfile_attrs(self): with self.tar.extractfile(file) as fobj: self.assertEqual(fobj.name, 'ustar/regtype') self.assertRaises(AttributeError, fobj.fileno) + self.assertEqual(fobj.mode, 'rb') self.assertIs(fobj.readable(), True) self.assertIs(fobj.writable(), False) if self.is_stream: @@ -523,6 +524,7 @@ def test_extractfile_attrs(self): self.assertIs(fobj.closed, True) self.assertEqual(fobj.name, 'ustar/regtype') self.assertRaises(AttributeError, fobj.fileno) + self.assertEqual(fobj.mode, 'rb') self.assertIs(fobj.readable(), True) self.assertIs(fobj.writable(), False) if self.is_stream: @@ -533,11 +535,8 @@ def test_extractfile_attrs(self): class MiscReadTestBase(CommonReadTest): is_stream = False - def requires_name_attribute(self): - pass def test_no_name_argument(self): - self.requires_name_attribute() with open(self.tarname, "rb") as fobj: self.assertIsInstance(fobj.name, str) with tarfile.open(fileobj=fobj, mode=self.mode) as tar: @@ -570,7 +569,6 @@ def test_int_name_attribute(self): self.assertIsNone(tar.name) def test_bytes_name_attribute(self): - self.requires_name_attribute() tarname = os.fsencode(self.tarname) with open(tarname, 'rb') as fobj: self.assertIsInstance(fobj.name, bytes) @@ -839,12 +837,10 @@ class GzipMiscReadTest(GzipTest, MiscReadTestBase, unittest.TestCase): pass class Bz2MiscReadTest(Bz2Test, MiscReadTestBase, unittest.TestCase): - def requires_name_attribute(self): - self.skipTest("BZ2File have no name attribute") + pass class LzmaMiscReadTest(LzmaTest, MiscReadTestBase, unittest.TestCase): - def requires_name_attribute(self): - self.skipTest("LZMAFile have no name attribute") + pass class StreamReadTest(CommonReadTest, unittest.TestCase): diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index a605aa1f14fe3f6..423974aada4ac1a 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -389,7 +389,6 @@ def test_repr(self): with zipfp.open(fname) as zipopen: r = repr(zipopen) self.assertIn('name=%r' % fname, r) - self.assertIn("mode='r'", r) if self.compression != zipfile.ZIP_STORED: self.assertIn('compress_type=', r) self.assertIn('[closed]', repr(zipopen)) @@ -455,14 +454,14 @@ def test_zipextfile_attrs(self): with zipfp.open(fname) as fid: self.assertEqual(fid.name, fname) self.assertRaises(io.UnsupportedOperation, fid.fileno) - self.assertEqual(fid.mode, 'r') + self.assertEqual(fid.mode, 'rb') self.assertIs(fid.readable(), True) self.assertIs(fid.writable(), False) self.assertIs(fid.seekable(), True) self.assertIs(fid.closed, False) self.assertIs(fid.closed, True) self.assertEqual(fid.name, fname) - self.assertEqual(fid.mode, 'r') + self.assertEqual(fid.mode, 'rb') self.assertRaises(io.UnsupportedOperation, fid.fileno) self.assertRaises(ValueError, fid.readable) self.assertIs(fid.writable(), False) @@ -1308,12 +1307,16 @@ def test_zipwritefile_attrs(self): fname = "somefile.txt" with zipfile.ZipFile(TESTFN2, mode="w", compression=self.compression) as zipfp: with zipfp.open(fname, 'w') as fid: + self.assertEqual(fid.name, fname) self.assertRaises(io.UnsupportedOperation, fid.fileno) + self.assertEqual(fid.mode, 'wb') self.assertIs(fid.readable(), False) self.assertIs(fid.writable(), True) self.assertIs(fid.seekable(), False) self.assertIs(fid.closed, False) self.assertIs(fid.closed, True) + self.assertEqual(fid.name, fname) + self.assertEqual(fid.mode, 'wb') self.assertRaises(io.UnsupportedOperation, fid.fileno) self.assertIs(fid.readable(), False) self.assertIs(fid.writable(), True) diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index e4603b559f5962d..31ef9bb1ad925e3 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -940,7 +940,7 @@ def __repr__(self): result = ['<%s.%s' % (self.__class__.__module__, self.__class__.__qualname__)] if not self.closed: - result.append(' name=%r mode=%r' % (self.name, self.mode)) + result.append(' name=%r' % (self.name,)) if self._compress_type != ZIP_STORED: result.append(' compress_type=%s' % compressor_names.get(self._compress_type, @@ -1217,6 +1217,14 @@ def __init__(self, zf, zinfo, zip64): def _fileobj(self): return self._zipfile.fp + @property + def name(self): + return self._zinfo.filename + + @property + def mode(self): + return 'wb' + def writable(self): return True @@ -1687,7 +1695,7 @@ def open(self, name, mode="r", pwd=None, *, force_zip64=False): else: pwd = None - return ZipExtFile(zef_file, mode, zinfo, pwd, True) + return ZipExtFile(zef_file, mode + 'b', zinfo, pwd, True) except: zef_file.close() raise diff --git a/Misc/NEWS.d/next/Library/2024-02-28-10-41-24.gh-issue-115961.P-_DU0.rst b/Misc/NEWS.d/next/Library/2024-02-28-10-41-24.gh-issue-115961.P-_DU0.rst new file mode 100644 index 000000000000000..eef7eb8687b44f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-02-28-10-41-24.gh-issue-115961.P-_DU0.rst @@ -0,0 +1,7 @@ +Added :attr:`!name` and :attr:`!mode` attributes for compressed and archived +file-like objects in modules :mod:`bz2`, :mod:`lzma`, :mod:`tarfile` and +:mod:`zipfile`. The value of the :attr:`!mode` attribute of +:class:`gzip.GzipFile` was changed from integer (``1`` or ``2``) to string +(``'rb'`` or ``'wb'``). The value of the :attr:`!mode` attribute of the +readable file-like object returned by :meth:`zipfile.ZipFile.open` was +changed from ``'r'`` to ``'rb'``. From 1446024124fb98c3051199760380685f8a2fd127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Sun, 21 Apr 2024 20:03:46 +0200 Subject: [PATCH 081/127] Docs: replace Harry Potter reference with Monty Python (#118130) --- Doc/library/doctest.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst index a643a0e7e313bf5..5f7d10a6dce0371 100644 --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -800,18 +800,18 @@ guarantee about output. For example, when printing a set, Python doesn't guarantee that the element is printed in any particular order, so a test like :: >>> foo() - {"Hermione", "Harry"} + {"spam", "eggs"} is vulnerable! One workaround is to do :: - >>> foo() == {"Hermione", "Harry"} + >>> foo() == {"spam", "eggs"} True instead. Another is to do :: >>> d = sorted(foo()) >>> d - ['Harry', 'Hermione'] + ['eggs', 'spam'] There are others, but you get the idea. From 8b541c017ea92040add608b3e0ef8dc85e9e6060 Mon Sep 17 00:00:00 2001 From: Dino Viehland Date: Sun, 21 Apr 2024 22:57:05 -0700 Subject: [PATCH 082/127] gh-112075: Make instance attributes stored in inline "dict" thread safe (#114742) Make instance attributes stored in inline "dict" thread safe on free-threaded builds --- Include/cpython/object.h | 1 + Include/internal/pycore_dict.h | 19 +- Include/internal/pycore_object.h | 16 +- .../internal/pycore_pyatomic_ft_wrappers.h | 14 + Lib/test/test_class.py | 9 + Objects/dictobject.c | 385 ++++++++++++++---- Objects/object.c | 45 +- Objects/typeobject.c | 30 +- Python/bytecodes.c | 15 +- Python/executor_cases.c.h | 10 +- Python/generated_cases.c.h | 13 +- Python/specialize.c | 3 +- Tools/cases_generator/analyzer.py | 1 + 13 files changed, 419 insertions(+), 142 deletions(-) diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 2797051281f3b4a..a8f57827a964cdf 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -493,6 +493,7 @@ do { \ PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj); PyAPI_FUNC(int) PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg); +PyAPI_FUNC(void) _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict); PyAPI_FUNC(void) PyObject_ClearManagedDict(PyObject *obj); #define TYPE_MAX_WATCHERS 8 diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index fba0dfc40714ec7..f33026dbd6be586 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -1,4 +1,3 @@ - #ifndef Py_INTERNAL_DICT_H #define Py_INTERNAL_DICT_H #ifdef __cplusplus @@ -9,9 +8,10 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#include "pycore_freelist.h" // _PyFreeListState -#include "pycore_identifier.h" // _Py_Identifier -#include "pycore_object.h" // PyManagedDictPointer +#include "pycore_freelist.h" // _PyFreeListState +#include "pycore_identifier.h" // _Py_Identifier +#include "pycore_object.h" // PyManagedDictPointer +#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_SSIZE_ACQUIRE // Unsafe flavor of PyDict_GetItemWithError(): no error checking extern PyObject* _PyDict_GetItemWithError(PyObject *dp, PyObject *key); @@ -249,7 +249,7 @@ _PyDict_NotifyEvent(PyInterpreterState *interp, return DICT_NEXT_VERSION(interp) | (mp->ma_version_tag & DICT_WATCHER_AND_MODIFICATION_MASK); } -extern PyDictObject *_PyObject_MakeDictFromInstanceAttributes(PyObject *obj); +extern PyDictObject *_PyObject_MaterializeManagedDict(PyObject *obj); PyAPI_FUNC(PyObject *)_PyDict_FromItems( PyObject *const *keys, Py_ssize_t keys_offset, @@ -277,7 +277,6 @@ _PyDictValues_AddToInsertionOrder(PyDictValues *values, Py_ssize_t ix) static inline size_t shared_keys_usable_size(PyDictKeysObject *keys) { -#ifdef Py_GIL_DISABLED // dk_usable will decrease for each instance that is created and each // value that is added. dk_nentries will increase for each value that // is added. We want to always return the right value or larger. @@ -285,11 +284,9 @@ shared_keys_usable_size(PyDictKeysObject *keys) // second, and conversely here we read dk_usable first and dk_entries // second (to avoid the case where we read entries before the increment // and read usable after the decrement) - return (size_t)(_Py_atomic_load_ssize_acquire(&keys->dk_usable) + - _Py_atomic_load_ssize_acquire(&keys->dk_nentries)); -#else - return (size_t)keys->dk_nentries + (size_t)keys->dk_usable; -#endif + Py_ssize_t dk_usable = FT_ATOMIC_LOAD_SSIZE_ACQUIRE(keys->dk_usable); + Py_ssize_t dk_nentries = FT_ATOMIC_LOAD_SSIZE_ACQUIRE(keys->dk_nentries); + return dk_nentries + dk_usable; } static inline size_t diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 512f7a35f50e382..88b052f4544b155 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -12,6 +12,7 @@ extern "C" { #include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() #include "pycore_emscripten_trampoline.h" // _PyCFunction_TrampolineCall() #include "pycore_interp.h" // PyInterpreterState.gc +#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_PTR_RELAXED #include "pycore_pystate.h" // _PyInterpreterState_GET() /* Check if an object is consistent. For example, ensure that the reference @@ -659,10 +660,10 @@ extern PyObject* _PyType_GetDocFromInternalDoc(const char *, const char *); extern PyObject* _PyType_GetTextSignatureFromInternalDoc(const char *, const char *, int); void _PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp); -extern int _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, - PyObject *name, PyObject *value); -PyObject * _PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values, - PyObject *name); +extern int _PyObject_StoreInstanceAttribute(PyObject *obj, + PyObject *name, PyObject *value); +extern bool _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, + PyObject **attr); #ifdef Py_GIL_DISABLED # define MANAGED_DICT_OFFSET (((Py_ssize_t)sizeof(PyObject *))*-1) @@ -683,6 +684,13 @@ _PyObject_ManagedDictPointer(PyObject *obj) return (PyManagedDictPointer *)((char *)obj + MANAGED_DICT_OFFSET); } +static inline PyDictObject * +_PyObject_GetManagedDict(PyObject *obj) +{ + PyManagedDictPointer *dorv = _PyObject_ManagedDictPointer(obj); + return (PyDictObject *)FT_ATOMIC_LOAD_PTR_RELAXED(dorv->dict); +} + static inline PyDictValues * _PyObject_InlineValues(PyObject *obj) { diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h b/Include/internal/pycore_pyatomic_ft_wrappers.h index fed5d6e0ec2c54e..bbfc462a733d0e3 100644 --- a/Include/internal/pycore_pyatomic_ft_wrappers.h +++ b/Include/internal/pycore_pyatomic_ft_wrappers.h @@ -21,7 +21,10 @@ extern "C" { #ifdef Py_GIL_DISABLED #define FT_ATOMIC_LOAD_PTR(value) _Py_atomic_load_ptr(&value) +#define FT_ATOMIC_STORE_PTR(value, new_value) _Py_atomic_store_ptr(&value, new_value) #define FT_ATOMIC_LOAD_SSIZE(value) _Py_atomic_load_ssize(&value) +#define FT_ATOMIC_LOAD_SSIZE_ACQUIRE(value) \ + _Py_atomic_load_ssize_acquire(&value) #define FT_ATOMIC_LOAD_SSIZE_RELAXED(value) \ _Py_atomic_load_ssize_relaxed(&value) #define FT_ATOMIC_STORE_PTR(value, new_value) \ @@ -30,6 +33,12 @@ extern "C" { _Py_atomic_load_ptr_acquire(&value) #define FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(value) \ _Py_atomic_load_uintptr_acquire(&value) +#define FT_ATOMIC_LOAD_PTR_RELAXED(value) \ + _Py_atomic_load_ptr_relaxed(&value) +#define FT_ATOMIC_LOAD_UINT8(value) \ + _Py_atomic_load_uint8(&value) +#define FT_ATOMIC_STORE_UINT8(value, new_value) \ + _Py_atomic_store_uint8(&value, new_value) #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) \ _Py_atomic_store_ptr_relaxed(&value, new_value) #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) \ @@ -43,11 +52,16 @@ extern "C" { #else #define FT_ATOMIC_LOAD_PTR(value) value +#define FT_ATOMIC_STORE_PTR(value, new_value) value = new_value #define FT_ATOMIC_LOAD_SSIZE(value) value +#define FT_ATOMIC_LOAD_SSIZE_ACQUIRE(value) value #define FT_ATOMIC_LOAD_SSIZE_RELAXED(value) value #define FT_ATOMIC_STORE_PTR(value, new_value) value = new_value #define FT_ATOMIC_LOAD_PTR_ACQUIRE(value) value #define FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(value) value +#define FT_ATOMIC_LOAD_PTR_RELAXED(value) value +#define FT_ATOMIC_LOAD_UINT8(value) value +#define FT_ATOMIC_STORE_UINT8(value, new_value) value = new_value #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value #define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) value = new_value diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index a9cfd8df6918453..5885db84b66b016 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -873,6 +873,15 @@ def __init__(self): obj.foo = None # Aborted here self.assertEqual(obj.__dict__, {"foo":None}) + def test_store_attr_deleted_dict(self): + class Foo: + pass + + f = Foo() + del f.__dict__ + f.a = 3 + self.assertEqual(f.a, 3) + if __name__ == '__main__': unittest.main() diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 4e696419eb5eb0a..2644516bc307706 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1752,7 +1752,7 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp, uint64_t new_version = _PyDict_NotifyEvent( interp, PyDict_EVENT_MODIFIED, mp, key, value); if (_PyDict_HasSplitTable(mp)) { - mp->ma_values->values[ix] = value; + STORE_SPLIT_VALUE(mp, ix, value); if (old_value == NULL) { _PyDictValues_AddToInsertionOrder(mp->ma_values, ix); mp->ma_used++; @@ -2514,7 +2514,7 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix, mp->ma_version_tag = new_version; if (_PyDict_HasSplitTable(mp)) { assert(old_value == mp->ma_values->values[ix]); - mp->ma_values->values[ix] = NULL; + STORE_SPLIT_VALUE(mp, ix, NULL); assert(ix < SHARED_KEYS_MAX_SIZE); /* Update order */ delete_index_from_values(mp->ma_values, ix); @@ -4226,7 +4226,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu assert(_PyDict_HasSplitTable(mp)); assert(mp->ma_values->values[ix] == NULL); MAINTAIN_TRACKING(mp, key, value); - mp->ma_values->values[ix] = Py_NewRef(value); + STORE_SPLIT_VALUE(mp, ix, Py_NewRef(value)); _PyDictValues_AddToInsertionOrder(mp->ma_values, ix); mp->ma_used++; mp->ma_version_tag = new_version; @@ -6616,28 +6616,79 @@ make_dict_from_instance_attributes(PyInterpreterState *interp, return res; } -PyDictObject * -_PyObject_MakeDictFromInstanceAttributes(PyObject *obj) +static PyDictObject * +materialize_managed_dict_lock_held(PyObject *obj) { + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj); + + OBJECT_STAT_INC(dict_materialized_on_request); + PyDictValues *values = _PyObject_InlineValues(obj); PyInterpreterState *interp = _PyInterpreterState_GET(); PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); OBJECT_STAT_INC(dict_materialized_on_request); - return make_dict_from_instance_attributes(interp, keys, values); + PyDictObject *dict = make_dict_from_instance_attributes(interp, keys, values); + FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict, + (PyDictObject *)dict); + return dict; } +PyDictObject * +_PyObject_MaterializeManagedDict(PyObject *obj) +{ + PyDictObject *dict = _PyObject_GetManagedDict(obj); + if (dict != NULL) { + return dict; + } + Py_BEGIN_CRITICAL_SECTION(obj); -int -_PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, +#ifdef Py_GIL_DISABLED + dict = _PyObject_GetManagedDict(obj); + if (dict != NULL) { + // We raced with another thread creating the dict + goto exit; + } +#endif + dict = materialize_managed_dict_lock_held(obj); + +#ifdef Py_GIL_DISABLED +exit: +#endif + Py_END_CRITICAL_SECTION(); + return dict; +} + +static int +set_or_del_lock_held(PyDictObject *dict, PyObject *name, PyObject *value) +{ + if (value == NULL) { + Py_hash_t hash; + if (!PyUnicode_CheckExact(name) || (hash = unicode_get_hash(name)) == -1) { + hash = PyObject_Hash(name); + if (hash == -1) + return -1; + } + return delitem_knownhash_lock_held((PyObject *)dict, name, hash); + } else { + return setitem_lock_held(dict, name, value); + } +} + +// Called with either the object's lock or the dict's lock held +// depending on whether or not a dict has been materialized for +// the object. +static int +store_instance_attr_lock_held(PyObject *obj, PyDictValues *values, PyObject *name, PyObject *value) { - PyInterpreterState *interp = _PyInterpreterState_GET(); PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); assert(keys != NULL); assert(values != NULL); assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES); Py_ssize_t ix = DKIX_EMPTY; + PyDictObject *dict = _PyObject_GetManagedDict(obj); + assert(dict == NULL || ((PyDictObject *)dict)->ma_values == values); if (PyUnicode_CheckExact(name)) { Py_hash_t hash = unicode_get_hash(name); if (hash == -1) { @@ -6674,25 +6725,33 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, } #endif } - PyDictObject *dict = _PyObject_ManagedDictPointer(obj)->dict; + if (ix == DKIX_EMPTY) { + int res; if (dict == NULL) { - dict = make_dict_from_instance_attributes( - interp, keys, values); - if (dict == NULL) { + // Make the dict but don't publish it in the object + // so that no one else will see it. + dict = make_dict_from_instance_attributes(PyInterpreterState_Get(), keys, values); + if (dict == NULL || + set_or_del_lock_held(dict, name, value) < 0) { + Py_XDECREF(dict); return -1; } - _PyObject_ManagedDictPointer(obj)->dict = (PyDictObject *)dict; - } - if (value == NULL) { - return PyDict_DelItem((PyObject *)dict, name); - } - else { - return PyDict_SetItem((PyObject *)dict, name, value); + + FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict, + (PyDictObject *)dict); + return 0; } + + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(dict); + + res = set_or_del_lock_held (dict, name, value); + return res; } + PyObject *old_value = values->values[ix]; - values->values[ix] = Py_XNewRef(value); + FT_ATOMIC_STORE_PTR_RELEASE(values->values[ix], Py_XNewRef(value)); + if (old_value == NULL) { if (value == NULL) { PyErr_Format(PyExc_AttributeError, @@ -6719,6 +6778,72 @@ _PyObject_StoreInstanceAttribute(PyObject *obj, PyDictValues *values, return 0; } +static inline int +store_instance_attr_dict(PyObject *obj, PyDictObject *dict, PyObject *name, PyObject *value) +{ + PyDictValues *values = _PyObject_InlineValues(obj); + int res; + Py_BEGIN_CRITICAL_SECTION(dict); + if (dict->ma_values == values) { + res = store_instance_attr_lock_held(obj, values, name, value); + } + else { + res = set_or_del_lock_held(dict, name, value); + } + Py_END_CRITICAL_SECTION(); + return res; +} + +int +_PyObject_StoreInstanceAttribute(PyObject *obj, PyObject *name, PyObject *value) +{ + PyDictValues *values = _PyObject_InlineValues(obj); + if (!FT_ATOMIC_LOAD_UINT8(values->valid)) { + PyDictObject *dict = _PyObject_GetManagedDict(obj); + if (dict == NULL) { + dict = (PyDictObject *)PyObject_GenericGetDict(obj, NULL); + if (dict == NULL) { + return -1; + } + int res = store_instance_attr_dict(obj, dict, name, value); + Py_DECREF(dict); + return res; + } + return store_instance_attr_dict(obj, dict, name, value); + } + +#ifdef Py_GIL_DISABLED + // We have a valid inline values, at least for now... There are two potential + // races with having the values become invalid. One is the dictionary + // being detached from the object. The other is if someone is inserting + // into the dictionary directly and therefore causing it to resize. + // + // If we haven't materialized the dictionary yet we lock on the object, which + // will also be used to prevent the dictionary from being materialized while + // we're doing the insertion. If we race and the dictionary gets created + // then we'll need to release the object lock and lock the dictionary to + // prevent resizing. + PyDictObject *dict = _PyObject_GetManagedDict(obj); + if (dict == NULL) { + int res; + Py_BEGIN_CRITICAL_SECTION(obj); + dict = _PyObject_GetManagedDict(obj); + + if (dict == NULL) { + res = store_instance_attr_lock_held(obj, values, name, value); + } + Py_END_CRITICAL_SECTION(); + + if (dict == NULL) { + return res; + } + } + return store_instance_attr_dict(obj, dict, name, value); +#else + return store_instance_attr_lock_held(obj, values, name, value); +#endif +} + /* Sanity check for managed dicts */ #if 0 #define CHECK(val) assert(val); if (!(val)) { return 0; } @@ -6750,19 +6875,79 @@ _PyObject_ManagedDictValidityCheck(PyObject *obj) } #endif -PyObject * -_PyObject_GetInstanceAttribute(PyObject *obj, PyDictValues *values, - PyObject *name) +// Attempts to get an instance attribute from the inline values. Returns true +// if successful, or false if the caller needs to lookup in the dictionary. +bool +_PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr) { assert(PyUnicode_CheckExact(name)); + PyDictValues *values = _PyObject_InlineValues(obj); + if (!FT_ATOMIC_LOAD_UINT8(values->valid)) { + return false; + } + PyDictKeysObject *keys = CACHED_KEYS(Py_TYPE(obj)); assert(keys != NULL); Py_ssize_t ix = _PyDictKeys_StringLookup(keys, name); if (ix == DKIX_EMPTY) { - return NULL; + *attr = NULL; + return true; + } + +#ifdef Py_GIL_DISABLED + PyObject *value = _Py_atomic_load_ptr_relaxed(&values->values[ix]); + if (value == NULL || _Py_TryIncrefCompare(&values->values[ix], value)) { + *attr = value; + return true; + } + + PyDictObject *dict = _PyObject_GetManagedDict(obj); + if (dict == NULL) { + // No dict, lock the object to prevent one from being + // materialized... + bool success = false; + Py_BEGIN_CRITICAL_SECTION(obj); + + dict = _PyObject_GetManagedDict(obj); + if (dict == NULL) { + // Still no dict, we can read from the values + assert(values->valid); + value = values->values[ix]; + *attr = Py_XNewRef(value); + success = true; + } + + Py_END_CRITICAL_SECTION(); + + if (success) { + return true; + } } + + // We have a dictionary, we'll need to lock it to prevent + // the values from being resized. + assert(dict != NULL); + + bool success; + Py_BEGIN_CRITICAL_SECTION(dict); + + if (dict->ma_values == values && FT_ATOMIC_LOAD_UINT8(values->valid)) { + value = _Py_atomic_load_ptr_relaxed(&values->values[ix]); + *attr = Py_XNewRef(value); + success = true; + } else { + // Caller needs to lookup from the dictionary + success = false; + } + + Py_END_CRITICAL_SECTION(); + + return success; +#else PyObject *value = values->values[ix]; - return Py_XNewRef(value); + *attr = Py_XNewRef(value); + return true; +#endif } int @@ -6775,20 +6960,19 @@ _PyObject_IsInstanceDictEmpty(PyObject *obj) PyDictObject *dict; if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) { PyDictValues *values = _PyObject_InlineValues(obj); - if (values->valid) { + if (FT_ATOMIC_LOAD_UINT8(values->valid)) { PyDictKeysObject *keys = CACHED_KEYS(tp); for (Py_ssize_t i = 0; i < keys->dk_nentries; i++) { - if (values->values[i] != NULL) { + if (FT_ATOMIC_LOAD_PTR_RELAXED(values->values[i]) != NULL) { return 0; } } return 1; } - dict = _PyObject_ManagedDictPointer(obj)->dict; + dict = _PyObject_GetManagedDict(obj); } else if (tp->tp_flags & Py_TPFLAGS_MANAGED_DICT) { - PyManagedDictPointer* managed_dict = _PyObject_ManagedDictPointer(obj); - dict = managed_dict->dict; + dict = _PyObject_GetManagedDict(obj); } else { PyObject **dictptr = _PyObject_ComputedDictPointer(obj); @@ -6820,53 +7004,115 @@ PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg) return 0; } +static void +set_dict_inline_values(PyObject *obj, PyDictObject *new_dict) +{ + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj); + + PyDictValues *values = _PyObject_InlineValues(obj); + + Py_XINCREF(new_dict); + FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict, new_dict); + + if (values->valid) { + FT_ATOMIC_STORE_UINT8(values->valid, 0); + for (Py_ssize_t i = 0; i < values->capacity; i++) { + Py_CLEAR(values->values[i]); + } + } +} + void -PyObject_ClearManagedDict(PyObject *obj) +_PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict) { assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); assert(_PyObject_InlineValuesConsistencyCheck(obj)); PyTypeObject *tp = Py_TYPE(obj); if (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) { - PyDictObject *dict = _PyObject_ManagedDictPointer(obj)->dict; - if (dict) { - _PyDict_DetachFromObject(dict, obj); - _PyObject_ManagedDictPointer(obj)->dict = NULL; - Py_DECREF(dict); - } - else { - PyDictValues *values = _PyObject_InlineValues(obj); - if (values->valid) { - for (Py_ssize_t i = 0; i < values->capacity; i++) { - Py_CLEAR(values->values[i]); - } - values->valid = 0; + PyDictObject *dict = _PyObject_GetManagedDict(obj); + if (dict == NULL) { +#ifdef Py_GIL_DISABLED + Py_BEGIN_CRITICAL_SECTION(obj); + + dict = _PyObject_ManagedDictPointer(obj)->dict; + if (dict == NULL) { + set_dict_inline_values(obj, (PyDictObject *)new_dict); + } + + Py_END_CRITICAL_SECTION(); + + if (dict == NULL) { + return; } +#else + set_dict_inline_values(obj, (PyDictObject *)new_dict); + return; +#endif } + + Py_BEGIN_CRITICAL_SECTION2(dict, obj); + + // We've locked dict, but the actual dict could have changed + // since we locked it. + dict = _PyObject_ManagedDictPointer(obj)->dict; + + FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict, + (PyDictObject *)Py_XNewRef(new_dict)); + + _PyDict_DetachFromObject(dict, obj); + + Py_END_CRITICAL_SECTION2(); + + Py_XDECREF(dict); } else { - Py_CLEAR(_PyObject_ManagedDictPointer(obj)->dict); + PyDictObject *dict; + + Py_BEGIN_CRITICAL_SECTION(obj); + + dict = _PyObject_ManagedDictPointer(obj)->dict; + + FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict, + (PyDictObject *)Py_XNewRef(new_dict)); + + Py_END_CRITICAL_SECTION(); + + Py_XDECREF(dict); } assert(_PyObject_InlineValuesConsistencyCheck(obj)); } +void +PyObject_ClearManagedDict(PyObject *obj) +{ + _PyObject_SetManagedDict(obj, NULL); +} + int _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj) { - assert(_PyObject_ManagedDictPointer(obj)->dict == mp); - assert(_PyObject_InlineValuesConsistencyCheck(obj)); - if (mp->ma_values == NULL || mp->ma_values != _PyObject_InlineValues(obj)) { + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj); + + if (FT_ATOMIC_LOAD_PTR_RELAXED(mp->ma_values) != _PyObject_InlineValues(obj)) { return 0; } + + // We could be called with an unlocked dict when the caller knows the + // values are already detached, so we assert after inline values check. + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp); assert(mp->ma_values->embedded == 1); assert(mp->ma_values->valid == 1); assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES); - Py_BEGIN_CRITICAL_SECTION(mp); - mp->ma_values = copy_values(mp->ma_values); - _PyObject_InlineValues(obj)->valid = 0; - Py_END_CRITICAL_SECTION(); - if (mp->ma_values == NULL) { + + PyDictValues *values = copy_values(mp->ma_values); + + if (values == NULL) { return -1; } + mp->ma_values = values; + + FT_ATOMIC_STORE_UINT8(_PyObject_InlineValues(obj)->valid, 0); + assert(_PyObject_InlineValuesConsistencyCheck(obj)); ASSERT_CONSISTENT(mp); return 0; @@ -6877,29 +7123,28 @@ PyObject_GenericGetDict(PyObject *obj, void *context) { PyInterpreterState *interp = _PyInterpreterState_GET(); PyTypeObject *tp = Py_TYPE(obj); + PyDictObject *dict; if (_PyType_HasFeature(tp, Py_TPFLAGS_MANAGED_DICT)) { - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(obj); - PyDictObject *dict = managed_dict->dict; + dict = _PyObject_GetManagedDict(obj); if (dict == NULL && (tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && - _PyObject_InlineValues(obj)->valid - ) { - PyDictValues *values = _PyObject_InlineValues(obj); - OBJECT_STAT_INC(dict_materialized_on_request); - dict = make_dict_from_instance_attributes( - interp, CACHED_KEYS(tp), values); - if (dict != NULL) { - managed_dict->dict = (PyDictObject *)dict; - } + FT_ATOMIC_LOAD_UINT8(_PyObject_InlineValues(obj)->valid)) { + dict = _PyObject_MaterializeManagedDict(obj); } - else { - dict = managed_dict->dict; + else if (dict == NULL) { + Py_BEGIN_CRITICAL_SECTION(obj); + + // Check again that we're not racing with someone else creating the dict + dict = _PyObject_GetManagedDict(obj); if (dict == NULL) { - dictkeys_incref(CACHED_KEYS(tp)); OBJECT_STAT_INC(dict_materialized_on_request); + dictkeys_incref(CACHED_KEYS(tp)); dict = (PyDictObject *)new_dict_with_shared_keys(interp, CACHED_KEYS(tp)); - managed_dict->dict = (PyDictObject *)dict; + FT_ATOMIC_STORE_PTR_RELEASE(_PyObject_ManagedDictPointer(obj)->dict, + (PyDictObject *)dict); } + + Py_END_CRITICAL_SECTION(); } return Py_XNewRef((PyObject *)dict); } @@ -7109,7 +7354,7 @@ _PyObject_InlineValuesConsistencyCheck(PyObject *obj) return 1; } assert(Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyDictObject *dict = (PyDictObject *)_PyObject_ManagedDictPointer(obj)->dict; + PyDictObject *dict = _PyObject_GetManagedDict(obj); if (dict == NULL) { return 1; } diff --git a/Objects/object.c b/Objects/object.c index 73a1927263cdcbd..91bb0114cbfc327 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -6,6 +6,7 @@ #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate() #include "pycore_context.h" // _PyContextTokenMissing_Type +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION #include "pycore_descrobject.h" // _PyMethodWrapper_Type #include "pycore_dict.h" // _PyObject_MakeDictFromInstanceAttributes() #include "pycore_floatobject.h" // _PyFloat_DebugMallocStats() @@ -25,6 +26,7 @@ #include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic #include "pycore_unionobject.h" // _PyUnion_Type + #ifdef Py_LIMITED_API // Prevent recursive call _Py_IncRef() <=> Py_INCREF() # error "Py_LIMITED_API macro must not be defined" @@ -1403,16 +1405,15 @@ _PyObject_GetDictPtr(PyObject *obj) if ((Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) { return _PyObject_ComputedDictPointer(obj); } - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(obj); - if (managed_dict->dict == NULL && Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) { - PyDictObject *dict = (PyDictObject *)_PyObject_MakeDictFromInstanceAttributes(obj); + PyDictObject *dict = _PyObject_GetManagedDict(obj); + if (dict == NULL && Py_TYPE(obj)->tp_flags & Py_TPFLAGS_INLINE_VALUES) { + dict = _PyObject_MaterializeManagedDict(obj); if (dict == NULL) { PyErr_Clear(); return NULL; } - managed_dict->dict = dict; } - return (PyObject **)&managed_dict->dict; + return (PyObject **)&_PyObject_ManagedDictPointer(obj)->dict; } PyObject * @@ -1480,10 +1481,9 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) } } } - PyObject *dict; - if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && _PyObject_InlineValues(obj)->valid) { - PyDictValues *values = _PyObject_InlineValues(obj); - PyObject *attr = _PyObject_GetInstanceAttribute(obj, values, name); + PyObject *dict, *attr; + if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && + _PyObject_TryGetInstanceAttribute(obj, name, &attr)) { if (attr != NULL) { *method = attr; Py_XDECREF(descr); @@ -1492,8 +1492,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) dict = NULL; } else if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) { - PyManagedDictPointer* managed_dict = _PyObject_ManagedDictPointer(obj); - dict = (PyObject *)managed_dict->dict; + dict = (PyObject *)_PyObject_GetManagedDict(obj); } else { PyObject **dictptr = _PyObject_ComputedDictPointer(obj); @@ -1586,26 +1585,23 @@ _PyObject_GenericGetAttrWithDict(PyObject *obj, PyObject *name, } } if (dict == NULL) { - if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && _PyObject_InlineValues(obj)->valid) { - PyDictValues *values = _PyObject_InlineValues(obj); - if (PyUnicode_CheckExact(name)) { - res = _PyObject_GetInstanceAttribute(obj, values, name); + if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES)) { + if (PyUnicode_CheckExact(name) && + _PyObject_TryGetInstanceAttribute(obj, name, &res)) { if (res != NULL) { goto done; } } else { - dict = (PyObject *)_PyObject_MakeDictFromInstanceAttributes(obj); + dict = (PyObject *)_PyObject_MaterializeManagedDict(obj); if (dict == NULL) { res = NULL; goto done; } - _PyObject_ManagedDictPointer(obj)->dict = (PyDictObject *)dict; } } else if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) { - PyManagedDictPointer* managed_dict = _PyObject_ManagedDictPointer(obj); - dict = (PyObject *)managed_dict->dict; + dict = (PyObject *)_PyObject_GetManagedDict(obj); } else { PyObject **dictptr = _PyObject_ComputedDictPointer(obj); @@ -1700,12 +1696,13 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name, if (dict == NULL) { PyObject **dictptr; - if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES) && _PyObject_InlineValues(obj)->valid) { - res = _PyObject_StoreInstanceAttribute( - obj, _PyObject_InlineValues(obj), name, value); + + if ((tp->tp_flags & Py_TPFLAGS_INLINE_VALUES)) { + res = _PyObject_StoreInstanceAttribute(obj, name, value); goto error_check; } - else if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) { + + if ((tp->tp_flags & Py_TPFLAGS_MANAGED_DICT)) { PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(obj); dictptr = (PyObject **)&managed_dict->dict; } @@ -1779,7 +1776,7 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context) PyObject **dictptr = _PyObject_GetDictPtr(obj); if (dictptr == NULL) { if (_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_INLINE_VALUES) && - _PyObject_ManagedDictPointer(obj)->dict == NULL + _PyObject_GetManagedDict(obj) == NULL ) { /* Was unable to convert to dict */ PyErr_NoMemory(); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 970c82d2a17ada6..808e11fcbaf1ff9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3165,9 +3165,9 @@ subtype_setdict(PyObject *obj, PyObject *value, void *context) "not a '%.200s'", Py_TYPE(value)->tp_name); return -1; } + if (Py_TYPE(obj)->tp_flags & Py_TPFLAGS_MANAGED_DICT) { - PyObject_ClearManagedDict(obj); - _PyObject_ManagedDictPointer(obj)->dict = (PyDictObject *)Py_XNewRef(value); + _PyObject_SetManagedDict(obj, value); } else { dictptr = _PyObject_ComputedDictPointer(obj); @@ -6194,15 +6194,27 @@ object_set_class(PyObject *self, PyObject *value, void *closure) /* Changing the class will change the implicit dict keys, * so we must materialize the dictionary first. */ if (oldto->tp_flags & Py_TPFLAGS_INLINE_VALUES) { - PyDictObject *dict = _PyObject_ManagedDictPointer(self)->dict; + PyDictObject *dict = _PyObject_MaterializeManagedDict(self); if (dict == NULL) { - dict = (PyDictObject *)_PyObject_MakeDictFromInstanceAttributes(self); - if (dict == NULL) { - return -1; - } - _PyObject_ManagedDictPointer(self)->dict = dict; + return -1; + } + + bool error = false; + + Py_BEGIN_CRITICAL_SECTION2(self, dict); + + // If we raced after materialization and replaced the dict + // then the materialized dict should no longer have the + // inline values in which case detach is a nop. + assert(_PyObject_GetManagedDict(self) == dict || + dict->ma_values != _PyObject_InlineValues(self)); + + if (_PyDict_DetachFromObject(dict, self) < 0) { + error = true; } - if (_PyDict_DetachFromObject(dict, self)) { + + Py_END_CRITICAL_SECTION2(); + if (error) { return -1; } } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c1fbd3c7d26e01e..b7511b9107fdf6c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1947,15 +1947,13 @@ dummy_func( op(_CHECK_ATTR_WITH_HINT, (owner -- owner)) { assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); DEOPT_IF(dict == NULL); assert(PyDict_CheckExact((PyObject *)dict)); } op(_LOAD_ATTR_WITH_HINT, (hint/1, owner -- attr, null if (oparg & 1))) { - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); if (DK_IS_UNICODE(dict->ma_keys)) { @@ -2072,14 +2070,15 @@ dummy_func( op(_GUARD_DORV_NO_DICT, (owner -- owner)) { assert(Py_TYPE(owner)->tp_dictoffset < 0); assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES); - DEOPT_IF(_PyObject_ManagedDictPointer(owner)->dict); + DEOPT_IF(_PyObject_GetManagedDict(owner)); DEOPT_IF(_PyObject_InlineValues(owner)->valid == 0); } op(_STORE_ATTR_INSTANCE_VALUE, (index/1, value, owner --)) { STAT_INC(STORE_ATTR, hit); - assert(_PyObject_ManagedDictPointer(owner)->dict == NULL); + assert(_PyObject_GetManagedDict(owner) == NULL); PyDictValues *values = _PyObject_InlineValues(owner); + PyObject *old_value = values->values[index]; values->values[index] = value; if (old_value == NULL) { @@ -2088,6 +2087,7 @@ dummy_func( else { Py_DECREF(old_value); } + Py_DECREF(owner); } @@ -2102,8 +2102,7 @@ dummy_func( assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); DEOPT_IF(dict == NULL); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index df87f9178f17cfc..841ce8cbedb3fb2 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -1998,8 +1998,7 @@ PyObject *owner; owner = stack_pointer[-1]; assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); if (dict == NULL) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -2015,8 +2014,7 @@ oparg = CURRENT_OPARG(); owner = stack_pointer[-1]; uint16_t hint = (uint16_t)CURRENT_OPERAND(); - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); if (hint >= (size_t)dict->ma_keys->dk_nentries) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -2159,7 +2157,7 @@ owner = stack_pointer[-1]; assert(Py_TYPE(owner)->tp_dictoffset < 0); assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES); - if (_PyObject_ManagedDictPointer(owner)->dict) { + if (_PyObject_GetManagedDict(owner)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } @@ -2177,7 +2175,7 @@ value = stack_pointer[-2]; uint16_t index = (uint16_t)CURRENT_OPERAND(); STAT_INC(STORE_ATTR, hit); - assert(_PyObject_ManagedDictPointer(owner)->dict == NULL); + assert(_PyObject_GetManagedDict(owner) == NULL); PyDictValues *values = _PyObject_InlineValues(owner); PyObject *old_value = values->values[index]; values->values[index] = value; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index a426d9e208492ec..058cac8bedd9179 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -4017,16 +4017,14 @@ // _CHECK_ATTR_WITH_HINT { assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); DEOPT_IF(dict == NULL, LOAD_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); } // _LOAD_ATTR_WITH_HINT { uint16_t hint = read_u16(&this_instr[4].cache); - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); if (DK_IS_UNICODE(dict->ma_keys)) { @@ -5309,7 +5307,7 @@ { assert(Py_TYPE(owner)->tp_dictoffset < 0); assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_INLINE_VALUES); - DEOPT_IF(_PyObject_ManagedDictPointer(owner)->dict, STORE_ATTR); + DEOPT_IF(_PyObject_GetManagedDict(owner), STORE_ATTR); DEOPT_IF(_PyObject_InlineValues(owner)->valid == 0, STORE_ATTR); } // _STORE_ATTR_INSTANCE_VALUE @@ -5317,7 +5315,7 @@ { uint16_t index = read_u16(&this_instr[4].cache); STAT_INC(STORE_ATTR, hit); - assert(_PyObject_ManagedDictPointer(owner)->dict == NULL); + assert(_PyObject_GetManagedDict(owner) == NULL); PyDictValues *values = _PyObject_InlineValues(owner); PyObject *old_value = values->values[index]; values->values[index] = value; @@ -5380,8 +5378,7 @@ assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); DEOPT_IF(dict == NULL, STORE_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); diff --git a/Python/specialize.c b/Python/specialize.c index 5e14bb56b30036e..ee51781372166a8 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -852,8 +852,7 @@ specialize_dict_access( instr->op.code = values_op; } else { - PyManagedDictPointer *managed_dict = _PyObject_ManagedDictPointer(owner); - PyDictObject *dict = managed_dict->dict; + PyDictObject *dict = _PyObject_GetManagedDict(owner); if (dict == NULL || !PyDict_CheckExact(dict)) { SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT); return 0; diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index d17b2b9b024b999..18cefa083288042 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -354,6 +354,7 @@ def has_error_without_pop(op: parser.InstDef) -> bool: NON_ESCAPING_FUNCTIONS = ( "Py_INCREF", "_PyManagedDictPointer_IsValues", + "_PyObject_GetManagedDict", "_PyObject_ManagedDictPointer", "_PyObject_InlineValues", "_PyDictValues_AddToInsertionOrder", From 550483b7e6c54b2a25d4db0c4ca41bd9c1132f93 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Mon, 22 Apr 2024 08:43:20 +0200 Subject: [PATCH 083/127] gh-117995: Don't raise DeprecationWarnings for indexed nameless params (#118001) Filter out '?NNN' placeholders when looking for named params. Co-authored-by: AN Long --- Lib/test/test_sqlite3/test_dbapi.py | 14 ++++++++++++++ .../2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst | 2 ++ Modules/_sqlite/cursor.c | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 4182de246a071b0..6d8744ca5f79699 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -28,6 +28,7 @@ import threading import unittest import urllib.parse +import warnings from test.support import ( SHORT_TIMEOUT, check_disallow_instantiation, requires_subprocess, @@ -887,6 +888,19 @@ def test_execute_named_param_and_sequence(self): self.cu.execute(query, params) self.assertEqual(cm.filename, __file__) + def test_execute_indexed_nameless_params(self): + # See gh-117995: "'?1' is considered a named placeholder" + for query, params, expected in ( + ("select ?1, ?2", (1, 2), (1, 2)), + ("select ?2, ?1", (1, 2), (2, 1)), + ): + with self.subTest(query=query, params=params): + with warnings.catch_warnings(): + warnings.simplefilter("error", DeprecationWarning) + cu = self.cu.execute(query, params) + actual, = cu.fetchall() + self.assertEqual(actual, expected) + def test_execute_too_many_params(self): category = sqlite.SQLITE_LIMIT_VARIABLE_NUMBER msg = "too many SQL variables" diff --git a/Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst b/Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst new file mode 100644 index 000000000000000..a289939d33e8300 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-17-19-41-59.gh-issue-117995.Vt76Rv.rst @@ -0,0 +1,2 @@ +Don't raise :exc:`DeprecationWarning` when a :term:`sequence` of parameters +is used to bind indexed, nameless placeholders. See also :gh:`100668`. diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index f95df612328e577..950596ea82b5683 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -669,7 +669,7 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self, } for (i = 0; i < num_params; i++) { const char *name = sqlite3_bind_parameter_name(self->st, i+1); - if (name != NULL) { + if (name != NULL && name[0] != '?') { int ret = PyErr_WarnFormat(PyExc_DeprecationWarning, 1, "Binding %d ('%s') is a named parameter, but you " "supplied a sequence which requires nameless (qmark) " From ceb6038b053c403bed3ca3a8bd17b7e3fc9aab7d Mon Sep 17 00:00:00 2001 From: Kerim Kabirov Date: Mon, 22 Apr 2024 12:28:21 +0200 Subject: [PATCH 084/127] gh-115986 Improve pprint documentation accuracy (#117403) Co-authored-by: Jelle Zijlstra --- Doc/library/pprint.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index eebd270a096ba5f..6dfea25d755f758 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -19,9 +19,8 @@ such as files, sockets or classes are included, as well as many other objects which are not representable as Python literals. The formatted representation keeps objects on a single line if it can, and -breaks them onto multiple lines if they don't fit within the allowed width. -Construct :class:`PrettyPrinter` objects explicitly if you need to adjust the -width constraint. +breaks them onto multiple lines if they don't fit within the allowed width, +adjustable by the *width* parameter defaulting to 80 characters. Dictionaries are sorted by key before the display is computed. From a6647d16abf4dd65997865e857371673238e60bf Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Mon, 22 Apr 2024 13:34:06 +0100 Subject: [PATCH 085/127] GH-115480: Reduce guard strength for binary ops when type of one operand is known already (GH-118050) --- Include/internal/pycore_optimizer.h | 1 + Include/internal/pycore_uop_ids.h | 168 +++++++++++++------------ Include/internal/pycore_uop_metadata.h | 16 +++ Lib/test/test_capi/test_opt.py | 44 ++++++- Python/bytecodes.c | 16 +++ Python/executor_cases.c.h | 40 ++++++ Python/optimizer_analysis.c | 1 + Python/optimizer_bytecodes.c | 51 ++++++-- Python/optimizer_cases.c.h | 68 ++++++++-- Python/optimizer_symbols.c | 14 ++- 10 files changed, 316 insertions(+), 103 deletions(-) diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 44cafe61b755960..c0a76e85350541a 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -98,6 +98,7 @@ extern bool _Py_uop_sym_set_type(_Py_UopsSymbol *sym, PyTypeObject *typ); extern bool _Py_uop_sym_set_const(_Py_UopsSymbol *sym, PyObject *const_val); extern bool _Py_uop_sym_is_bottom(_Py_UopsSymbol *sym); extern int _Py_uop_sym_truthiness(_Py_UopsSymbol *sym); +extern PyTypeObject *_Py_uop_sym_get_type(_Py_UopsSymbol *sym); extern int _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 3e4dd8b4009cd4d..f0558743b32f5e7 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -118,17 +118,21 @@ extern "C" { #define _GUARD_IS_NOT_NONE_POP 356 #define _GUARD_IS_TRUE_POP 357 #define _GUARD_KEYS_VERSION 358 -#define _GUARD_NOT_EXHAUSTED_LIST 359 -#define _GUARD_NOT_EXHAUSTED_RANGE 360 -#define _GUARD_NOT_EXHAUSTED_TUPLE 361 -#define _GUARD_TYPE_VERSION 362 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 363 -#define _INIT_CALL_PY_EXACT_ARGS 364 -#define _INIT_CALL_PY_EXACT_ARGS_0 365 -#define _INIT_CALL_PY_EXACT_ARGS_1 366 -#define _INIT_CALL_PY_EXACT_ARGS_2 367 -#define _INIT_CALL_PY_EXACT_ARGS_3 368 -#define _INIT_CALL_PY_EXACT_ARGS_4 369 +#define _GUARD_NOS_FLOAT 359 +#define _GUARD_NOS_INT 360 +#define _GUARD_NOT_EXHAUSTED_LIST 361 +#define _GUARD_NOT_EXHAUSTED_RANGE 362 +#define _GUARD_NOT_EXHAUSTED_TUPLE 363 +#define _GUARD_TOS_FLOAT 364 +#define _GUARD_TOS_INT 365 +#define _GUARD_TYPE_VERSION 366 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 367 +#define _INIT_CALL_PY_EXACT_ARGS 368 +#define _INIT_CALL_PY_EXACT_ARGS_0 369 +#define _INIT_CALL_PY_EXACT_ARGS_1 370 +#define _INIT_CALL_PY_EXACT_ARGS_2 371 +#define _INIT_CALL_PY_EXACT_ARGS_3 372 +#define _INIT_CALL_PY_EXACT_ARGS_4 373 #define _INSTRUMENTED_CALL INSTRUMENTED_CALL #define _INSTRUMENTED_CALL_FUNCTION_EX INSTRUMENTED_CALL_FUNCTION_EX #define _INSTRUMENTED_CALL_KW INSTRUMENTED_CALL_KW @@ -145,65 +149,65 @@ extern "C" { #define _INSTRUMENTED_RETURN_CONST INSTRUMENTED_RETURN_CONST #define _INSTRUMENTED_RETURN_VALUE INSTRUMENTED_RETURN_VALUE #define _INSTRUMENTED_YIELD_VALUE INSTRUMENTED_YIELD_VALUE -#define _INTERNAL_INCREMENT_OPT_COUNTER 370 -#define _IS_NONE 371 +#define _INTERNAL_INCREMENT_OPT_COUNTER 374 +#define _IS_NONE 375 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 372 -#define _ITER_CHECK_RANGE 373 -#define _ITER_CHECK_TUPLE 374 -#define _ITER_JUMP_LIST 375 -#define _ITER_JUMP_RANGE 376 -#define _ITER_JUMP_TUPLE 377 -#define _ITER_NEXT_LIST 378 -#define _ITER_NEXT_RANGE 379 -#define _ITER_NEXT_TUPLE 380 -#define _JUMP_TO_TOP 381 +#define _ITER_CHECK_LIST 376 +#define _ITER_CHECK_RANGE 377 +#define _ITER_CHECK_TUPLE 378 +#define _ITER_JUMP_LIST 379 +#define _ITER_JUMP_RANGE 380 +#define _ITER_JUMP_TUPLE 381 +#define _ITER_NEXT_LIST 382 +#define _ITER_NEXT_RANGE 383 +#define _ITER_NEXT_TUPLE 384 +#define _JUMP_TO_TOP 385 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND #define _LOAD_ASSERTION_ERROR LOAD_ASSERTION_ERROR -#define _LOAD_ATTR 382 -#define _LOAD_ATTR_CLASS 383 -#define _LOAD_ATTR_CLASS_0 384 -#define _LOAD_ATTR_CLASS_1 385 +#define _LOAD_ATTR 386 +#define _LOAD_ATTR_CLASS 387 +#define _LOAD_ATTR_CLASS_0 388 +#define _LOAD_ATTR_CLASS_1 389 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 386 -#define _LOAD_ATTR_INSTANCE_VALUE_0 387 -#define _LOAD_ATTR_INSTANCE_VALUE_1 388 -#define _LOAD_ATTR_METHOD_LAZY_DICT 389 -#define _LOAD_ATTR_METHOD_NO_DICT 390 -#define _LOAD_ATTR_METHOD_WITH_VALUES 391 -#define _LOAD_ATTR_MODULE 392 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 393 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 394 +#define _LOAD_ATTR_INSTANCE_VALUE 390 +#define _LOAD_ATTR_INSTANCE_VALUE_0 391 +#define _LOAD_ATTR_INSTANCE_VALUE_1 392 +#define _LOAD_ATTR_METHOD_LAZY_DICT 393 +#define _LOAD_ATTR_METHOD_NO_DICT 394 +#define _LOAD_ATTR_METHOD_WITH_VALUES 395 +#define _LOAD_ATTR_MODULE 396 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 397 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 398 #define _LOAD_ATTR_PROPERTY LOAD_ATTR_PROPERTY -#define _LOAD_ATTR_SLOT 395 -#define _LOAD_ATTR_SLOT_0 396 -#define _LOAD_ATTR_SLOT_1 397 -#define _LOAD_ATTR_WITH_HINT 398 +#define _LOAD_ATTR_SLOT 399 +#define _LOAD_ATTR_SLOT_0 400 +#define _LOAD_ATTR_SLOT_1 401 +#define _LOAD_ATTR_WITH_HINT 402 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 399 -#define _LOAD_CONST_INLINE_BORROW 400 -#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 401 -#define _LOAD_CONST_INLINE_WITH_NULL 402 +#define _LOAD_CONST_INLINE 403 +#define _LOAD_CONST_INLINE_BORROW 404 +#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 405 +#define _LOAD_CONST_INLINE_WITH_NULL 406 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 403 -#define _LOAD_FAST_0 404 -#define _LOAD_FAST_1 405 -#define _LOAD_FAST_2 406 -#define _LOAD_FAST_3 407 -#define _LOAD_FAST_4 408 -#define _LOAD_FAST_5 409 -#define _LOAD_FAST_6 410 -#define _LOAD_FAST_7 411 +#define _LOAD_FAST 407 +#define _LOAD_FAST_0 408 +#define _LOAD_FAST_1 409 +#define _LOAD_FAST_2 410 +#define _LOAD_FAST_3 411 +#define _LOAD_FAST_4 412 +#define _LOAD_FAST_5 413 +#define _LOAD_FAST_6 414 +#define _LOAD_FAST_7 415 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #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 412 -#define _LOAD_GLOBAL_BUILTINS 413 -#define _LOAD_GLOBAL_MODULE 414 +#define _LOAD_GLOBAL 416 +#define _LOAD_GLOBAL_BUILTINS 417 +#define _LOAD_GLOBAL_MODULE 418 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR @@ -217,49 +221,49 @@ extern "C" { #define _MATCH_SEQUENCE MATCH_SEQUENCE #define _NOP NOP #define _POP_EXCEPT POP_EXCEPT -#define _POP_FRAME 415 -#define _POP_JUMP_IF_FALSE 416 -#define _POP_JUMP_IF_TRUE 417 +#define _POP_FRAME 419 +#define _POP_JUMP_IF_FALSE 420 +#define _POP_JUMP_IF_TRUE 421 #define _POP_TOP POP_TOP -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 418 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 422 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 419 +#define _PUSH_FRAME 423 #define _PUSH_NULL PUSH_NULL -#define _REPLACE_WITH_TRUE 420 +#define _REPLACE_WITH_TRUE 424 #define _RESUME_CHECK RESUME_CHECK -#define _SAVE_RETURN_OFFSET 421 -#define _SEND 422 +#define _SAVE_RETURN_OFFSET 425 +#define _SEND 426 #define _SEND_GEN SEND_GEN #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _SIDE_EXIT 423 -#define _START_EXECUTOR 424 -#define _STORE_ATTR 425 -#define _STORE_ATTR_INSTANCE_VALUE 426 -#define _STORE_ATTR_SLOT 427 +#define _SIDE_EXIT 427 +#define _START_EXECUTOR 428 +#define _STORE_ATTR 429 +#define _STORE_ATTR_INSTANCE_VALUE 430 +#define _STORE_ATTR_SLOT 431 #define _STORE_ATTR_WITH_HINT STORE_ATTR_WITH_HINT #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 428 -#define _STORE_FAST_0 429 -#define _STORE_FAST_1 430 -#define _STORE_FAST_2 431 -#define _STORE_FAST_3 432 -#define _STORE_FAST_4 433 -#define _STORE_FAST_5 434 -#define _STORE_FAST_6 435 -#define _STORE_FAST_7 436 +#define _STORE_FAST 432 +#define _STORE_FAST_0 433 +#define _STORE_FAST_1 434 +#define _STORE_FAST_2 435 +#define _STORE_FAST_3 436 +#define _STORE_FAST_4 437 +#define _STORE_FAST_5 438 +#define _STORE_FAST_6 439 +#define _STORE_FAST_7 440 #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME #define _STORE_SLICE STORE_SLICE -#define _STORE_SUBSCR 437 +#define _STORE_SUBSCR 441 #define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT #define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT #define _SWAP SWAP -#define _TO_BOOL 438 +#define _TO_BOOL 442 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT #define _TO_BOOL_LIST TO_BOOL_LIST @@ -269,12 +273,12 @@ extern "C" { #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 439 +#define _UNPACK_SEQUENCE 443 #define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST #define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE #define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define MAX_UOP_ID 439 +#define MAX_UOP_ID 443 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 44ede3e77c68e1e..4d15be6317d615f 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -59,10 +59,14 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_REPLACE_WITH_TRUE] = 0, [_UNARY_INVERT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_BOTH_INT] = HAS_EXIT_FLAG, + [_GUARD_NOS_INT] = HAS_EXIT_FLAG, + [_GUARD_TOS_INT] = HAS_EXIT_FLAG, [_BINARY_OP_MULTIPLY_INT] = HAS_ERROR_FLAG | HAS_PURE_FLAG, [_BINARY_OP_ADD_INT] = HAS_ERROR_FLAG | HAS_PURE_FLAG, [_BINARY_OP_SUBTRACT_INT] = HAS_ERROR_FLAG | HAS_PURE_FLAG, [_GUARD_BOTH_FLOAT] = HAS_EXIT_FLAG, + [_GUARD_NOS_FLOAT] = HAS_EXIT_FLAG, + [_GUARD_TOS_FLOAT] = HAS_EXIT_FLAG, [_BINARY_OP_MULTIPLY_FLOAT] = HAS_PURE_FLAG, [_BINARY_OP_ADD_FLOAT] = HAS_PURE_FLAG, [_BINARY_OP_SUBTRACT_FLOAT] = HAS_PURE_FLAG, @@ -352,9 +356,13 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_GUARD_IS_NOT_NONE_POP] = "_GUARD_IS_NOT_NONE_POP", [_GUARD_IS_TRUE_POP] = "_GUARD_IS_TRUE_POP", [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION", + [_GUARD_NOS_FLOAT] = "_GUARD_NOS_FLOAT", + [_GUARD_NOS_INT] = "_GUARD_NOS_INT", [_GUARD_NOT_EXHAUSTED_LIST] = "_GUARD_NOT_EXHAUSTED_LIST", [_GUARD_NOT_EXHAUSTED_RANGE] = "_GUARD_NOT_EXHAUSTED_RANGE", [_GUARD_NOT_EXHAUSTED_TUPLE] = "_GUARD_NOT_EXHAUSTED_TUPLE", + [_GUARD_TOS_FLOAT] = "_GUARD_TOS_FLOAT", + [_GUARD_TOS_INT] = "_GUARD_TOS_INT", [_GUARD_TYPE_VERSION] = "_GUARD_TYPE_VERSION", [_INIT_CALL_BOUND_METHOD_EXACT_ARGS] = "_INIT_CALL_BOUND_METHOD_EXACT_ARGS", [_INIT_CALL_PY_EXACT_ARGS] = "_INIT_CALL_PY_EXACT_ARGS", @@ -566,6 +574,10 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _GUARD_BOTH_INT: return 2; + case _GUARD_NOS_INT: + return 2; + case _GUARD_TOS_INT: + return 1; case _BINARY_OP_MULTIPLY_INT: return 2; case _BINARY_OP_ADD_INT: @@ -574,6 +586,10 @@ int _PyUop_num_popped(int opcode, int oparg) return 2; case _GUARD_BOTH_FLOAT: return 2; + case _GUARD_NOS_FLOAT: + return 2; + case _GUARD_TOS_FLOAT: + return 1; case _BINARY_OP_MULTIPLY_FLOAT: return 2; case _BINARY_OP_ADD_FLOAT: diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 28d18739b6d4a5b..ae23eadb8aafa07 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -903,10 +903,50 @@ def testfunc(n): self.assertTrue(res) self.assertIsNotNone(ex) uops = get_opnames(ex) - guard_both_float_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_INT"] - self.assertLessEqual(len(guard_both_float_count), 1) + guard_both_int_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_INT"] + self.assertLessEqual(len(guard_both_int_count), 1) self.assertIn("_COMPARE_OP_INT", uops) + def test_compare_op_type_propagation_int_partial(self): + def testfunc(n): + a = 1 + for _ in range(n): + if a > 2: + x = 0 + if a < 2: + x = 1 + return x + + res, ex = self._run_with_optimizer(testfunc, 32) + self.assertEqual(res, 1) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + guard_left_int_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_NOS_INT"] + guard_both_int_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_INT"] + self.assertLessEqual(len(guard_left_int_count), 1) + self.assertEqual(len(guard_both_int_count), 0) + self.assertIn("_COMPARE_OP_INT", uops) + + def test_compare_op_type_propagation_float_partial(self): + def testfunc(n): + a = 1.0 + for _ in range(n): + if a > 2.0: + x = 0 + if a < 2.0: + x = 1 + return x + + res, ex = self._run_with_optimizer(testfunc, 32) + self.assertEqual(res, 1) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + guard_left_float_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_NOS_FLOAT"] + guard_both_float_count = [opname for opname in iter_opnames(ex) if opname == "_GUARD_BOTH_FLOAT"] + self.assertLessEqual(len(guard_left_float_count), 1) + self.assertEqual(len(guard_both_float_count), 0) + self.assertIn("_COMPARE_OP_FLOAT", uops) + def test_compare_op_type_propagation_unicode(self): def testfunc(n): a = "" diff --git a/Python/bytecodes.c b/Python/bytecodes.c index b7511b9107fdf6c..4541eb635da0150 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -426,6 +426,14 @@ dummy_func( EXIT_IF(!PyLong_CheckExact(right)); } + op(_GUARD_NOS_INT, (left, unused -- left, unused)) { + EXIT_IF(!PyLong_CheckExact(left)); + } + + op(_GUARD_TOS_INT, (value -- value)) { + EXIT_IF(!PyLong_CheckExact(value)); + } + pure op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); @@ -462,6 +470,14 @@ dummy_func( EXIT_IF(!PyFloat_CheckExact(right)); } + op(_GUARD_NOS_FLOAT, (left, unused -- left, unused)) { + EXIT_IF(!PyFloat_CheckExact(left)); + } + + op(_GUARD_TOS_FLOAT, (value -- value)) { + EXIT_IF(!PyFloat_CheckExact(value)); + } + pure op(_BINARY_OP_MULTIPLY_FLOAT, (left, right -- res)) { STAT_INC(BINARY_OP, hit); double dres = diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 841ce8cbedb3fb2..43b022107a9ae6f 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -447,6 +447,26 @@ break; } + case _GUARD_NOS_INT: { + PyObject *left; + left = stack_pointer[-2]; + if (!PyLong_CheckExact(left)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + break; + } + + case _GUARD_TOS_INT: { + PyObject *value; + value = stack_pointer[-1]; + if (!PyLong_CheckExact(value)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + break; + } + case _BINARY_OP_MULTIPLY_INT: { PyObject *right; PyObject *left; @@ -511,6 +531,26 @@ break; } + case _GUARD_NOS_FLOAT: { + PyObject *left; + left = stack_pointer[-2]; + if (!PyFloat_CheckExact(left)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + break; + } + + case _GUARD_TOS_FLOAT: { + PyObject *value; + value = stack_pointer[-1]; + if (!PyFloat_CheckExact(value)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + break; + } + case _BINARY_OP_MULTIPLY_FLOAT: { PyObject *right; PyObject *left; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 155f7026b041b0a..76de6e50f1f786c 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -320,6 +320,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer, #define sym_new_const _Py_uop_sym_new_const #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_matches_type _Py_uop_sym_matches_type #define sym_set_null _Py_uop_sym_set_null #define sym_set_non_null _Py_uop_sym_set_non_null diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index f119b8e20719fa9..481fb8387af4167 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -21,6 +21,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; #define sym_new_const _Py_uop_sym_new_const #define sym_new_null _Py_uop_sym_new_null #define sym_matches_type _Py_uop_sym_matches_type +#define sym_get_type _Py_uop_sym_get_type #define sym_has_type _Py_uop_sym_has_type #define sym_set_null _Py_uop_sym_set_null #define sym_set_non_null _Py_uop_sym_set_non_null @@ -99,9 +100,18 @@ dummy_func(void) { } op(_GUARD_BOTH_INT, (left, right -- left, right)) { - if (sym_matches_type(left, &PyLong_Type) && - sym_matches_type(right, &PyLong_Type)) { - REPLACE_OP(this_instr, _NOP, 0, 0); + if (sym_matches_type(left, &PyLong_Type)) { + if (sym_matches_type(right, &PyLong_Type)) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + else { + REPLACE_OP(this_instr, _GUARD_TOS_INT, 0, 0); + } + } + else { + if (sym_matches_type(right, &PyLong_Type)) { + REPLACE_OP(this_instr, _GUARD_NOS_INT, 0, 0); + } } if (!sym_set_type(left, &PyLong_Type)) { goto hit_bottom; @@ -112,9 +122,18 @@ dummy_func(void) { } op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) { - if (sym_matches_type(left, &PyFloat_Type) && - sym_matches_type(right, &PyFloat_Type)) { - REPLACE_OP(this_instr, _NOP, 0 ,0); + if (sym_matches_type(left, &PyFloat_Type)) { + if (sym_matches_type(right, &PyFloat_Type)) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + else { + REPLACE_OP(this_instr, _GUARD_TOS_FLOAT, 0, 0); + } + } + else { + if (sym_matches_type(right, &PyFloat_Type)) { + REPLACE_OP(this_instr, _GUARD_NOS_FLOAT, 0, 0); + } } if (!sym_set_type(left, &PyFloat_Type)) { goto hit_bottom; @@ -137,6 +156,25 @@ dummy_func(void) { } } + op(_BINARY_OP, (left, right -- res)) { + PyTypeObject *ltype = sym_get_type(left); + PyTypeObject *rtype = sym_get_type(right); + if (ltype != NULL && (ltype == &PyLong_Type || ltype == &PyFloat_Type) && + rtype != NULL && (rtype == &PyLong_Type || rtype == &PyFloat_Type)) + { + if (oparg != NB_TRUE_DIVIDE && oparg != NB_INPLACE_TRUE_DIVIDE && + ltype == &PyLong_Type && rtype == &PyLong_Type) { + /* If both inputs are ints and the op is not division the result is an int */ + OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyLong_Type)); + } + else { + /* For any other op combining ints/floats the result is a float */ + OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyFloat_Type)); + } + } + OUT_OF_SPACE_IF_NULL(res = sym_new_unknown(ctx)); + } + op(_BINARY_OP_ADD_INT, (left, right -- res)) { if (sym_is_const(left) && sym_is_const(right) && sym_matches_type(left, &PyLong_Type) && sym_matches_type(right, &PyLong_Type)) @@ -424,7 +462,6 @@ dummy_func(void) { OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); } - op(_COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) { assert(oparg > 0); top = bottom; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 50f335e0c8a0a2e..0a7d96d30ad3e89 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -225,9 +225,18 @@ _Py_UopsSymbol *left; right = stack_pointer[-1]; left = stack_pointer[-2]; - if (sym_matches_type(left, &PyLong_Type) && - sym_matches_type(right, &PyLong_Type)) { - REPLACE_OP(this_instr, _NOP, 0, 0); + if (sym_matches_type(left, &PyLong_Type)) { + if (sym_matches_type(right, &PyLong_Type)) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + else { + REPLACE_OP(this_instr, _GUARD_TOS_INT, 0, 0); + } + } + else { + if (sym_matches_type(right, &PyLong_Type)) { + REPLACE_OP(this_instr, _GUARD_NOS_INT, 0, 0); + } } if (!sym_set_type(left, &PyLong_Type)) { goto hit_bottom; @@ -238,6 +247,14 @@ break; } + case _GUARD_NOS_INT: { + break; + } + + case _GUARD_TOS_INT: { + break; + } + case _BINARY_OP_MULTIPLY_INT: { _Py_UopsSymbol *right; _Py_UopsSymbol *left; @@ -333,9 +350,18 @@ _Py_UopsSymbol *left; right = stack_pointer[-1]; left = stack_pointer[-2]; - if (sym_matches_type(left, &PyFloat_Type) && - sym_matches_type(right, &PyFloat_Type)) { - REPLACE_OP(this_instr, _NOP, 0 ,0); + if (sym_matches_type(left, &PyFloat_Type)) { + if (sym_matches_type(right, &PyFloat_Type)) { + REPLACE_OP(this_instr, _NOP, 0, 0); + } + else { + REPLACE_OP(this_instr, _GUARD_TOS_FLOAT, 0, 0); + } + } + else { + if (sym_matches_type(right, &PyFloat_Type)) { + REPLACE_OP(this_instr, _GUARD_NOS_FLOAT, 0, 0); + } } if (!sym_set_type(left, &PyFloat_Type)) { goto hit_bottom; @@ -346,6 +372,14 @@ break; } + case _GUARD_NOS_FLOAT: { + break; + } + + case _GUARD_TOS_FLOAT: { + break; + } + case _BINARY_OP_MULTIPLY_FLOAT: { _Py_UopsSymbol *right; _Py_UopsSymbol *left; @@ -1852,9 +1886,27 @@ } case _BINARY_OP: { + _Py_UopsSymbol *right; + _Py_UopsSymbol *left; _Py_UopsSymbol *res; - res = sym_new_not_null(ctx); - if (res == NULL) goto out_of_space; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + PyTypeObject *ltype = sym_get_type(left); + PyTypeObject *rtype = sym_get_type(right); + if (ltype != NULL && (ltype == &PyLong_Type || ltype == &PyFloat_Type) && + rtype != NULL && (rtype == &PyLong_Type || rtype == &PyFloat_Type)) + { + if (oparg != NB_TRUE_DIVIDE && oparg != NB_INPLACE_TRUE_DIVIDE && + ltype == &PyLong_Type && rtype == &PyLong_Type) { + /* If both inputs are ints and the op is not division the result is an int */ + OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyLong_Type)); + } + else { + /* For any other op combining ints/floats the result is a float */ + OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyFloat_Type)); + } + } + OUT_OF_SPACE_IF_NULL(res = sym_new_unknown(ctx)); stack_pointer[-2] = res; stack_pointer += -1; break; diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c index 86b0d4d395afa2c..204599b08766c3a 100644 --- a/Python/optimizer_symbols.c +++ b/Python/optimizer_symbols.c @@ -231,6 +231,15 @@ _Py_uop_sym_new_null(_Py_UOpsContext *ctx) return null_sym; } +PyTypeObject * +_Py_uop_sym_get_type(_Py_UopsSymbol *sym) +{ + if (_Py_uop_sym_is_bottom(sym)) { + return NULL; + } + return sym->typ; +} + bool _Py_uop_sym_has_type(_Py_UopsSymbol *sym) { @@ -244,10 +253,7 @@ bool _Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ) { assert(typ != NULL && PyType_Check(typ)); - if (_Py_uop_sym_is_bottom(sym)) { - return false; - } - return sym->typ == typ; + return _Py_uop_sym_get_type(sym) == typ; } int From 287d939ed4445089e8312ab44110cbb6b6306a5c Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 22 Apr 2024 16:27:47 +0300 Subject: [PATCH 086/127] gh-118148: Improve tests for shutil.make_archive() (GH-118149) --- Lib/test/test_shutil.py | 247 ++++++++++++++++++++++++++++------------ 1 file changed, 176 insertions(+), 71 deletions(-) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 60e88d57b2b23de..3aa0ec6952339ba 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1615,42 +1615,6 @@ class TestArchives(BaseTest, unittest.TestCase): ### shutil.make_archive - @support.requires_zlib() - def test_make_tarball(self): - # creating something to tar - root_dir, base_dir = self._create_files('') - - tmpdir2 = self.mkdtemp() - # force shutil to create the directory - os.rmdir(tmpdir2) - # working with relative paths - work_dir = os.path.dirname(tmpdir2) - rel_base_name = os.path.join(os.path.basename(tmpdir2), 'archive') - - with os_helper.change_cwd(work_dir), no_chdir: - base_name = os.path.abspath(rel_base_name) - tarball = make_archive(rel_base_name, 'gztar', root_dir, '.') - - # check if the compressed tarball was created - self.assertEqual(tarball, base_name + '.tar.gz') - self.assertTrue(os.path.isfile(tarball)) - self.assertTrue(tarfile.is_tarfile(tarball)) - with tarfile.open(tarball, 'r:gz') as tf: - self.assertCountEqual(tf.getnames(), - ['.', './sub', './sub2', - './file1', './file2', './sub/file3']) - - # trying an uncompressed one - with os_helper.change_cwd(work_dir), no_chdir: - tarball = make_archive(rel_base_name, 'tar', root_dir, '.') - self.assertEqual(tarball, base_name + '.tar') - self.assertTrue(os.path.isfile(tarball)) - self.assertTrue(tarfile.is_tarfile(tarball)) - with tarfile.open(tarball, 'r') as tf: - self.assertCountEqual(tf.getnames(), - ['.', './sub', './sub2', - './file1', './file2', './sub/file3']) - def _tarinfo(self, path): with tarfile.open(path) as tar: names = tar.getnames() @@ -1671,6 +1635,92 @@ def _create_files(self, base_dir='dist'): write_file((root_dir, 'outer'), 'xxx') return root_dir, base_dir + @support.requires_zlib() + def test_make_tarfile(self): + root_dir, base_dir = self._create_files() + # Test without base_dir. + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst', 'archive') + archive = make_archive(base_name, 'tar', root_dir) + # check if the compressed tarball was created + self.assertEqual(archive, os.path.abspath(base_name) + '.tar') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(tarfile.is_tarfile(archive)) + with tarfile.open(archive, 'r') as tf: + self.assertCountEqual(tf.getnames(), + ['.', './dist', './dist/sub', './dist/sub2', + './dist/file1', './dist/file2', './dist/sub/file3', + './outer']) + + # Test with base_dir. + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst2', 'archive') + archive = make_archive(base_name, 'tar', root_dir, base_dir) + self.assertEqual(archive, os.path.abspath(base_name) + '.tar') + # check if the uncompressed tarball was created + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(tarfile.is_tarfile(archive)) + with tarfile.open(archive, 'r') as tf: + self.assertCountEqual(tf.getnames(), + ['dist', 'dist/sub', 'dist/sub2', + 'dist/file1', 'dist/file2', 'dist/sub/file3']) + + # Test with multi-component base_dir. + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst3', 'archive') + archive = make_archive(base_name, 'tar', root_dir, + os.path.join(base_dir, 'sub')) + self.assertEqual(archive, os.path.abspath(base_name) + '.tar') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(tarfile.is_tarfile(archive)) + with tarfile.open(archive, 'r') as tf: + self.assertCountEqual(tf.getnames(), + ['dist/sub', 'dist/sub/file3']) + + @support.requires_zlib() + def test_make_tarfile_without_rootdir(self): + root_dir, base_dir = self._create_files() + # Test without base_dir. + base_name = os.path.join(self.mkdtemp(), 'dst', 'archive') + base_name = os.path.relpath(base_name, root_dir) + with os_helper.change_cwd(root_dir), no_chdir: + archive = make_archive(base_name, 'gztar') + self.assertEqual(archive, base_name + '.tar.gz') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(tarfile.is_tarfile(archive)) + with tarfile.open(archive, 'r:gz') as tf: + self.assertCountEqual(tf.getnames(), + ['.', './dist', './dist/sub', './dist/sub2', + './dist/file1', './dist/file2', './dist/sub/file3', + './outer']) + + # Test with base_dir. + with os_helper.change_cwd(root_dir), no_chdir: + base_name = os.path.join('dst', 'archive') + archive = make_archive(base_name, 'tar', base_dir=base_dir) + self.assertEqual(archive, base_name + '.tar') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(tarfile.is_tarfile(archive)) + with tarfile.open(archive, 'r') as tf: + self.assertCountEqual(tf.getnames(), + ['dist', 'dist/sub', 'dist/sub2', + 'dist/file1', 'dist/file2', 'dist/sub/file3']) + + def test_make_tarfile_with_explicit_curdir(self): + # Test with base_dir=os.curdir. + root_dir, base_dir = self._create_files() + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst', 'archive') + archive = make_archive(base_name, 'tar', root_dir, os.curdir) + self.assertEqual(archive, os.path.abspath(base_name) + '.tar') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(tarfile.is_tarfile(archive)) + with tarfile.open(archive, 'r') as tf: + self.assertCountEqual(tf.getnames(), + ['.', './dist', './dist/sub', './dist/sub2', + './dist/file1', './dist/file2', './dist/sub/file3', + './outer']) + @support.requires_zlib() @unittest.skipUnless(shutil.which('tar'), 'Need the tar command to run') @@ -1720,40 +1770,89 @@ def test_tarfile_vs_tar(self): @support.requires_zlib() def test_make_zipfile(self): - # creating something to zip root_dir, base_dir = self._create_files() + # Test without base_dir. + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst', 'archive') + archive = make_archive(base_name, 'zip', root_dir) + self.assertEqual(archive, os.path.abspath(base_name) + '.zip') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(zipfile.is_zipfile(archive)) + with zipfile.ZipFile(archive) as zf: + self.assertCountEqual(zf.namelist(), + ['dist/', 'dist/sub/', 'dist/sub2/', + 'dist/file1', 'dist/file2', 'dist/sub/file3', + 'outer']) + + # Test with base_dir. + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst2', 'archive') + archive = make_archive(base_name, 'zip', root_dir, base_dir) + self.assertEqual(archive, os.path.abspath(base_name) + '.zip') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(zipfile.is_zipfile(archive)) + with zipfile.ZipFile(archive) as zf: + self.assertCountEqual(zf.namelist(), + ['dist/', 'dist/sub/', 'dist/sub2/', + 'dist/file1', 'dist/file2', 'dist/sub/file3']) + + # Test with multi-component base_dir. + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst3', 'archive') + archive = make_archive(base_name, 'zip', root_dir, + os.path.join(base_dir, 'sub')) + self.assertEqual(archive, os.path.abspath(base_name) + '.zip') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(zipfile.is_zipfile(archive)) + with zipfile.ZipFile(archive) as zf: + self.assertCountEqual(zf.namelist(), + ['dist/sub/', 'dist/sub/file3']) - tmpdir2 = self.mkdtemp() - # force shutil to create the directory - os.rmdir(tmpdir2) - # working with relative paths - work_dir = os.path.dirname(tmpdir2) - rel_base_name = os.path.join(os.path.basename(tmpdir2), 'archive') - - with os_helper.change_cwd(work_dir), no_chdir: - base_name = os.path.abspath(rel_base_name) - res = make_archive(rel_base_name, 'zip', root_dir) + @support.requires_zlib() + def test_make_zipfile_without_rootdir(self): + root_dir, base_dir = self._create_files() + # Test without base_dir. + base_name = os.path.join(self.mkdtemp(), 'dst', 'archive') + base_name = os.path.relpath(base_name, root_dir) + with os_helper.change_cwd(root_dir), no_chdir: + archive = make_archive(base_name, 'zip') + self.assertEqual(archive, base_name + '.zip') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(zipfile.is_zipfile(archive)) + with zipfile.ZipFile(archive) as zf: + self.assertCountEqual(zf.namelist(), + ['dist/', 'dist/sub/', 'dist/sub2/', + 'dist/file1', 'dist/file2', 'dist/sub/file3', + 'outer']) + + # Test with base_dir. + root_dir, base_dir = self._create_files() + with os_helper.change_cwd(root_dir), no_chdir: + base_name = os.path.join('dst', 'archive') + archive = make_archive(base_name, 'zip', base_dir=base_dir) + self.assertEqual(archive, base_name + '.zip') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(zipfile.is_zipfile(archive)) + with zipfile.ZipFile(archive) as zf: + self.assertCountEqual(zf.namelist(), + ['dist/', 'dist/sub/', 'dist/sub2/', + 'dist/file1', 'dist/file2', 'dist/sub/file3']) - self.assertEqual(res, base_name + '.zip') - self.assertTrue(os.path.isfile(res)) - self.assertTrue(zipfile.is_zipfile(res)) - with zipfile.ZipFile(res) as zf: - self.assertCountEqual(zf.namelist(), - ['dist/', 'dist/sub/', 'dist/sub2/', - 'dist/file1', 'dist/file2', 'dist/sub/file3', - 'outer']) - - with os_helper.change_cwd(work_dir), no_chdir: - base_name = os.path.abspath(rel_base_name) - res = make_archive(rel_base_name, 'zip', root_dir, base_dir) - - self.assertEqual(res, base_name + '.zip') - self.assertTrue(os.path.isfile(res)) - self.assertTrue(zipfile.is_zipfile(res)) - with zipfile.ZipFile(res) as zf: - self.assertCountEqual(zf.namelist(), - ['dist/', 'dist/sub/', 'dist/sub2/', - 'dist/file1', 'dist/file2', 'dist/sub/file3']) + @support.requires_zlib() + def test_make_zipfile_with_explicit_curdir(self): + # Test with base_dir=os.curdir. + root_dir, base_dir = self._create_files() + with os_helper.temp_cwd(), no_chdir: + base_name = os.path.join('dst', 'archive') + archive = make_archive(base_name, 'zip', root_dir, os.curdir) + self.assertEqual(archive, os.path.abspath(base_name) + '.zip') + self.assertTrue(os.path.isfile(archive)) + self.assertTrue(zipfile.is_zipfile(archive)) + with zipfile.ZipFile(archive) as zf: + self.assertCountEqual(zf.namelist(), + ['dist/', 'dist/sub/', 'dist/sub2/', + 'dist/file1', 'dist/file2', 'dist/sub/file3', + 'outer']) @support.requires_zlib() @unittest.skipUnless(shutil.which('zip'), @@ -1923,17 +2022,19 @@ def archiver(base_name, base_dir, **kw): unregister_archive_format('xxx') def test_make_tarfile_in_curdir(self): - # Issue #21280 + # Issue #21280: Test with the archive in the current directory. root_dir = self.mkdtemp() with os_helper.change_cwd(root_dir), no_chdir: + # root_dir must be None, so the archive path is relative. self.assertEqual(make_archive('test', 'tar'), 'test.tar') self.assertTrue(os.path.isfile('test.tar')) @support.requires_zlib() def test_make_zipfile_in_curdir(self): - # Issue #21280 + # Issue #21280: Test with the archive in the current directory. root_dir = self.mkdtemp() with os_helper.change_cwd(root_dir), no_chdir: + # root_dir must be None, so the archive path is relative. self.assertEqual(make_archive('test', 'zip'), 'test.zip') self.assertTrue(os.path.isfile('test.zip')) @@ -1954,10 +2055,11 @@ def test_register_archive_format(self): self.assertNotIn('xxx', formats) def test_make_tarfile_rootdir_nodir(self): - # GH-99203 + # GH-99203: Test with root_dir is not a real directory. self.addCleanup(os_helper.unlink, f'{TESTFN}.tar') for dry_run in (False, True): with self.subTest(dry_run=dry_run): + # root_dir does not exist. tmp_dir = self.mkdtemp() nonexisting_file = os.path.join(tmp_dir, 'nonexisting') with self.assertRaises(FileNotFoundError) as cm: @@ -1966,6 +2068,7 @@ def test_make_tarfile_rootdir_nodir(self): self.assertEqual(cm.exception.filename, nonexisting_file) self.assertFalse(os.path.exists(f'{TESTFN}.tar')) + # root_dir is a file. tmp_fd, tmp_file = tempfile.mkstemp(dir=tmp_dir) os.close(tmp_fd) with self.assertRaises(NotADirectoryError) as cm: @@ -1976,10 +2079,11 @@ def test_make_tarfile_rootdir_nodir(self): @support.requires_zlib() def test_make_zipfile_rootdir_nodir(self): - # GH-99203 + # GH-99203: Test with root_dir is not a real directory. self.addCleanup(os_helper.unlink, f'{TESTFN}.zip') for dry_run in (False, True): with self.subTest(dry_run=dry_run): + # root_dir does not exist. tmp_dir = self.mkdtemp() nonexisting_file = os.path.join(tmp_dir, 'nonexisting') with self.assertRaises(FileNotFoundError) as cm: @@ -1988,6 +2092,7 @@ def test_make_zipfile_rootdir_nodir(self): self.assertEqual(cm.exception.filename, nonexisting_file) self.assertFalse(os.path.exists(f'{TESTFN}.zip')) + # root_dir is a file. tmp_fd, tmp_file = tempfile.mkstemp(dir=tmp_dir) os.close(tmp_fd) with self.assertRaises(NotADirectoryError) as cm: From 78ba4cb758ba1e40d27af6bc2fa15ed3e33a29d2 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Mon, 22 Apr 2024 16:57:46 +0200 Subject: [PATCH 087/127] gh-118030: Group definitions for `ParamSpecArgs` and `ParamSpecKwargs` in `typing.rst` (#118154) --- Doc/library/typing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 2e71be7eaf8d03d..d816e6368f40d29 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1972,7 +1972,7 @@ without the dedicated syntax, as documented below. * :ref:`annotating-callables` .. data:: ParamSpecArgs -.. data:: ParamSpecKwargs + ParamSpecKwargs Arguments and keyword arguments attributes of a :class:`ParamSpec`. The ``P.args`` attribute of a ``ParamSpec`` is an instance of ``ParamSpecArgs``, From 8974a63f5ee0557e14db97eb1284a5dd8c49f8f7 Mon Sep 17 00:00:00 2001 From: tahia Date: Mon, 22 Apr 2024 14:23:36 -0400 Subject: [PATCH 088/127] bpo-18108: Adding dir_fd and follow_symlinks keyword args to shutil.chown (GH-15811) * Adding dir_fd and follow_symlinks keyword args to shutil.chown * Extending test_shutil.TestShutil.test_chown to include new kwargs * Updating shutil.chown documentation Co-authored-by: Serhiy Storchaka Co-authored-by: Berker Peksag Co-authored-by: Zachary Ware --- Doc/library/shutil.rst | 6 +++- Doc/whatsnew/3.13.rst | 4 +++ Lib/shutil.py | 12 +++++-- Lib/test/test_shutil.py | 34 ++++++++++++++++++- .../2019-09-09-18-18-34.bpo-18108.ajPLAO.rst | 1 + 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 4f07b9f6040d240..8e5828c789e4e23 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -421,7 +421,8 @@ Directory and files operations .. availability:: Unix, Windows. -.. function:: chown(path, user=None, group=None) +.. function:: chown(path, user=None, group=None, *, dir_fd=None, \ + follow_symlinks=True) Change owner *user* and/or *group* of the given *path*. @@ -436,6 +437,9 @@ Directory and files operations .. versionadded:: 3.3 + .. versionchanged:: 3.13 + Added *dir_fd* and *follow_symlinks* parameters. + .. function:: which(cmd, mode=os.F_OK | os.X_OK, path=None) diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 5be562030b507b2..c04dc924d1efa53 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -594,6 +594,10 @@ os.path exactly one (back)slash to be absolute. (Contributed by Barney Gale and Jon Foster in :gh:`44626`.) +* Add support of *dir_fd* and *follow_symlinks* keyword arguments in + :func:`shutil.chown`. + (Contributed by Berker Peksag and Tahia K in :gh:`62308`) + pathlib ------- diff --git a/Lib/shutil.py b/Lib/shutil.py index 94b09509008b0bb..910d6b6c63ac088 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1442,11 +1442,18 @@ def disk_usage(path): return _ntuple_diskusage(total, used, free) -def chown(path, user=None, group=None): +def chown(path, user=None, group=None, *, dir_fd=None, follow_symlinks=True): """Change owner user and group of the given path. user and group can be the uid/gid or the user/group names, and in that case, they are converted to their respective uid/gid. + + If dir_fd is set, it should be an open file descriptor to the directory to + be used as the root of *path* if it is relative. + + If follow_symlinks is set to False and the last element of the path is a + symbolic link, chown will modify the link itself and not the file being + referenced by the link. """ sys.audit('shutil.chown', path, user, group) @@ -1472,7 +1479,8 @@ def chown(path, user=None, group=None): if _group is None: raise LookupError("no such group: {!r}".format(group)) - os.chown(path, _user, _group) + os.chown(path, _user, _group, dir_fd=dir_fd, + follow_symlinks=follow_symlinks) def get_terminal_size(fallback=(80, 24)): """Get the size of the terminal window. diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 3aa0ec6952339ba..5b0aac67a0adeb5 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -2212,7 +2212,9 @@ def test_disk_usage(self): def test_chown(self): dirname = self.mkdtemp() filename = tempfile.mktemp(dir=dirname) + linkname = os.path.join(dirname, "chown_link") write_file(filename, 'testing chown function') + os.symlink(filename, linkname) with self.assertRaises(ValueError): shutil.chown(filename) @@ -2233,7 +2235,7 @@ def test_chown(self): gid = os.getgid() def check_chown(path, uid=None, gid=None): - s = os.stat(filename) + s = os.stat(path) if uid is not None: self.assertEqual(uid, s.st_uid) if gid is not None: @@ -2269,6 +2271,36 @@ def check_chown(path, uid=None, gid=None): shutil.chown(dirname, user, group) check_chown(dirname, uid, gid) + dirfd = os.open(dirname, os.O_RDONLY) + self.addCleanup(os.close, dirfd) + basename = os.path.basename(filename) + baselinkname = os.path.basename(linkname) + shutil.chown(basename, uid, gid, dir_fd=dirfd) + check_chown(filename, uid, gid) + shutil.chown(basename, uid, dir_fd=dirfd) + check_chown(filename, uid) + shutil.chown(basename, group=gid, dir_fd=dirfd) + check_chown(filename, gid=gid) + shutil.chown(basename, uid, gid, dir_fd=dirfd, follow_symlinks=True) + check_chown(filename, uid, gid) + shutil.chown(basename, uid, gid, dir_fd=dirfd, follow_symlinks=False) + check_chown(filename, uid, gid) + shutil.chown(linkname, uid, follow_symlinks=True) + check_chown(filename, uid) + shutil.chown(baselinkname, group=gid, dir_fd=dirfd, follow_symlinks=False) + check_chown(filename, gid=gid) + shutil.chown(baselinkname, uid, gid, dir_fd=dirfd, follow_symlinks=True) + check_chown(filename, uid, gid) + + with self.assertRaises(TypeError): + shutil.chown(filename, uid, dir_fd=dirname) + + with self.assertRaises(FileNotFoundError): + shutil.chown('missingfile', uid, gid, dir_fd=dirfd) + + with self.assertRaises(ValueError): + shutil.chown(filename, dir_fd=dirfd) + @support.requires_subprocess() class TestWhich(BaseTest, unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst b/Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst new file mode 100644 index 000000000000000..70ff76a0c920be7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-09-09-18-18-34.bpo-18108.ajPLAO.rst @@ -0,0 +1 @@ +:func:`shutil.chown` now supports *dir_fd* and *follow_symlinks* keyword arguments. From 4c7bfdff90544deb5d2055fcbe4db4c2a231e95d Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 22 Apr 2024 12:17:57 -0700 Subject: [PATCH 089/127] Remove more remnants of deepfreeze (#118159) --- Include/incl.tar | Bin 0 -> 1864192 bytes Include/internal/pycore_code.h | 5 ----- Include/internal/pycore_pylifecycle.h | 2 -- Programs/_bootstrap_python.c | 11 ----------- Programs/_freeze_module.c | 11 ----------- 5 files changed, 29 deletions(-) create mode 100644 Include/incl.tar diff --git a/Include/incl.tar b/Include/incl.tar new file mode 100644 index 0000000000000000000000000000000000000000..fecc1fb5dec534148d40b4a4c3f1bcfce411a832 GIT binary patch literal 1864192 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%0DN$)T@_T(Wn2(qM_vfI#uE# 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
UW98&SdxSMC!PoVY5J#99u=5s5?@ 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%0AK?J9w$I*mRT%S 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 literal 0 HcmV?d00001 diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 1ec0348d6e5e8ba..8d832c59e36874c 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -288,11 +288,6 @@ extern void _Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr); extern void _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr); extern void _Py_Specialize_ContainsOp(PyObject *value, _Py_CODEUNIT *instr); -/* Finalizer function for static codeobjects used in deepfreeze.py */ -extern void _PyStaticCode_Fini(PyCodeObject *co); -/* Function to intern strings of codeobjects and quicken the bytecode */ -extern int _PyStaticCode_Init(PyCodeObject *co); - #ifdef Py_STATS #include "pycore_bitutils.h" // _Py_bit_length diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 47ff0806574ac02..f426ae0e103b9c9 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -42,7 +42,6 @@ extern PyStatus _Py_HashRandomization_Init(const PyConfig *); extern PyStatus _PyGC_Init(PyInterpreterState *interp); extern PyStatus _PyAtExit_Init(PyInterpreterState *interp); -extern int _Py_Deepfreeze_Init(void); /* Various internal finalizers */ @@ -58,7 +57,6 @@ extern void _PyWarnings_Fini(PyInterpreterState *interp); extern void _PyAST_Fini(PyInterpreterState *interp); extern void _PyAtExit_Fini(PyInterpreterState *interp); extern void _PyThread_FiniType(PyInterpreterState *interp); -extern void _Py_Deepfreeze_Fini(void); extern void _PyArg_Fini(void); extern void _Py_FinalizeAllocatedBlocks(_PyRuntimeState *); diff --git a/Programs/_bootstrap_python.c b/Programs/_bootstrap_python.c index 34f79191b4e8d77..6443d814a22dabf 100644 --- a/Programs/_bootstrap_python.c +++ b/Programs/_bootstrap_python.c @@ -15,17 +15,6 @@ #include "Python/frozen_modules/zipimport.h" /* End includes */ -/* Empty initializer for deepfrozen modules */ -int _Py_Deepfreeze_Init(void) -{ - return 0; -} -/* Empty finalizer for deepfrozen modules */ -void -_Py_Deepfreeze_Fini(void) -{ -} - /* Note that a negative size indicates a package. */ static const struct _frozen bootstrap_modules[] = { diff --git a/Programs/_freeze_module.c b/Programs/_freeze_module.c index 3de6c6816c1e614..2a462a42cdad7c7 100644 --- a/Programs/_freeze_module.c +++ b/Programs/_freeze_module.c @@ -22,17 +22,6 @@ # include #endif -/* Empty initializer for deepfrozen modules */ -int _Py_Deepfreeze_Init(void) -{ - return 0; -} -/* Empty finalizer for deepfrozen modules */ -void -_Py_Deepfreeze_Fini(void) -{ -} - /* To avoid a circular dependency on frozen.o, we create our own structure of frozen modules instead, left deliberately blank so as to avoid unintentional import of a stale version of _frozen_importlib. */ From 85f727c5fb2afa60affa9ae3396ce4149cf5215d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 22 Apr 2024 12:50:26 -0700 Subject: [PATCH 090/127] gh-109118: Allow lambdas in annotation scopes in classes (#118019) --- Doc/whatsnew/3.13.rst | 3 ++ Lib/test/test_type_params.py | 50 ++++++++++++++++++- ...-04-17-17-52-32.gh-issue-109118.q9iPEI.rst | 2 + Python/symtable.c | 11 ---- 4 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index c04dc924d1efa53..67d1956a19697e6 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -241,6 +241,9 @@ Other Language Changes ones if configured to do so. (Contributed by Pedro Sousa Lacerda in :gh:`66449`.) +* :ref:`annotation scope ` within class scopes can now + contain lambdas. (Contributed by Jelle Zijlstra in :gh:`109118`.) + New Modules =========== diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py index 25ee188731f31fb..fbb80d9aac99421 100644 --- a/Lib/test/test_type_params.py +++ b/Lib/test/test_type_params.py @@ -486,8 +486,6 @@ class C[T]: {} """ error_cases = [ - "type Alias1[T] = lambda: T", - "type Alias2 = lambda: T", "type Alias3[T] = (T for _ in (1,))", "type Alias4 = (T for _ in (1,))", "type Alias5[T] = [T for _ in (1,)]", @@ -499,6 +497,54 @@ class C[T]: r"Cannot use [a-z]+ in annotation scope within class scope"): run_code(code.format(case)) + def test_lambda_in_alias_in_class(self): + code = """ + T = "global" + class C: + T = "class" + type Alias = lambda: T + """ + C = run_code(code)["C"] + self.assertEqual(C.Alias.__value__(), "global") + + def test_lambda_in_alias_in_generic_class(self): + code = """ + class C[T]: + T = "class" + type Alias = lambda: T + """ + C = run_code(code)["C"] + self.assertIs(C.Alias.__value__(), C.__type_params__[0]) + + def test_lambda_in_generic_alias_in_class(self): + # A lambda nested in the alias cannot see the class scope, but can see + # a surrounding annotation scope. + code = """ + T = U = "global" + class C: + T = "class" + U = "class" + type Alias[T] = lambda: (T, U) + """ + C = run_code(code)["C"] + T, U = C.Alias.__value__() + self.assertIs(T, C.Alias.__type_params__[0]) + self.assertEqual(U, "global") + + def test_lambda_in_generic_alias_in_generic_class(self): + # A lambda nested in the alias cannot see the class scope, but can see + # a surrounding annotation scope. + code = """ + class C[T, U]: + T = "class" + U = "class" + type Alias[T] = lambda: (T, U) + """ + C = run_code(code)["C"] + T, U = C.Alias.__value__() + self.assertIs(T, C.Alias.__type_params__[0]) + self.assertIs(U, C.__type_params__[1]) + def make_base(arg): class Base: diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst new file mode 100644 index 000000000000000..124540045547b17 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-17-17-52-32.gh-issue-109118.q9iPEI.rst @@ -0,0 +1,2 @@ +:ref:`annotation scope ` within class scopes can now +contain lambdas. diff --git a/Python/symtable.c b/Python/symtable.c index 36ccc0e73723d59..483ef1c3c465422 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -2140,17 +2140,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.UnaryOp.operand); break; case Lambda_kind: { - if (st->st_cur->ste_can_see_class_scope) { - // gh-109118 - PyErr_Format(PyExc_SyntaxError, - "Cannot use lambda in annotation scope within class scope"); - PyErr_RangedSyntaxLocationObject(st->st_filename, - e->lineno, - e->col_offset + 1, - e->end_lineno, - e->end_col_offset + 1); - VISIT_QUIT(st, 0); - } if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults) From fc21c7f7a731d64f7e4f0e82469f78fa9c104bbd Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 23 Apr 2024 00:31:01 +0300 Subject: [PATCH 091/127] Set proper permissions for `jit.yml` workflow (#118084) --- .github/workflows/jit.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index f18fb0030bbf8ba..490005b7170e95b 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -12,6 +12,9 @@ on: - 'Python/optimizer*.c' workflow_dispatch: +permissions: + contents: read + concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true From 1b85b3424c081835406592868123fe898ee029ad Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 22 Apr 2024 16:20:39 -0700 Subject: [PATCH 092/127] GH-118074: Executors in the COLD_EXITS array are not GC'able (#118117) --- .../2024-04-22-08-34-28.gh-issue-118074.5_JnIa.rst | 2 ++ Python/optimizer.c | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-22-08-34-28.gh-issue-118074.5_JnIa.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-22-08-34-28.gh-issue-118074.5_JnIa.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-22-08-34-28.gh-issue-118074.5_JnIa.rst new file mode 100644 index 000000000000000..69d29bce12ee57c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-22-08-34-28.gh-issue-118074.5_JnIa.rst @@ -0,0 +1,2 @@ +Make sure that the Executor objects in the COLD_EXITS array aren't assumed +to be GC-able (which would access bytes outside the object). diff --git a/Python/optimizer.c b/Python/optimizer.c index bb537c9111a51f3..5863336c0d9ecfe 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -394,6 +394,15 @@ executor_traverse(PyObject *o, visitproc visit, void *arg) return 0; } +static int +executor_is_gc(PyObject *o) +{ + if ((PyObject *)&COLD_EXITS[0] <= o && o < (PyObject *)&COLD_EXITS[COLD_EXIT_COUNT]) { + return 0; + } + return 1; +} + PyTypeObject _PyUOpExecutor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) .tp_name = "uop_executor", @@ -405,6 +414,7 @@ PyTypeObject _PyUOpExecutor_Type = { .tp_methods = executor_methods, .tp_traverse = executor_traverse, .tp_clear = executor_clear, + .tp_is_gc = executor_is_gc, }; /* TO DO -- Generate these tables */ From c9829eec0883a8991ea4d319d965e123a3cf6c20 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Mon, 22 Apr 2024 18:15:08 -0700 Subject: [PATCH 093/127] gh-116741: Upgrade libexpat to 2.6.2 (#117296) Upgrade libexpat to 2.6.2 --- ...-03-27-13-50-02.gh-issue-116741.ZoGryG.rst | 1 + Misc/sbom.spdx.json | 20 ++++++------- Modules/expat/expat.h | 5 ++-- Modules/expat/internal.h | 17 +++++++---- Modules/expat/xmlparse.c | 30 +++++++++++++------ 5 files changed, 47 insertions(+), 26 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2024-03-27-13-50-02.gh-issue-116741.ZoGryG.rst diff --git a/Misc/NEWS.d/next/Security/2024-03-27-13-50-02.gh-issue-116741.ZoGryG.rst b/Misc/NEWS.d/next/Security/2024-03-27-13-50-02.gh-issue-116741.ZoGryG.rst new file mode 100644 index 000000000000000..12a41948066bed2 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2024-03-27-13-50-02.gh-issue-116741.ZoGryG.rst @@ -0,0 +1 @@ +Update bundled libexpat to 2.6.2 diff --git a/Misc/sbom.spdx.json b/Misc/sbom.spdx.json index 07db46b09ae5f58..b60adcfd362f682 100644 --- a/Misc/sbom.spdx.json +++ b/Misc/sbom.spdx.json @@ -48,11 +48,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "90c06411f131e777e2b5c3d22b7ccf50bc46f617" + "checksumValue": "4076a884f0ca96873589b5c8159e2e5bfb8b829a" }, { "algorithm": "SHA256", - "checksumValue": "3045f9176950aa13a54e53fa096385670c676c492705d636e977f888e4c72d48" + "checksumValue": "1a434bf3d2f9fb8a0b5adb79201a942788d11824c3e5b46a0b9962c0c482016c" } ], "fileName": "Modules/expat/expat.h" @@ -90,11 +90,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "9f6d9211a7b627785d5c48d10cc8eda66255113f" + "checksumValue": "e23d160cc33cc2c25a4b48f7b242f906444418e0" }, { "algorithm": "SHA256", - "checksumValue": "9f0bdd346dd94ac4359c636a4e60bc768f4ae53ce0e836eb05fb9246ee36c7f2" + "checksumValue": "f7523357d8009749e7dba94b0bd7d0fa60e011cc254e55c4ebccd6313f031122" } ], "fileName": "Modules/expat/internal.h" @@ -188,11 +188,11 @@ "checksums": [ { "algorithm": "SHA1", - "checksumValue": "3b5de0ed1de33cad85b46230707403247f2851df" + "checksumValue": "fed1311be8577491b7f63085a27014eabf2caec8" }, { "algorithm": "SHA256", - "checksumValue": "a03abd531601eef61a87e06113d218ff139b6969e15a3d4668cd85d65fc6f79b" + "checksumValue": "3dc233eca5fa1bb7387c503f8a12d840707e4374b229e05d5657db9645725040" } ], "fileName": "Modules/expat/xmlparse.c" @@ -1562,14 +1562,14 @@ "checksums": [ { "algorithm": "SHA256", - "checksumValue": "a13447b9aa67d7c860783fdf6820f33ebdea996900d6d8bbc50a628f55f099f7" + "checksumValue": "d4cf38d26e21a56654ffe4acd9cd5481164619626802328506a2869afab29ab3" } ], - "downloadLocation": "https://github.com/libexpat/libexpat/releases/download/R_2_6_0/expat-2.6.0.tar.gz", + "downloadLocation": "https://github.com/libexpat/libexpat/releases/download/R_2_6_2/expat-2.6.2.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:libexpat_project:libexpat:2.6.0:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:libexpat_project:libexpat:2.6.2:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], @@ -1577,7 +1577,7 @@ "name": "expat", "originator": "Organization: Expat development team", "primaryPackagePurpose": "SOURCE", - "versionInfo": "2.6.0" + "versionInfo": "2.6.2" }, { "SPDXID": "SPDXRef-PACKAGE-hacl-star", diff --git a/Modules/expat/expat.h b/Modules/expat/expat.h index 95464b0dd177351..c2770be3897e58a 100644 --- a/Modules/expat/expat.h +++ b/Modules/expat/expat.h @@ -18,6 +18,7 @@ Copyright (c) 2022 Thijs Schreijer Copyright (c) 2023 Hanno Böck Copyright (c) 2023 Sony Corporation / Snild Dolkow + Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -1042,7 +1043,7 @@ typedef struct { XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); -#if XML_GE == 1 +#if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1) /* Added in Expat 2.4.0 for XML_DTD defined and * added in Expat 2.6.0 for XML_GE == 1. */ XMLPARSEAPI(XML_Bool) @@ -1065,7 +1066,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled); */ #define XML_MAJOR_VERSION 2 #define XML_MINOR_VERSION 6 -#define XML_MICRO_VERSION 0 +#define XML_MICRO_VERSION 2 #ifdef __cplusplus } diff --git a/Modules/expat/internal.h b/Modules/expat/internal.h index cce71e4c5164b51..167ec36804a43b0 100644 --- a/Modules/expat/internal.h +++ b/Modules/expat/internal.h @@ -28,10 +28,11 @@ Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2003 Greg Stein - Copyright (c) 2016-2023 Sebastian Pipping + Copyright (c) 2016-2024 Sebastian Pipping Copyright (c) 2018 Yury Gribov Copyright (c) 2019 David Loffredo - Copyright (c) 2023 Sony Corporation / Snild Dolkow + Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow + Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -155,14 +156,20 @@ extern "C" { void _INTERNAL_trim_to_complete_utf8_characters(const char *from, const char **fromLimRef); -#if XML_GE == 1 +#if defined(XML_GE) && XML_GE == 1 unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser); unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser); const char *unsignedCharToPrintable(unsigned char c); #endif -extern XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c -extern unsigned int g_parseAttempts; // used for testing only +extern +#if ! defined(XML_TESTING) + const +#endif + XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c +#if defined(XML_TESTING) +extern unsigned int g_bytesScanned; // used for testing only +#endif #ifdef __cplusplus } diff --git a/Modules/expat/xmlparse.c b/Modules/expat/xmlparse.c index aaf0fa9c8f96d1e..2951fec70c56cb9 100644 --- a/Modules/expat/xmlparse.c +++ b/Modules/expat/xmlparse.c @@ -1,4 +1,4 @@ -/* 628e24d4966bedbd4800f6ed128d06d29703765b4bce12d3b7f099f90f842fc9 (2.6.0+) +/* 2a14271ad4d35e82bde8ba210b4edb7998794bcbae54deab114046a300f9639a (2.6.2+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| @@ -38,7 +38,7 @@ Copyright (c) 2022 Jann Horn Copyright (c) 2022 Sean McBride Copyright (c) 2023 Owain Davies - Copyright (c) 2023 Sony Corporation / Snild Dolkow + Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining @@ -210,7 +210,7 @@ typedef char ICHAR; #endif /* Round up n to be a multiple of sz, where sz is a power of 2. */ -#define ROUND_UP(n, sz) (((n) + ((sz)-1)) & ~((sz)-1)) +#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) /* Do safe (NULL-aware) pointer arithmetic */ #define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0) @@ -248,7 +248,7 @@ static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key); it odd, since odd numbers are always relative prime to a power of 2. */ #define SECOND_HASH(hash, mask, power) \ - ((((hash) & ~(mask)) >> ((power)-1)) & ((mask) >> 2)) + ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2)) #define PROBE_STEP(hash, mask, power) \ ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1)) @@ -629,8 +629,14 @@ static unsigned long getDebugLevel(const char *variableName, ? 0 \ : ((*((pool)->ptr)++ = c), 1)) -XML_Bool g_reparseDeferralEnabledDefault = XML_TRUE; // write ONLY in runtests.c -unsigned int g_parseAttempts = 0; // used for testing only +#if ! defined(XML_TESTING) +const +#endif + XML_Bool g_reparseDeferralEnabledDefault + = XML_TRUE; // write ONLY in runtests.c +#if defined(XML_TESTING) +unsigned int g_bytesScanned = 0; // used for testing only +#endif struct XML_ParserStruct { /* The first member must be m_userData so that the XML_GetUserData @@ -1017,7 +1023,9 @@ callProcessor(XML_Parser parser, const char *start, const char *end, return XML_ERROR_NONE; } } - g_parseAttempts += 1; +#if defined(XML_TESTING) + g_bytesScanned += (unsigned)have_now; +#endif const enum XML_Error ret = parser->m_processor(parser, start, end, endPtr); if (ret == XML_ERROR_NONE) { // if we consumed nothing, remember what we had on this parse attempt. @@ -6232,7 +6240,7 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc, dtd->keepProcessing = dtd->standalone; goto endEntityValue; } - if (entity->open) { + if (entity->open || (entity == parser->m_declEntity)) { if (enc == parser->m_encoding) parser->m_eventPtr = entityTextPtr; result = XML_ERROR_RECURSIVE_ENTITY_REF; @@ -7779,6 +7787,8 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { static float accountingGetCurrentAmplification(XML_Parser rootParser) { + // 1.........1.........12 => 22 + const size_t lenOfShortestInclude = sizeof("") - 1; const XmlBigCount countBytesOutput = rootParser->m_accounting.countBytesDirect + rootParser->m_accounting.countBytesIndirect; @@ -7786,7 +7796,9 @@ accountingGetCurrentAmplification(XML_Parser rootParser) { = rootParser->m_accounting.countBytesDirect ? (countBytesOutput / (float)(rootParser->m_accounting.countBytesDirect)) - : 1.0f; + : ((lenOfShortestInclude + + rootParser->m_accounting.countBytesIndirect) + / (float)lenOfShortestInclude); assert(! rootParser->m_parentParser); return amplificationFactor; } From 8e86579caef59fad0c54ac698d589f23a7951c55 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Mon, 22 Apr 2024 18:24:21 -0700 Subject: [PATCH 094/127] gh-95754: Better error when script shadows a standard library or third party module (#113769) --- Doc/whatsnew/3.13.rst | 34 +++ .../pycore_global_objects_fini_generated.h | 1 + Include/internal/pycore_global_strings.h | 1 + .../internal/pycore_runtime_init_generated.h | 1 + .../internal/pycore_unicodeobject_generated.h | 3 + Lib/test/test_import/__init__.py | 221 ++++++++++++++++ ...4-01-07-03-38-34.gh-issue-95754.aPjEBG.rst | 4 + Objects/moduleobject.c | 244 ++++++++++++++---- 8 files changed, 456 insertions(+), 53 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-01-07-03-38-34.gh-issue-95754.aPjEBG.rst diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 67d1956a19697e6..89694afdfa3fece 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -104,6 +104,40 @@ Improved Error Messages variables. See also :ref:`using-on-controlling-color`. (Contributed by Pablo Galindo Salgado in :gh:`112730`.) +* A common mistake is to write a script with the same name as a + standard library module. When this results in errors, we now + display a more helpful error message: + + .. code-block:: shell-session + + $ python random.py + Traceback (most recent call last): + File "/home/random.py", line 1, in + import random; print(random.randint(5)) + ^^^^^^^^^^^^^ + File "/home/random.py", line 1, in + import random; print(random.randint(5)) + ^^^^^^^^^^^^^^ + AttributeError: module 'random' has no attribute 'randint' (consider renaming '/home/random.py' since it has the same name as the standard library module named 'random' and the import system gives it precedence) + + Similarly, if a script has the same name as a third-party + module it attempts to import, and this results in errors, + we also display a more helpful error message: + + .. code-block:: shell-session + + $ python numpy.py + Traceback (most recent call last): + File "/home/numpy.py", line 1, in + import numpy as np; np.array([1,2,3]) + ^^^^^^^^^^^^^^^^^^ + File "/home/numpy.py", line 1, in + import numpy as np; np.array([1,2,3]) + ^^^^^^^^ + AttributeError: module 'numpy' has no attribute 'array' (consider renaming '/home/numpy.py' if it has the same name as a third-party module you intended to import) + + (Contributed by Shantanu Jain in :gh:`95754`.) + * When an incorrect keyword argument is passed to a function, the error message now potentially suggests the correct keyword argument. (Contributed by Pablo Galindo Salgado and Shantanu Jain in :gh:`107944`.) diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 90a338ade17c61b..4a6f40c84088e84 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -981,6 +981,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(h)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(handle)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(handle_seq)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(has_location)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(hash_name)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(header)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(headers)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 0899e7ee776617a..8332cdf874c0c98 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -470,6 +470,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(h) STRUCT_FOR_ID(handle) STRUCT_FOR_ID(handle_seq) + STRUCT_FOR_ID(has_location) STRUCT_FOR_ID(hash_name) STRUCT_FOR_ID(header) STRUCT_FOR_ID(headers) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index d4323e5bd12a67e..103279a4cf228b1 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -979,6 +979,7 @@ extern "C" { INIT_ID(h), \ INIT_ID(handle), \ INIT_ID(handle_seq), \ + INIT_ID(has_location), \ INIT_ID(hash_name), \ INIT_ID(header), \ INIT_ID(headers), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 9daef267069d0d1..a180054d407b39a 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1251,6 +1251,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(handle_seq); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(has_location); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(hash_name); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 469d1fbe59aaa2d..947a7b19056bdbf 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -804,6 +804,227 @@ def test_issue105979(self): self.assertIn("Frozen object named 'x' is invalid", str(cm.exception)) + def test_script_shadowing_stdlib(self): + with os_helper.temp_dir() as tmp: + with open(os.path.join(tmp, "fractions.py"), "w", encoding='utf-8') as f: + f.write("import fractions\nfractions.Fraction") + + expected_error = ( + rb"AttributeError: module 'fractions' has no attribute 'Fraction' " + rb"\(consider renaming '.*fractions.py' since it has the " + rb"same name as the standard library module named 'fractions' " + rb"and the import system gives it precedence\)" + ) + + popen = script_helper.spawn_python(os.path.join(tmp, "fractions.py"), cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + popen = script_helper.spawn_python('-m', 'fractions', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + popen = script_helper.spawn_python('-c', 'import fractions', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + # and there's no error at all when using -P + popen = script_helper.spawn_python('-P', 'fractions.py', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertEqual(stdout, b'') + + tmp_child = os.path.join(tmp, "child") + os.mkdir(tmp_child) + + # test the logic with different cwd + popen = script_helper.spawn_python(os.path.join(tmp, "fractions.py"), cwd=tmp_child) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + popen = script_helper.spawn_python('-m', 'fractions', cwd=tmp_child) + stdout, stderr = popen.communicate() + self.assertEqual(stdout, b'') # no error + + popen = script_helper.spawn_python('-c', 'import fractions', cwd=tmp_child) + stdout, stderr = popen.communicate() + self.assertEqual(stdout, b'') # no error + + def test_package_shadowing_stdlib_module(self): + with os_helper.temp_dir() as tmp: + os.mkdir(os.path.join(tmp, "fractions")) + with open(os.path.join(tmp, "fractions", "__init__.py"), "w", encoding='utf-8') as f: + f.write("shadowing_module = True") + with open(os.path.join(tmp, "main.py"), "w", encoding='utf-8') as f: + f.write(""" +import fractions +fractions.shadowing_module +fractions.Fraction +""") + + expected_error = ( + rb"AttributeError: module 'fractions' has no attribute 'Fraction' " + rb"\(consider renaming '.*fractions.__init__.py' since it has the " + rb"same name as the standard library module named 'fractions' " + rb"and the import system gives it precedence\)" + ) + + popen = script_helper.spawn_python(os.path.join(tmp, "main.py"), cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + popen = script_helper.spawn_python('-m', 'main', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + # and there's no shadowing at all when using -P + popen = script_helper.spawn_python('-P', 'main.py', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, b"module 'fractions' has no attribute 'shadowing_module'") + + def test_script_shadowing_third_party(self): + with os_helper.temp_dir() as tmp: + with open(os.path.join(tmp, "numpy.py"), "w", encoding='utf-8') as f: + f.write("import numpy\nnumpy.array") + + expected_error = ( + rb"AttributeError: module 'numpy' has no attribute 'array' " + rb"\(consider renaming '.*numpy.py' if it has the " + rb"same name as a third-party module you intended to import\)\s+\Z" + ) + + popen = script_helper.spawn_python(os.path.join(tmp, "numpy.py")) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + popen = script_helper.spawn_python('-m', 'numpy', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + popen = script_helper.spawn_python('-c', 'import numpy', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + def test_script_maybe_not_shadowing_third_party(self): + with os_helper.temp_dir() as tmp: + with open(os.path.join(tmp, "numpy.py"), "w", encoding='utf-8') as f: + f.write("this_script_does_not_attempt_to_import_numpy = True") + + expected_error = ( + rb"AttributeError: module 'numpy' has no attribute 'attr'\s+\Z" + ) + + popen = script_helper.spawn_python('-c', 'import numpy; numpy.attr', cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + + def test_script_shadowing_stdlib_edge_cases(self): + with os_helper.temp_dir() as tmp: + with open(os.path.join(tmp, "fractions.py"), "w", encoding='utf-8') as f: + f.write("shadowing_module = True") + with open(os.path.join(tmp, "main.py"), "w", encoding='utf-8') as f: + f.write(""" +import fractions +fractions.shadowing_module +class substr(str): + __hash__ = None +fractions.__name__ = substr('fractions') +try: + fractions.Fraction +except TypeError as e: + print(str(e)) +""") + + popen = script_helper.spawn_python("main.py", cwd=tmp) + stdout, stderr = popen.communicate() + self.assertEqual(stdout.rstrip(), b"unhashable type: 'substr'") + + with open(os.path.join(tmp, "main.py"), "w", encoding='utf-8') as f: + f.write(""" +import fractions +fractions.shadowing_module + +import sys +sys.stdlib_module_names = None +try: + fractions.Fraction +except AttributeError as e: + print(str(e)) + +del sys.stdlib_module_names +try: + fractions.Fraction +except AttributeError as e: + print(str(e)) + +sys.path = [0] +try: + fractions.Fraction +except AttributeError as e: + print(str(e)) +""") + + popen = script_helper.spawn_python("main.py", cwd=tmp) + stdout, stderr = popen.communicate() + self.assertEqual( + stdout.splitlines(), + [ + b"module 'fractions' has no attribute 'Fraction'", + b"module 'fractions' has no attribute 'Fraction'", + b"module 'fractions' has no attribute 'Fraction'", + ], + ) + + with open(os.path.join(tmp, "main.py"), "w", encoding='utf-8') as f: + f.write(""" +import fractions +fractions.shadowing_module +del fractions.__spec__.origin +try: + fractions.Fraction +except AttributeError as e: + print(str(e)) + +fractions.__spec__.origin = 0 +try: + fractions.Fraction +except AttributeError as e: + print(str(e)) +""") + + popen = script_helper.spawn_python("main.py", cwd=tmp) + stdout, stderr = popen.communicate() + self.assertEqual( + stdout.splitlines(), + [ + b"module 'fractions' has no attribute 'Fraction'", + b"module 'fractions' has no attribute 'Fraction'" + ], + ) + + def test_script_shadowing_stdlib_sys_path_modification(self): + with os_helper.temp_dir() as tmp: + with open(os.path.join(tmp, "fractions.py"), "w", encoding='utf-8') as f: + f.write("shadowing_module = True") + + expected_error = ( + rb"AttributeError: module 'fractions' has no attribute 'Fraction' " + rb"\(consider renaming '.*fractions.py' since it has the " + rb"same name as the standard library module named 'fractions' " + rb"and the import system gives it precedence\)" + ) + + with open(os.path.join(tmp, "main.py"), "w", encoding='utf-8') as f: + f.write(""" +import sys +sys.path.insert(0, "this_folder_does_not_exist") +import fractions +fractions.Fraction +""") + + popen = script_helper.spawn_python("main.py", cwd=tmp) + stdout, stderr = popen.communicate() + self.assertRegex(stdout, expected_error) + @skip_if_dont_write_bytecode class FilePermissionTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-01-07-03-38-34.gh-issue-95754.aPjEBG.rst b/Misc/NEWS.d/next/Core and Builtins/2024-01-07-03-38-34.gh-issue-95754.aPjEBG.rst new file mode 100644 index 000000000000000..588be2d28cd76e2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-01-07-03-38-34.gh-issue-95754.aPjEBG.rst @@ -0,0 +1,4 @@ +Improve the error message when a script shadowing a module from the standard +library causes :exc:`AttributeError` to be raised. Similarly, improve the error +message when a script shadowing a third party module attempts to access an +attribute from that third party module while still initialising. diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index da6a276c41be1fe..2f6adb9a2e12be5 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_fileutils.h" // _Py_wgetcwd #include "pycore_interp.h" // PyInterpreterState.importlib #include "pycore_modsupport.h" // _PyModule_CreateInitialized() #include "pycore_moduleobject.h" // _PyModule_GetDef() @@ -10,6 +11,7 @@ #include "pycore_pyerrors.h" // _PyErr_FormatFromCause() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "osdefs.h" // MAXPATHLEN static PyMemberDef module_members[] = { @@ -785,11 +787,104 @@ _PyModuleSpec_IsUninitializedSubmodule(PyObject *spec, PyObject *name) return rc; } +static int +_get_file_origin_from_spec(PyObject *spec, PyObject **p_origin) +{ + PyObject *has_location = NULL; + int rc = PyObject_GetOptionalAttr(spec, &_Py_ID(has_location), &has_location); + if (rc <= 0) { + return rc; + } + // If origin is not a location, or doesn't exist, or is not a str), we could consider falling + // back to module.__file__. But the cases in which module.__file__ is not __spec__.origin + // are cases in which we probably shouldn't be guessing. + rc = PyObject_IsTrue(has_location); + Py_DECREF(has_location); + if (rc <= 0) { + return rc; + } + // has_location is true, so origin is a location + PyObject *origin = NULL; + rc = PyObject_GetOptionalAttr(spec, &_Py_ID(origin), &origin); + if (rc <= 0) { + return rc; + } + assert(origin != NULL); + if (!PyUnicode_Check(origin)) { + Py_DECREF(origin); + return 0; + } + *p_origin = origin; + return 1; +} + +static int +_is_module_possibly_shadowing(PyObject *origin) +{ + // origin must be a unicode subtype + // Returns 1 if the module at origin could be shadowing a module of the + // same name later in the module search path. The condition we check is basically: + // root = os.path.dirname(origin.removesuffix(os.sep + "__init__.py")) + // return not sys.flags.safe_path and root == (sys.path[0] or os.getcwd()) + // Returns 0 otherwise (or if we aren't sure) + // Returns -1 if an error occurred that should be propagated + if (origin == NULL) { + return 0; + } + + // not sys.flags.safe_path + const PyConfig *config = _Py_GetConfig(); + if (config->safe_path) { + return 0; + } + + // root = os.path.dirname(origin.removesuffix(os.sep + "__init__.py")) + wchar_t root[MAXPATHLEN + 1]; + Py_ssize_t size = PyUnicode_AsWideChar(origin, root, MAXPATHLEN); + if (size < 0) { + return -1; + } + assert(size <= MAXPATHLEN); + root[size] = L'\0'; + + wchar_t *sep = wcsrchr(root, SEP); + if (sep == NULL) { + return 0; + } + // If it's a package then we need to look one directory further up + if (wcscmp(sep + 1, L"__init__.py") == 0) { + *sep = L'\0'; + sep = wcsrchr(root, SEP); + if (sep == NULL) { + return 0; + } + } + *sep = L'\0'; + + // sys.path[0] or os.getcwd() + wchar_t *sys_path_0 = config->sys_path_0; + if (!sys_path_0) { + return 0; + } + + wchar_t sys_path_0_buf[MAXPATHLEN]; + if (sys_path_0[0] == L'\0') { + // if sys.path[0] == "", treat it as if it were the current directory + if (!_Py_wgetcwd(sys_path_0_buf, MAXPATHLEN)) { + return -1; + } + sys_path_0 = sys_path_0_buf; + } + + int result = wcscmp(sys_path_0, root) == 0; + return result; +} + PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) { // When suppress=1, this function suppresses AttributeError. - PyObject *attr, *mod_name, *getattr, *origin; + PyObject *attr, *mod_name, *getattr; attr = _PyObject_GenericGetAttrWithDict((PyObject *)m, name, NULL, suppress); if (attr) { return attr; @@ -820,68 +915,111 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) Py_DECREF(getattr); return result; } + + // The attribute was not found. We make a best effort attempt at a useful error message, + // but only if we're not suppressing AttributeError. + if (suppress == 1) { + return NULL; + } if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__name__), &mod_name) < 0) { return NULL; } - if (mod_name && PyUnicode_Check(mod_name)) { - PyObject *spec; - if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__spec__), &spec) < 0) { - Py_DECREF(mod_name); - return NULL; + if (!mod_name || !PyUnicode_Check(mod_name)) { + Py_XDECREF(mod_name); + PyErr_Format(PyExc_AttributeError, + "module has no attribute '%U'", name); + return NULL; + } + PyObject *spec; + if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__spec__), &spec) < 0) { + Py_DECREF(mod_name); + return NULL; + } + if (spec == NULL) { + PyErr_Format(PyExc_AttributeError, + "module '%U' has no attribute '%U'", + mod_name, name); + Py_DECREF(mod_name); + return NULL; + } + + PyObject *origin = NULL; + if (_get_file_origin_from_spec(spec, &origin) < 0) { + goto done; + } + + int is_possibly_shadowing = _is_module_possibly_shadowing(origin); + if (is_possibly_shadowing < 0) { + goto done; + } + int is_possibly_shadowing_stdlib = 0; + if (is_possibly_shadowing) { + PyObject *stdlib_modules = PySys_GetObject("stdlib_module_names"); + if (stdlib_modules && PyAnySet_Check(stdlib_modules)) { + is_possibly_shadowing_stdlib = PySet_Contains(stdlib_modules, mod_name); + if (is_possibly_shadowing_stdlib < 0) { + goto done; + } + } + } + + if (is_possibly_shadowing_stdlib) { + assert(origin); + PyErr_Format(PyExc_AttributeError, + "module '%U' has no attribute '%U' " + "(consider renaming '%U' since it has the same " + "name as the standard library module named '%U' " + "and the import system gives it precedence)", + mod_name, name, origin, mod_name); + } + else { + int rc = _PyModuleSpec_IsInitializing(spec); + if (rc > 0) { + if (is_possibly_shadowing) { + assert(origin); + // For third-party modules, only mention the possibility of + // shadowing if the module is being initialized. + PyErr_Format(PyExc_AttributeError, + "module '%U' has no attribute '%U' " + "(consider renaming '%U' if it has the same name " + "as a third-party module you intended to import)", + mod_name, name, origin); + } + else if (origin) { + PyErr_Format(PyExc_AttributeError, + "partially initialized " + "module '%U' from '%U' has no attribute '%U' " + "(most likely due to a circular import)", + mod_name, origin, name); + } + else { + PyErr_Format(PyExc_AttributeError, + "partially initialized " + "module '%U' has no attribute '%U' " + "(most likely due to a circular import)", + mod_name, name); + } } - if (suppress != 1) { - int rc = _PyModuleSpec_IsInitializing(spec); + else if (rc == 0) { + rc = _PyModuleSpec_IsUninitializedSubmodule(spec, name); if (rc > 0) { - int valid_spec = PyObject_GetOptionalAttr(spec, &_Py_ID(origin), &origin); - if (valid_spec == -1) { - Py_XDECREF(spec); - Py_DECREF(mod_name); - return NULL; - } - if (valid_spec == 1 && !PyUnicode_Check(origin)) { - valid_spec = 0; - Py_DECREF(origin); - } - if (valid_spec == 1) { - PyErr_Format(PyExc_AttributeError, - "partially initialized " - "module '%U' from '%U' has no attribute '%U' " - "(most likely due to a circular import)", - mod_name, origin, name); - Py_DECREF(origin); - } - else { - PyErr_Format(PyExc_AttributeError, - "partially initialized " - "module '%U' has no attribute '%U' " - "(most likely due to a circular import)", - mod_name, name); - } + PyErr_Format(PyExc_AttributeError, + "cannot access submodule '%U' of module '%U' " + "(most likely due to a circular import)", + name, mod_name); } else if (rc == 0) { - rc = _PyModuleSpec_IsUninitializedSubmodule(spec, name); - if (rc > 0) { - PyErr_Format(PyExc_AttributeError, - "cannot access submodule '%U' of module '%U' " - "(most likely due to a circular import)", - name, mod_name); - } - else if (rc == 0) { - PyErr_Format(PyExc_AttributeError, - "module '%U' has no attribute '%U'", - mod_name, name); - } + PyErr_Format(PyExc_AttributeError, + "module '%U' has no attribute '%U'", + mod_name, name); } } - Py_XDECREF(spec); - Py_DECREF(mod_name); - return NULL; - } - Py_XDECREF(mod_name); - if (suppress != 1) { - PyErr_Format(PyExc_AttributeError, - "module has no attribute '%U'", name); } + +done: + Py_XDECREF(origin); + Py_DECREF(spec); + Py_DECREF(mod_name); return NULL; } From 456c29cf85847c67dfc0fa36d6fe6168569b46fe Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Tue, 23 Apr 2024 09:46:28 +0200 Subject: [PATCH 095/127] gh-118039: Fix config.cache key on WASI (#118137) --- .github/workflows/build.yml | 1 + .github/workflows/reusable-wasi.yml | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e1a2a62c60c6de1..299c02e0944d429 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -137,6 +137,7 @@ jobs: uses: actions/cache@v4 with: path: config.cache + # Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ needs.check_source.outputs.config_hash }}-${{ env.pythonLocation }} - name: Install Dependencies run: sudo ./.github/workflows/posix-deps-apt.sh diff --git a/.github/workflows/reusable-wasi.yml b/.github/workflows/reusable-wasi.yml index 60eef7bc478bbfe..4a509a8acfee961 100644 --- a/.github/workflows/reusable-wasi.yml +++ b/.github/workflows/reusable-wasi.yml @@ -50,7 +50,8 @@ jobs: uses: actions/cache@v4 with: path: ${{ env.CROSS_BUILD_PYTHON }}/config.cache - key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }} + # Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python + key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-${{ inputs.config_hash }}-${{ env.pythonLocation }} - name: "Configure build Python" run: python3 Tools/wasm/wasi.py configure-build-python -- --config-cache --with-pydebug - name: "Make build Python" @@ -59,7 +60,8 @@ jobs: uses: actions/cache@v4 with: path: ${{ env.CROSS_BUILD_WASI }}/config.cache - key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}-${{ inputs.config_hash }} + # Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python + key: ${{ github.job }}-${{ runner.os }}-${{ env.IMAGE_VERSION }}-wasi-sdk-${{ env.WASI_SDK_VERSION }}-${{ inputs.config_hash }}-${{ env.pythonLocation }} - name: "Configure host" # `--with-pydebug` inferred from configure-build-python run: python3 Tools/wasm/wasi.py configure-host -- --config-cache From e17cd1fbfd4f20824c686c7242423e84ba6a6cc5 Mon Sep 17 00:00:00 2001 From: Yichen Yan Date: Tue, 23 Apr 2024 15:56:00 +0800 Subject: [PATCH 096/127] gh-116984: Install mimalloc headers (#116985) - Install mimalloc header only when enabled - Rename WITH_MIMALLOC to INSTALL_MIMALLOC --- Makefile.pre.in | 19 +++++++++++++++++++ configure | 3 ++- configure.ac | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index f7c21a380caa99f..c7cf44de2dbe79a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -233,6 +233,9 @@ LIBHACL_SHA2_A= Modules/_hacl/libHacl_Hash_SHA2.a # Default zoneinfo.TZPATH. Added here to expose it in sysconfig.get_config_var TZPATH=@TZPATH@ +# If to install mimalloc headers +INSTALL_MIMALLOC=@INSTALL_MIMALLOC@ + # Modes for directories, executables and data files created by the # install process. Default to user-only-writable for all file types. DIRMODE= 755 @@ -2616,6 +2619,12 @@ inclinstall: $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(INCLUDEPY)/internal; \ else true; \ fi + @if test "$(INSTALL_MIMALLOC)" == "yes"; then \ + if test ! -d $(DESTDIR)$(INCLUDEPY)/internal/mimalloc/mimalloc; then \ + echo "Creating directory $(DESTDIR)$(INCLUDEPY)/internal/mimalloc/mimalloc"; \ + $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(INCLUDEPY)/internal/mimalloc/mimalloc; \ + fi; \ + fi @for i in $(srcdir)/Include/*.h; \ do \ echo $(INSTALL_DATA) $$i $(INCLUDEPY); \ @@ -2631,6 +2640,16 @@ inclinstall: echo $(INSTALL_DATA) $$i $(INCLUDEPY)/internal; \ $(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEPY)/internal; \ done + @if test "$(INSTALL_MIMALLOC)" == "yes"; then \ + echo $(INSTALL_DATA) $(srcdir)/Include/internal/mimalloc/mimalloc.h $(DESTDIR)$(INCLUDEPY)/internal/mimalloc/mimalloc.h; \ + $(INSTALL_DATA) $(srcdir)/Include/internal/mimalloc/mimalloc.h $(DESTDIR)$(INCLUDEPY)/internal/mimalloc/mimalloc.h; \ + for i in $(srcdir)/Include/internal/mimalloc/mimalloc/*.h; \ + do \ + echo $(INSTALL_DATA) $$i $(INCLUDEPY)/internal/mimalloc/mimalloc; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(INCLUDEPY)/internal/mimalloc/mimalloc; \ + done; \ + fi + echo $(INSTALL_DATA) pyconfig.h $(DESTDIR)$(CONFINCLUDEPY)/pyconfig.h $(INSTALL_DATA) pyconfig.h $(DESTDIR)$(CONFINCLUDEPY)/pyconfig.h # Install the library and miscellaneous stuff needed for extending/embedding diff --git a/configure b/configure index 29a7d5b2b86c293..94ee1ca9cd0b8dc 100755 --- a/configure +++ b/configure @@ -869,7 +869,7 @@ DTRACE_OBJS DTRACE_HEADERS DFLAGS DTRACE -WITH_MIMALLOC +INSTALL_MIMALLOC MIMALLOC_HEADERS GDBM_LIBS GDBM_CFLAGS @@ -17335,6 +17335,7 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_mimalloc" >&5 printf "%s\n" "$with_mimalloc" >&6; } +INSTALL_MIMALLOC=$with_mimalloc diff --git a/configure.ac b/configure.ac index 7723c805b93daee..7877ef45c2e500c 100644 --- a/configure.ac +++ b/configure.ac @@ -4779,7 +4779,7 @@ elif test "$disable_gil" = "yes"; then fi AC_MSG_RESULT([$with_mimalloc]) -AC_SUBST([WITH_MIMALLOC]) +AC_SUBST([INSTALL_MIMALLOC], [$with_mimalloc]) AC_SUBST([MIMALLOC_HEADERS]) # Check for Python-specific malloc support From eb927e9fc823de9539fcb82c9ea9d055462eb04a Mon Sep 17 00:00:00 2001 From: Joe Jevnik Date: Tue, 23 Apr 2024 07:15:15 -0400 Subject: [PATCH 097/127] gh-68114: Fix handling for removed PyArg_ParseTuple 'w' formatters (GH-8204) Co-authored-by: Joe Jevnik Co-authored-by: Petr Viktorin --- Lib/test/test_capi/test_getargs.py | 38 +++--- ...4-03-18-17-29-52.gh-issue-68114.W7R_lI.rst | 2 + Modules/_testcapi/getargs.c | 118 ++++++++++++++++++ Python/getargs.c | 5 + 4 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2024-03-18-17-29-52.gh-issue-68114.W7R_lI.rst diff --git a/Lib/test/test_capi/test_getargs.py b/Lib/test/test_capi/test_getargs.py index 12039803ba543eb..e710400f75c235e 100644 --- a/Lib/test/test_capi/test_getargs.py +++ b/Lib/test/test_capi/test_getargs.py @@ -856,20 +856,24 @@ def test_y_hash(self): def test_w_star(self): # getargs_w_star() modifies first and last byte - from _testcapi import getargs_w_star - self.assertRaises(TypeError, getargs_w_star, 'abc\xe9') - self.assertRaises(TypeError, getargs_w_star, b'bytes') - self.assertRaises(TypeError, getargs_w_star, b'nul:\0') - self.assertRaises(TypeError, getargs_w_star, memoryview(b'bytes')) - buf = bytearray(b'bytearray') - self.assertEqual(getargs_w_star(buf), b'[ytearra]') - self.assertEqual(buf, bytearray(b'[ytearra]')) - buf = bytearray(b'memoryview') - self.assertEqual(getargs_w_star(memoryview(buf)), b'[emoryvie]') - self.assertEqual(buf, bytearray(b'[emoryvie]')) - self.assertRaises(TypeError, getargs_w_star, None) - self.assertRaises(TypeError, getargs_w_star, NONCONTIG_WRITABLE) - self.assertRaises(TypeError, getargs_w_star, NONCONTIG_READONLY) + # getargs_w_star_opt() takes additional optional args: with one + # argument it should behave the same as getargs_w_star + from _testcapi import getargs_w_star, getargs_w_star_opt + for func in (getargs_w_star, getargs_w_star_opt): + with self.subTest(func=func): + self.assertRaises(TypeError, func, 'abc\xe9') + self.assertRaises(TypeError, func, b'bytes') + self.assertRaises(TypeError, func, b'nul:\0') + self.assertRaises(TypeError, func, memoryview(b'bytes')) + buf = bytearray(b'bytearray') + self.assertEqual(func(buf), b'[ytearra]') + self.assertEqual(buf, bytearray(b'[ytearra]')) + buf = bytearray(b'memoryview') + self.assertEqual(func(memoryview(buf)), b'[emoryvie]') + self.assertEqual(buf, bytearray(b'[emoryvie]')) + self.assertRaises(TypeError, func, None) + self.assertRaises(TypeError, func, NONCONTIG_WRITABLE) + self.assertRaises(TypeError, func, NONCONTIG_READONLY) def test_getargs_empty(self): from _testcapi import getargs_empty @@ -1112,9 +1116,9 @@ def test_skipitem(self): c = chr(i) # skip parentheses, the error reporting is inconsistent about them - # skip 'e', it's always a two-character code + # skip 'e' and 'w', they're always two-character codes # skip '|' and '$', they don't represent arguments anyway - if c in '()e|$': + if c in '()ew|$': continue # test the format unit when not skipped @@ -1152,7 +1156,7 @@ def test_skipitem_with_suffix(self): dict_b = {'b':1} keywords = ["a", "b"] - supported = ('s#', 's*', 'z#', 'z*', 'y#', 'y*', 'w#', 'w*') + supported = ('s#', 's*', 'z#', 'z*', 'y#', 'y*', 'w*') for c in string.ascii_letters: for c2 in '#*': f = c + c2 diff --git a/Misc/NEWS.d/next/C API/2024-03-18-17-29-52.gh-issue-68114.W7R_lI.rst b/Misc/NEWS.d/next/C API/2024-03-18-17-29-52.gh-issue-68114.W7R_lI.rst new file mode 100644 index 000000000000000..fa09d2a0a72df7d --- /dev/null +++ b/Misc/NEWS.d/next/C API/2024-03-18-17-29-52.gh-issue-68114.W7R_lI.rst @@ -0,0 +1,2 @@ +Fixed skipitem()'s handling of the old 'w' and 'w#' formatters. These are +no longer supported and now raise an exception if used. diff --git a/Modules/_testcapi/getargs.c b/Modules/_testcapi/getargs.c index 0d61d8c8969f827..ee04c760d272132 100644 --- a/Modules/_testcapi/getargs.c +++ b/Modules/_testcapi/getargs.c @@ -141,6 +141,122 @@ getargs_w_star(PyObject *self, PyObject *args) return result; } +static PyObject * +getargs_w_star_opt(PyObject *self, PyObject *args) +{ + Py_buffer buffer; + Py_buffer buf2; + int number = 1; + + if (!PyArg_ParseTuple(args, "w*|w*i:getargs_w_star", + &buffer, &buf2, &number)) { + return NULL; + } + + if (2 <= buffer.len) { + char *str = buffer.buf; + str[0] = '['; + str[buffer.len-1] = ']'; + } + + PyObject *result = PyBytes_FromStringAndSize(buffer.buf, buffer.len); + PyBuffer_Release(&buffer); + return result; +} + +/* Test the old w and w# codes that no longer work */ +static PyObject * +test_w_code_invalid(PyObject *self, PyObject *arg) +{ + static const char * const keywords[] = {"a", "b", "c", "d", NULL}; + char *formats_3[] = {"O|w#$O", + "O|w$O", + "O|w#O", + "O|wO", + NULL}; + char *formats_4[] = {"O|w#O$O", + "O|wO$O", + "O|Ow#O", + "O|OwO", + "O|Ow#$O", + "O|Ow$O", + NULL}; + size_t n; + PyObject *args; + PyObject *kwargs; + PyObject *tmp; + + if (!(args = PyTuple_Pack(1, Py_None))) { + return NULL; + } + + kwargs = PyDict_New(); + if (!kwargs) { + Py_DECREF(args); + return NULL; + } + + if (PyDict_SetItemString(kwargs, "c", Py_None)) { + Py_DECREF(args); + Py_XDECREF(kwargs); + return NULL; + } + + for (n = 0; formats_3[n]; ++n) { + if (PyArg_ParseTupleAndKeywords(args, kwargs, formats_3[n], + (char**) keywords, + &tmp, &tmp, &tmp)) { + Py_DECREF(args); + Py_DECREF(kwargs); + PyErr_Format(PyExc_AssertionError, + "test_w_code_invalid_suffix: %s", + formats_3[n]); + return NULL; + } + else { + if (!PyErr_ExceptionMatches(PyExc_SystemError)) { + Py_DECREF(args); + Py_DECREF(kwargs); + return NULL; + } + PyErr_Clear(); + } + } + + if (PyDict_DelItemString(kwargs, "c") || + PyDict_SetItemString(kwargs, "d", Py_None)) { + + Py_DECREF(kwargs); + Py_DECREF(args); + return NULL; + } + + for (n = 0; formats_4[n]; ++n) { + if (PyArg_ParseTupleAndKeywords(args, kwargs, formats_4[n], + (char**) keywords, + &tmp, &tmp, &tmp, &tmp)) { + Py_DECREF(args); + Py_DECREF(kwargs); + PyErr_Format(PyExc_AssertionError, + "test_w_code_invalid_suffix: %s", + formats_4[n]); + return NULL; + } + else { + if (!PyErr_ExceptionMatches(PyExc_SystemError)) { + Py_DECREF(args); + Py_DECREF(kwargs); + return NULL; + } + PyErr_Clear(); + } + } + + Py_DECREF(args); + Py_DECREF(kwargs); + Py_RETURN_NONE; +} + static PyObject * getargs_empty(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -684,6 +800,7 @@ static PyMethodDef test_methods[] = { {"getargs_s_star", getargs_s_star, METH_VARARGS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, {"getargs_w_star", getargs_w_star, METH_VARARGS}, + {"getargs_w_star_opt", getargs_w_star_opt, METH_VARARGS}, {"getargs_empty", _PyCFunction_CAST(getargs_empty), METH_VARARGS|METH_KEYWORDS}, {"getargs_y", getargs_y, METH_VARARGS}, {"getargs_y_hash", getargs_y_hash, METH_VARARGS}, @@ -693,6 +810,7 @@ static PyMethodDef test_methods[] = { {"getargs_z_star", getargs_z_star, METH_VARARGS}, {"parse_tuple_and_keywords", parse_tuple_and_keywords, METH_VARARGS}, {"gh_99240_clear_args", gh_99240_clear_args, METH_VARARGS}, + {"test_w_code_invalid", test_w_code_invalid, METH_NOARGS}, {NULL}, }; diff --git a/Python/getargs.c b/Python/getargs.c index bec981698767ca0..539925e471f54c0 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2641,6 +2641,11 @@ skipitem(const char **p_format, va_list *p_va, int flags) if (p_va != NULL) { (void) va_arg(*p_va, char **); } + if (c == 'w' && *format != '*') + { + /* after 'w', only '*' is allowed */ + goto err; + } if (*format == '#') { if (p_va != NULL) { (void) va_arg(*p_va, Py_ssize_t *); From de1f6868270d31f56c388ef416daacd35feb152d Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Tue, 23 Apr 2024 15:00:52 +0300 Subject: [PATCH 098/127] gh-118082: Improve `import` without names syntax error message (#118083) --- Grammar/python.gram | 4 + Lib/test/test_syntax.py | 12 + ...-04-19-11-59-57.gh-issue-118082._FLuOT.rst | 3 + Parser/parser.c | 349 ++++++++++-------- 4 files changed, 219 insertions(+), 149 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-19-11-59-57.gh-issue-118082._FLuOT.rst diff --git a/Grammar/python.gram b/Grammar/python.gram index 9564abf5ec314b7..11438e57da527bf 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -1299,10 +1299,14 @@ invalid_group: invalid_import: | a='import' ','.dotted_name+ 'from' dotted_name { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "Did you mean to use 'from ... import ...' instead?") } + | 'import' token=NEWLINE { + RAISE_SYNTAX_ERROR_STARTING_FROM(token, "Expected one or more names after 'import'") } invalid_import_from_targets: | import_from_as_names ',' NEWLINE { RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") } + | token=NEWLINE { + RAISE_SYNTAX_ERROR_STARTING_FROM(token, "Expected one or more names after 'import'") } invalid_compound_stmt: | a='elif' named_expression ':' { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "'elif' must match an if-statement here") } diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index dfa2a3b2f5413b0..e9bec3317811dd6 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1699,6 +1699,18 @@ Traceback (most recent call last): SyntaxError: invalid syntax +>>> from i import +Traceback (most recent call last): +SyntaxError: Expected one or more names after 'import' + +>>> from .. import +Traceback (most recent call last): +SyntaxError: Expected one or more names after 'import' + +>>> import +Traceback (most recent call last): +SyntaxError: Expected one or more names after 'import' + >>> (): int Traceback (most recent call last): SyntaxError: only single target (not tuple) can be annotated diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-19-11-59-57.gh-issue-118082._FLuOT.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-19-11-59-57.gh-issue-118082._FLuOT.rst new file mode 100644 index 000000000000000..7b9a726d7c77c2c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-19-11-59-57.gh-issue-118082._FLuOT.rst @@ -0,0 +1,3 @@ +Improve :exc:`SyntaxError` message for imports without names, like in +``from x import`` and ``import`` cases. It now points +out to users that :keyword:`import` expects at least one name after it. diff --git a/Parser/parser.c b/Parser/parser.c index 35d672b0d397f98..b6683bfd1f1bc01 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -21,28 +21,28 @@ static KeywordToken *reserved_keywords[] = { (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) {{NULL, -1}}, (KeywordToken[]) { - {"if", 661}, - {"as", 659}, - {"in", 672}, + {"if", 662}, + {"as", 660}, + {"in", 673}, {"or", 581}, {"is", 589}, {NULL, -1}, }, (KeywordToken[]) { {"del", 616}, - {"def", 674}, - {"for", 671}, - {"try", 643}, + {"def", 675}, + {"for", 672}, + {"try", 644}, {"and", 582}, - {"not", 678}, + {"not", 679}, {NULL, -1}, }, (KeywordToken[]) { {"from", 621}, {"pass", 504}, - {"with", 634}, - {"elif", 663}, - {"else", 664}, + {"with", 635}, + {"elif", 664}, + {"else", 665}, {"None", 614}, {"True", 613}, {NULL, -1}, @@ -51,24 +51,24 @@ static KeywordToken *reserved_keywords[] = { {"raise", 525}, {"yield", 580}, {"break", 508}, - {"async", 673}, - {"class", 676}, - {"while", 666}, + {"async", 674}, + {"class", 677}, + {"while", 667}, {"False", 615}, {"await", 590}, {NULL, -1}, }, (KeywordToken[]) { {"return", 522}, - {"import", 620}, + {"import", 622}, {"assert", 529}, {"global", 526}, - {"except", 656}, + {"except", 657}, {"lambda", 612}, {NULL, -1}, }, (KeywordToken[]) { - {"finally", 652}, + {"finally", 653}, {NULL, -1}, }, (KeywordToken[]) { @@ -2135,7 +2135,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt")); stmt_ty if_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 661) // token='if' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 662) // token='if' && (if_stmt_var = if_stmt_rule(p)) // if_stmt ) @@ -2219,7 +2219,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt")); stmt_ty try_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 643) // token='try' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 644) // token='try' && (try_stmt_var = try_stmt_rule(p)) // try_stmt ) @@ -2240,7 +2240,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt")); stmt_ty while_stmt_var; if ( - _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 666) // token='while' + _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 667) // token='while' && (while_stmt_var = while_stmt_rule(p)) // while_stmt ) @@ -3514,7 +3514,7 @@ import_name_rule(Parser *p) Token * _keyword; asdl_alias_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='import' + (_keyword = _PyPegen_expect_token(p, 622)) // token='import' && (a = dotted_as_names_rule(p)) // dotted_as_names ) @@ -3589,7 +3589,7 @@ import_from_rule(Parser *p) && (b = dotted_name_rule(p)) // dotted_name && - (_keyword_1 = _PyPegen_expect_token(p, 620)) // token='import' + (_keyword_1 = _PyPegen_expect_token(p, 622)) // token='import' && (c = import_from_targets_rule(p)) // import_from_targets ) @@ -3631,7 +3631,7 @@ import_from_rule(Parser *p) && (a = _loop1_25_rule(p)) // (('.' | '...'))+ && - (_keyword_1 = _PyPegen_expect_token(p, 620)) // token='import' + (_keyword_1 = _PyPegen_expect_token(p, 622)) // token='import' && (b = import_from_targets_rule(p)) // import_from_targets ) @@ -4380,7 +4380,7 @@ class_def_raw_rule(Parser *p) asdl_stmt_seq* c; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 676)) // token='class' + (_keyword = _PyPegen_expect_token(p, 677)) // token='class' && (a = _PyPegen_name_token(p)) // NAME && @@ -4547,7 +4547,7 @@ function_def_raw_rule(Parser *p) void *t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 674)) // token='def' + (_keyword = _PyPegen_expect_token(p, 675)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -4608,9 +4608,9 @@ function_def_raw_rule(Parser *p) void *t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 674)) // token='def' + (_keyword_1 = _PyPegen_expect_token(p, 675)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && @@ -5948,7 +5948,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -5993,7 +5993,7 @@ if_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (a = named_expression_rule(p)) // named_expression && @@ -6088,7 +6088,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; stmt_ty c; if ( - (_keyword = _PyPegen_expect_token(p, 663)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 664)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -6133,7 +6133,7 @@ elif_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 663)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 664)) // token='elif' && (a = named_expression_rule(p)) // named_expression && @@ -6214,7 +6214,7 @@ else_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 664)) // token='else' + (_keyword = _PyPegen_expect_token(p, 665)) // token='else' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6293,7 +6293,7 @@ while_stmt_rule(Parser *p) asdl_stmt_seq* b; void *c; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='while' + (_keyword = _PyPegen_expect_token(p, 667)) // token='while' && (a = named_expression_rule(p)) // named_expression && @@ -6393,11 +6393,11 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword = _PyPegen_expect_token(p, 672)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 673)) // token='in' && (_cut_var = 1) && @@ -6455,13 +6455,13 @@ for_stmt_rule(Parser *p) expr_ty t; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='for' && (t = star_targets_rule(p)) // star_targets && - (_keyword_2 = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword_2 = _PyPegen_expect_token(p, 673)) // token='in' && (_cut_var = 1) && @@ -6590,7 +6590,7 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 634)) // token='with' + (_keyword = _PyPegen_expect_token(p, 635)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -6641,7 +6641,7 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 634)) // token='with' + (_keyword = _PyPegen_expect_token(p, 635)) // token='with' && (a = (asdl_withitem_seq*)_gather_53_rule(p)) // ','.with_item+ && @@ -6690,9 +6690,9 @@ with_stmt_rule(Parser *p) asdl_withitem_seq* a; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='with' + (_keyword_1 = _PyPegen_expect_token(p, 635)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -6742,9 +6742,9 @@ with_stmt_rule(Parser *p) asdl_stmt_seq* b; void *tc; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 634)) // token='with' + (_keyword_1 = _PyPegen_expect_token(p, 635)) // token='with' && (a = (asdl_withitem_seq*)_gather_57_rule(p)) // ','.with_item+ && @@ -6830,7 +6830,7 @@ with_item_rule(Parser *p) if ( (e = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (t = star_target_rule(p)) // star_target && @@ -6955,7 +6955,7 @@ try_stmt_rule(Parser *p) asdl_stmt_seq* b; asdl_stmt_seq* f; if ( - (_keyword = _PyPegen_expect_token(p, 643)) // token='try' + (_keyword = _PyPegen_expect_token(p, 644)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -6999,7 +6999,7 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 643)) // token='try' + (_keyword = _PyPegen_expect_token(p, 644)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7047,7 +7047,7 @@ try_stmt_rule(Parser *p) asdl_excepthandler_seq* ex; void *f; if ( - (_keyword = _PyPegen_expect_token(p, 643)) // token='try' + (_keyword = _PyPegen_expect_token(p, 644)) // token='try' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7145,7 +7145,7 @@ except_block_rule(Parser *p) expr_ty e; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='except' + (_keyword = _PyPegen_expect_token(p, 657)) // token='except' && (e = expression_rule(p)) // expression && @@ -7188,7 +7188,7 @@ except_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* b; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='except' + (_keyword = _PyPegen_expect_token(p, 657)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -7299,7 +7299,7 @@ except_star_block_rule(Parser *p) expr_ty e; void *t; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='except' + (_keyword = _PyPegen_expect_token(p, 657)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -7401,7 +7401,7 @@ finally_block_rule(Parser *p) Token * _literal; asdl_stmt_seq* a; if ( - (_keyword = _PyPegen_expect_token(p, 652)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 653)) // token='finally' && (_literal = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -7709,7 +7709,7 @@ guard_rule(Parser *p) Token * _keyword; expr_ty guard; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (guard = named_expression_rule(p)) // named_expression ) @@ -7904,7 +7904,7 @@ as_pattern_rule(Parser *p) if ( (pattern = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (target = pattern_capture_target_rule(p)) // pattern_capture_target ) @@ -11127,11 +11127,11 @@ expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 664)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 665)) // token='else' && (c = expression_rule(p)) // expression ) @@ -12013,7 +12013,7 @@ inversion_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 678)) // token='not' + (_keyword = _PyPegen_expect_token(p, 679)) // token='not' && (a = inversion_rule(p)) // inversion ) @@ -12667,9 +12667,9 @@ notin_bitwise_or_rule(Parser *p) Token * _keyword_1; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 678)) // token='not' + (_keyword = _PyPegen_expect_token(p, 679)) // token='not' && - (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 673)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -12715,7 +12715,7 @@ in_bitwise_or_rule(Parser *p) Token * _keyword; expr_ty a; if ( - (_keyword = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword = _PyPegen_expect_token(p, 673)) // token='in' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -12764,7 +12764,7 @@ isnot_bitwise_or_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 589)) // token='is' && - (_keyword_1 = _PyPegen_expect_token(p, 678)) // token='not' + (_keyword_1 = _PyPegen_expect_token(p, 679)) // token='not' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -16935,13 +16935,13 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' && - (_keyword_1 = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_2 = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword_2 = _PyPegen_expect_token(p, 673)) // token='in' && (_cut_var = 1) && @@ -16980,11 +16980,11 @@ for_if_clause_rule(Parser *p) expr_ty b; asdl_expr_seq* c; if ( - (_keyword = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword = _PyPegen_expect_token(p, 672)) // token='for' && (a = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 673)) // token='in' && (_cut_var = 1) && @@ -17021,13 +17021,13 @@ for_if_clause_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings void *_tmp_122_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword = _PyPegen_expect_token(p, 672)) // token='for' && (_tmp_122_var = _tmp_122_rule(p)) // bitwise_or ((',' bitwise_or))* ','? && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 672) // token='in' + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 673) // token='in' ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in'")); @@ -20301,11 +20301,11 @@ expression_without_invalid_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (b = disjunction_rule(p)) // disjunction && - (_keyword_1 = _PyPegen_expect_token(p, 664)) // token='else' + (_keyword_1 = _PyPegen_expect_token(p, 665)) // token='else' && (c = expression_rule(p)) // expression ) @@ -20486,7 +20486,7 @@ invalid_expression_rule(Parser *p) if ( (a = disjunction_rule(p)) // disjunction && - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (b = disjunction_rule(p)) // disjunction && @@ -22424,7 +22424,7 @@ invalid_with_item_rule(Parser *p) if ( (expression_var = expression_rule(p)) // expression && - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (a = expression_rule(p)) // expression && @@ -22474,9 +22474,9 @@ invalid_for_target_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings expr_ty a; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword = _PyPegen_expect_token(p, 672)) // token='for' && (a = star_expressions_rule(p)) // star_expressions ) @@ -22582,7 +22582,7 @@ invalid_group_rule(Parser *p) return _res; } -// invalid_import: 'import' ','.dotted_name+ 'from' dotted_name +// invalid_import: 'import' ','.dotted_name+ 'from' dotted_name | 'import' NEWLINE static void * invalid_import_rule(Parser *p) { @@ -22606,7 +22606,7 @@ invalid_import_rule(Parser *p) Token * a; expr_ty dotted_name_var; if ( - (a = _PyPegen_expect_token(p, 620)) // token='import' + (a = _PyPegen_expect_token(p, 622)) // token='import' && (_gather_206_var = _gather_206_rule(p)) // ','.dotted_name+ && @@ -22628,13 +22628,40 @@ invalid_import_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_import[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name")); } + { // 'import' NEWLINE + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_import[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' NEWLINE")); + Token * _keyword; + Token * token; + if ( + (_keyword = _PyPegen_expect_token(p, 622)) // token='import' + && + (token = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + ) + { + 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()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_import[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'import' NEWLINE")); + } _res = NULL; done: p->level--; return _res; } -// invalid_import_from_targets: import_from_as_names ',' NEWLINE +// invalid_import_from_targets: import_from_as_names ',' NEWLINE | NEWLINE static void * invalid_import_from_targets_rule(Parser *p) { @@ -22677,6 +22704,30 @@ invalid_import_from_targets_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_import_from_targets[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "import_from_as_names ',' NEWLINE")); } + { // NEWLINE + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_import_from_targets[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + Token * token; + if ( + (token = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + ) + { + 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()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_import_from_targets[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); + } _res = NULL; done: p->level--; @@ -22706,7 +22757,7 @@ invalid_compound_stmt_rule(Parser *p) Token * a; expr_ty named_expression_var; if ( - (a = _PyPegen_expect_token(p, 663)) // token='elif' + (a = _PyPegen_expect_token(p, 664)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -22735,7 +22786,7 @@ invalid_compound_stmt_rule(Parser *p) Token * _literal; Token * a; if ( - (a = _PyPegen_expect_token(p, 664)) // token='else' + (a = _PyPegen_expect_token(p, 665)) // token='else' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -22786,9 +22837,9 @@ invalid_with_stmt_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 634)) // token='with' + (_keyword = _PyPegen_expect_token(p, 635)) // token='with' && (_gather_208_var = _gather_208_rule(p)) // ','.(expression ['as' star_target])+ && @@ -22824,9 +22875,9 @@ invalid_with_stmt_rule(Parser *p) UNUSED(_opt_var_1); // Silence compiler warnings Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 634)) // token='with' + (_keyword = _PyPegen_expect_token(p, 635)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -22886,9 +22937,9 @@ invalid_with_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 634)) // token='with' + (a = _PyPegen_expect_token(p, 635)) // token='with' && (_gather_212_var = _gather_212_rule(p)) // ','.(expression ['as' star_target])+ && @@ -22929,9 +22980,9 @@ invalid_with_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 634)) // token='with' + (a = _PyPegen_expect_token(p, 635)) // token='with' && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && @@ -22994,7 +23045,7 @@ invalid_try_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 643)) // token='try' + (a = _PyPegen_expect_token(p, 644)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23026,7 +23077,7 @@ invalid_try_stmt_rule(Parser *p) Token * _literal; asdl_stmt_seq* block_var; if ( - (_keyword = _PyPegen_expect_token(p, 643)) // token='try' + (_keyword = _PyPegen_expect_token(p, 644)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23065,7 +23116,7 @@ invalid_try_stmt_rule(Parser *p) Token * b; expr_ty expression_var; if ( - (_keyword = _PyPegen_expect_token(p, 643)) // token='try' + (_keyword = _PyPegen_expect_token(p, 644)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23073,7 +23124,7 @@ invalid_try_stmt_rule(Parser *p) && (_loop1_218_var = _loop1_218_rule(p)) // except_block+ && - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (b = _PyPegen_expect_token(p, 16)) // token='*' && @@ -23112,7 +23163,7 @@ invalid_try_stmt_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings Token * a; if ( - (_keyword = _PyPegen_expect_token(p, 643)) // token='try' + (_keyword = _PyPegen_expect_token(p, 644)) // token='try' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23120,7 +23171,7 @@ invalid_try_stmt_rule(Parser *p) && (_loop1_221_var = _loop1_221_rule(p)) // except_star_block+ && - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (_opt_var = _tmp_222_rule(p), !p->error_indicator) // [expression ['as' NAME]] && @@ -23179,7 +23230,7 @@ invalid_except_stmt_rule(Parser *p) expr_ty a; expr_ty expressions_var; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='except' + (_keyword = _PyPegen_expect_token(p, 657)) // token='except' && (_opt_var = _PyPegen_expect_token(p, 16), !p->error_indicator) // '*'? && @@ -23221,7 +23272,7 @@ invalid_except_stmt_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (_opt_var = _PyPegen_expect_token(p, 16), !p->error_indicator) // '*'? && @@ -23254,7 +23305,7 @@ invalid_except_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -23282,7 +23333,7 @@ invalid_except_stmt_rule(Parser *p) void *_tmp_225_var; Token * a; if ( - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -23331,7 +23382,7 @@ invalid_finally_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 652)) // token='finally' + (a = _PyPegen_expect_token(p, 653)) // token='finally' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23387,7 +23438,7 @@ invalid_except_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (expression_var = expression_rule(p)) // expression && @@ -23423,7 +23474,7 @@ invalid_except_stmt_indent_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23479,7 +23530,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) expr_ty expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 656)) // token='except' + (a = _PyPegen_expect_token(p, 657)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && @@ -23718,7 +23769,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (a = _PyPegen_expect_soft_keyword(p, "_")) // soft_keyword='"_"' ) @@ -23748,7 +23799,7 @@ invalid_as_pattern_rule(Parser *p) if ( (or_pattern_var = or_pattern_rule(p)) // or_pattern && - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && _PyPegen_lookahead_with_name(0, _PyPegen_name_token, p) && @@ -23902,7 +23953,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -23933,7 +23984,7 @@ invalid_if_stmt_rule(Parser *p) expr_ty a_1; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 661)) // token='if' + (a = _PyPegen_expect_token(p, 662)) // token='if' && (a_1 = named_expression_rule(p)) // named_expression && @@ -23988,7 +24039,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 663)) // token='elif' + (_keyword = _PyPegen_expect_token(p, 664)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24019,7 +24070,7 @@ invalid_elif_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 663)) // token='elif' + (a = _PyPegen_expect_token(p, 664)) // token='elif' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24072,7 +24123,7 @@ invalid_else_stmt_rule(Parser *p) Token * a; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 664)) // token='else' + (a = _PyPegen_expect_token(p, 665)) // token='else' && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24125,7 +24176,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='while' + (_keyword = _PyPegen_expect_token(p, 667)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24156,7 +24207,7 @@ invalid_while_stmt_rule(Parser *p) expr_ty named_expression_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 666)) // token='while' + (a = _PyPegen_expect_token(p, 667)) // token='while' && (named_expression_var = named_expression_rule(p)) // named_expression && @@ -24215,13 +24266,13 @@ invalid_for_stmt_rule(Parser *p) expr_ty star_expressions_var; expr_ty star_targets_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (_keyword = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword = _PyPegen_expect_token(p, 672)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword_1 = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword_1 = _PyPegen_expect_token(p, 673)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -24256,13 +24307,13 @@ invalid_for_stmt_rule(Parser *p) expr_ty star_expressions_var; expr_ty star_targets_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 671)) // token='for' + (a = _PyPegen_expect_token(p, 672)) // token='for' && (star_targets_var = star_targets_rule(p)) // star_targets && - (_keyword = _PyPegen_expect_token(p, 672)) // token='in' + (_keyword = _PyPegen_expect_token(p, 673)) // token='in' && (star_expressions_var = star_expressions_rule(p)) // star_expressions && @@ -24327,9 +24378,9 @@ invalid_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (_opt_var = _PyPegen_expect_token(p, 673), !p->error_indicator) // 'async'? + (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && - (a = _PyPegen_expect_token(p, 674)) // token='def' + (a = _PyPegen_expect_token(p, 675)) // token='def' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -24398,7 +24449,7 @@ invalid_class_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (_keyword = _PyPegen_expect_token(p, 676)) // token='class' + (_keyword = _PyPegen_expect_token(p, 677)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -24437,7 +24488,7 @@ invalid_class_def_raw_rule(Parser *p) expr_ty name_var; Token * newline_var; if ( - (a = _PyPegen_expect_token(p, 676)) // token='class' + (a = _PyPegen_expect_token(p, 677)) // token='class' && (name_var = _PyPegen_name_token(p)) // NAME && @@ -25212,7 +25263,7 @@ invalid_arithmetic_rule(Parser *p) && (_tmp_251_var = _tmp_251_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' && - (a = _PyPegen_expect_token(p, 678)) // token='not' + (a = _PyPegen_expect_token(p, 679)) // token='not' && (b = inversion_rule(p)) // inversion ) @@ -25261,7 +25312,7 @@ invalid_factor_rule(Parser *p) if ( (_tmp_252_var = _tmp_252_rule(p)) // '+' | '-' | '~' && - (a = _PyPegen_expect_token(p, 678)) // token='not' + (a = _PyPegen_expect_token(p, 679)) // token='not' && (b = factor_rule(p)) // factor ) @@ -25629,7 +25680,7 @@ _tmp_6_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 620)) // token='import' + (_keyword = _PyPegen_expect_token(p, 622)) // token='import' ) { D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import'")); @@ -25686,7 +25737,7 @@ _tmp_7_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 674)) // token='def' + (_keyword = _PyPegen_expect_token(p, 675)) // token='def' ) { D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); @@ -25724,7 +25775,7 @@ _tmp_7_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' ) { D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); @@ -25762,7 +25813,7 @@ _tmp_8_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 676)) // token='class' + (_keyword = _PyPegen_expect_token(p, 677)) // token='class' ) { D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); @@ -25819,7 +25870,7 @@ _tmp_9_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 634)) // token='with' + (_keyword = _PyPegen_expect_token(p, 635)) // token='with' ) { D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); @@ -25838,7 +25889,7 @@ _tmp_9_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' ) { D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); @@ -25876,7 +25927,7 @@ _tmp_10_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 671)) // token='for' + (_keyword = _PyPegen_expect_token(p, 672)) // token='for' ) { D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); @@ -25895,7 +25946,7 @@ _tmp_10_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 673)) // token='async' + (_keyword = _PyPegen_expect_token(p, 674)) // token='async' ) { D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); @@ -26919,7 +26970,7 @@ _tmp_28_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -27082,7 +27133,7 @@ _tmp_31_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -29069,7 +29120,7 @@ _tmp_62_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -29115,7 +29166,7 @@ _tmp_63_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (z = _PyPegen_name_token(p)) // NAME ) @@ -35059,7 +35110,7 @@ _tmp_160_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 664)) // token='else' + (_keyword = _PyPegen_expect_token(p, 665)) // token='else' ) { D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); @@ -38652,7 +38703,7 @@ _tmp_216_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 656)) // token='except' + (_keyword = _PyPegen_expect_token(p, 657)) // token='except' ) { D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); @@ -38671,7 +38722,7 @@ _tmp_216_rule(Parser *p) D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 652)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 653)) // token='finally' ) { D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); @@ -38849,7 +38900,7 @@ _tmp_219_rule(Parser *p) Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) @@ -39071,7 +39122,7 @@ _tmp_223_rule(Parser *p) Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) @@ -39112,7 +39163,7 @@ _tmp_224_rule(Parser *p) Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) @@ -39210,7 +39261,7 @@ _tmp_226_rule(Parser *p) Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) @@ -39251,7 +39302,7 @@ _tmp_227_rule(Parser *p) Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) @@ -41304,7 +41355,7 @@ _tmp_263_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (z = disjunction_rule(p)) // disjunction ) @@ -41350,7 +41401,7 @@ _tmp_264_rule(Parser *p) Token * _keyword; expr_ty z; if ( - (_keyword = _PyPegen_expect_token(p, 661)) // token='if' + (_keyword = _PyPegen_expect_token(p, 662)) // token='if' && (z = disjunction_rule(p)) // disjunction ) @@ -42063,7 +42114,7 @@ _tmp_279_rule(Parser *p) Token * _keyword; expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (name_var = _PyPegen_name_token(p)) // NAME ) @@ -42322,7 +42373,7 @@ _tmp_284_rule(Parser *p) Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) @@ -42363,7 +42414,7 @@ _tmp_285_rule(Parser *p) Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) @@ -42404,7 +42455,7 @@ _tmp_286_rule(Parser *p) Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) @@ -42445,7 +42496,7 @@ _tmp_287_rule(Parser *p) Token * _keyword; expr_ty star_target_var; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='as' + (_keyword = _PyPegen_expect_token(p, 660)) // token='as' && (star_target_var = star_target_rule(p)) // star_target ) From d687d3fcfaa13b173005897634fc5ab515c8a660 Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Tue, 23 Apr 2024 15:36:06 +0300 Subject: [PATCH 099/127] gh-118140: Make the``test_concurrent_futures.test_init`` quiet. (GH-118141) Add stream argument to unittest.TextTestRunner call --- Lib/test/test_concurrent_futures/test_init.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_concurrent_futures/test_init.py b/Lib/test/test_concurrent_futures/test_init.py index 113a4d1c54be03b..a36f592b79b7cfd 100644 --- a/Lib/test/test_concurrent_futures/test_init.py +++ b/Lib/test/test_concurrent_futures/test_init.py @@ -4,6 +4,7 @@ import time import unittest import sys +import io from concurrent.futures._base import BrokenExecutor from concurrent.futures.process import _check_system_limits @@ -124,7 +125,7 @@ def _test(self, test_class): except NotImplementedError: self.skipTest("ProcessPoolExecutor unavailable on this system") - runner = unittest.TextTestRunner() + runner = unittest.TextTestRunner(stream=io.StringIO()) runner.run(test_class('test_initializer')) # GH-104090: From d0b664ee065e69fc4f1506b00391e093d2d6638d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Tue, 23 Apr 2024 06:40:26 -0700 Subject: [PATCH 100/127] gh-118168: Fix Unpack interaction with builtin aliases (#118169) Co-authored-by: Alex Waygood --- Lib/test/test_typing.py | 32 +++++++++++++++++++ Lib/typing.py | 5 +-- ...-04-22-20-42-29.gh-issue-118168.Igni7h.rst | 4 +++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-22-20-42-29.gh-issue-118168.Igni7h.rst diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 58781e52aca6d83..703fe84f3aad107 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -978,6 +978,38 @@ def foo(**kwargs: Unpack[Movie]): ... self.assertEqual(repr(foo.__annotations__['kwargs']), f"typing.Unpack[{__name__}.Movie]") + def test_builtin_tuple(self): + Ts = TypeVarTuple("Ts") + + class Old(Generic[*Ts]): ... + class New[*Ts]: ... + + PartOld = Old[int, *Ts] + self.assertEqual(PartOld[str].__args__, (int, str)) + self.assertEqual(PartOld[*tuple[str]].__args__, (int, str)) + self.assertEqual(PartOld[*Tuple[str]].__args__, (int, str)) + self.assertEqual(PartOld[Unpack[tuple[str]]].__args__, (int, str)) + self.assertEqual(PartOld[Unpack[Tuple[str]]].__args__, (int, str)) + + PartNew = New[int, *Ts] + self.assertEqual(PartNew[str].__args__, (int, str)) + self.assertEqual(PartNew[*tuple[str]].__args__, (int, str)) + self.assertEqual(PartNew[*Tuple[str]].__args__, (int, str)) + self.assertEqual(PartNew[Unpack[tuple[str]]].__args__, (int, str)) + self.assertEqual(PartNew[Unpack[Tuple[str]]].__args__, (int, str)) + + def test_unpack_wrong_type(self): + Ts = TypeVarTuple("Ts") + class Gen[*Ts]: ... + PartGen = Gen[int, *Ts] + + bad_unpack_param = re.escape("Unpack[...] must be used with a tuple type") + with self.assertRaisesRegex(TypeError, bad_unpack_param): + PartGen[Unpack[list[int]]] + with self.assertRaisesRegex(TypeError, bad_unpack_param): + PartGen[Unpack[List[int]]] + + class TypeVarTupleTests(BaseTestCase): def assertEndsWith(self, string, tail): diff --git a/Lib/typing.py b/Lib/typing.py index a0b68f593ca0d91..b3f4ba99f9ec219 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1786,8 +1786,9 @@ def __typing_unpacked_tuple_args__(self): assert self.__origin__ is Unpack assert len(self.__args__) == 1 arg, = self.__args__ - if isinstance(arg, _GenericAlias): - assert arg.__origin__ is tuple + if isinstance(arg, (_GenericAlias, types.GenericAlias)): + if arg.__origin__ is not tuple: + raise TypeError("Unpack[...] must be used with a tuple type") return arg.__args__ return None diff --git a/Misc/NEWS.d/next/Library/2024-04-22-20-42-29.gh-issue-118168.Igni7h.rst b/Misc/NEWS.d/next/Library/2024-04-22-20-42-29.gh-issue-118168.Igni7h.rst new file mode 100644 index 000000000000000..78c3e0fe17979ad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-22-20-42-29.gh-issue-118168.Igni7h.rst @@ -0,0 +1,4 @@ +Fix incorrect argument substitution when :data:`typing.Unpack` is used with +the builtin :class:`tuple`. :data:`!typing.Unpack` now raises +:exc:`TypeError` when used with certain invalid types. Patch by Jelle +Zijlstra. From 23950beff84c39d50f48011e930f4c6ebf32fc73 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 23 Apr 2024 08:25:50 -0600 Subject: [PATCH 101/127] gh-117953: Small Cleanup of Extensions-Related Machinery Code (gh-118167) This is a collection of very basic cleanups I've pulled out of gh-118116. It is mostly renaming variables and moving a couple bits of code in functionally equivalent ways. --- Include/internal/pycore_import.h | 1 + Python/import.c | 134 ++++++++++++++++++++----------- Python/importdl.c | 45 +++++------ 3 files changed, 105 insertions(+), 75 deletions(-) diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h index eb8a9a0db46c221..08af53258cde977 100644 --- a/Include/internal/pycore_import.h +++ b/Include/internal/pycore_import.h @@ -22,6 +22,7 @@ extern int _PyImport_SetModuleString(const char *name, PyObject* module); extern void _PyImport_AcquireLock(PyInterpreterState *interp); extern int _PyImport_ReleaseLock(PyInterpreterState *interp); +// This is used exclusively for the sys and builtins modules: extern int _PyImport_FixupBuiltin( PyObject *mod, const char *name, /* UTF-8 encoded string */ diff --git a/Python/import.c b/Python/import.c index b040c7d5c0f7f5e..8cdc04f03dd201b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1125,10 +1125,10 @@ _PyImport_CheckSubinterpIncompatibleExtensionAllowed(const char *name) static PyObject * get_core_module_dict(PyInterpreterState *interp, - PyObject *name, PyObject *filename) + PyObject *name, PyObject *path) { /* Only builtin modules are core. */ - if (filename == name) { + if (path == name) { assert(!PyErr_Occurred()); if (PyUnicode_CompareWithASCIIString(name, "sys") == 0) { return interp->sysdict_copy; @@ -1143,11 +1143,11 @@ get_core_module_dict(PyInterpreterState *interp, } static inline int -is_core_module(PyInterpreterState *interp, PyObject *name, PyObject *filename) +is_core_module(PyInterpreterState *interp, PyObject *name, PyObject *path) { /* This might be called before the core dict copies are in place, so we can't rely on get_core_module_dict() here. */ - if (filename == name) { + if (path == name) { if (PyUnicode_CompareWithASCIIString(name, "sys") == 0) { return 1; } @@ -1159,7 +1159,7 @@ is_core_module(PyInterpreterState *interp, PyObject *name, PyObject *filename) } static int -fix_up_extension(PyObject *mod, PyObject *name, PyObject *filename) +fix_up_extension(PyObject *mod, PyObject *name, PyObject *path) { if (mod == NULL || !PyModule_Check(mod)) { PyErr_BadInternalCall(); @@ -1180,7 +1180,7 @@ fix_up_extension(PyObject *mod, PyObject *name, PyObject *filename) // bpo-44050: Extensions and def->m_base.m_copy can be updated // when the extension module doesn't support sub-interpreters. if (def->m_size == -1) { - if (!is_core_module(tstate->interp, name, filename)) { + if (!is_core_module(tstate->interp, name, path)) { assert(PyUnicode_CompareWithASCIIString(name, "sys") != 0); assert(PyUnicode_CompareWithASCIIString(name, "builtins") != 0); if (def->m_base.m_copy) { @@ -1202,7 +1202,7 @@ fix_up_extension(PyObject *mod, PyObject *name, PyObject *filename) // XXX Why special-case the main interpreter? if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) { - if (_extensions_cache_set(filename, name, def) < 0) { + if (_extensions_cache_set(path, name, def) < 0) { return -1; } } @@ -1227,10 +1227,10 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, static PyObject * import_find_extension(PyThreadState *tstate, PyObject *name, - PyObject *filename) + PyObject *path) { /* Only single-phase init modules will be in the cache. */ - PyModuleDef *def = _extensions_cache_get(filename, name); + PyModuleDef *def = _extensions_cache_get(path, name); if (def == NULL) { return NULL; } @@ -1253,7 +1253,7 @@ import_find_extension(PyThreadState *tstate, PyObject *name, if (m_copy == NULL) { /* It might be a core module (e.g. sys & builtins), for which we don't set m_copy. */ - m_copy = get_core_module_dict(tstate->interp, name, filename); + m_copy = get_core_module_dict(tstate->interp, name, path); if (m_copy == NULL) { return NULL; } @@ -1292,16 +1292,16 @@ import_find_extension(PyThreadState *tstate, PyObject *name, int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose; if (verbose) { PySys_FormatStderr("import %U # previously loaded (%R)\n", - name, filename); + name, path); } return mod; } static int clear_singlephase_extension(PyInterpreterState *interp, - PyObject *name, PyObject *filename) + PyObject *name, PyObject *path) { - PyModuleDef *def = _extensions_cache_get(filename, name); + PyModuleDef *def = _extensions_cache_get(path, name); if (def == NULL) { if (PyErr_Occurred()) { return -1; @@ -1322,7 +1322,7 @@ clear_singlephase_extension(PyInterpreterState *interp, } /* Clear the cached module def. */ - _extensions_cache_delete(filename, name); + _extensions_cache_delete(path, name); return 0; } @@ -1336,11 +1336,20 @@ int _PyImport_FixupBuiltin(PyObject *mod, const char *name, PyObject *modules) { int res = -1; + assert(mod != NULL && PyModule_Check(mod)); + PyObject *nameobj; nameobj = PyUnicode_InternFromString(name); if (nameobj == NULL) { return -1; } + + PyModuleDef *def = PyModule_GetDef(mod); + if (def == NULL) { + PyErr_BadInternalCall(); + goto finally; + } + if (PyObject_SetItem(modules, nameobj, mod) < 0) { goto finally; } @@ -1348,6 +1357,7 @@ _PyImport_FixupBuiltin(PyObject *mod, const char *name, PyObject *modules) PyMapping_DelItem(modules, nameobj); goto finally; } + res = 0; finally: @@ -1382,39 +1392,45 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) } PyObject *modules = MODULES(tstate->interp); + struct _inittab *found = NULL; for (struct _inittab *p = INITTAB; p->name != NULL; p++) { if (_PyUnicode_EqualToASCIIString(name, p->name)) { - if (p->initfunc == NULL) { - /* Cannot re-init internal module ("sys" or "builtins") */ - return import_add_module(tstate, name); - } - mod = (*p->initfunc)(); - if (mod == NULL) { - return NULL; - } + found = p; + } + } + if (found == NULL) { + // not found + Py_RETURN_NONE; + } - if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) { - return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec); - } - else { - /* Remember pointer to module init function. */ - PyModuleDef *def = PyModule_GetDef(mod); - if (def == NULL) { - return NULL; - } + PyModInitFunction p0 = (PyModInitFunction)found->initfunc; + if (p0 == NULL) { + /* Cannot re-init internal module ("sys" or "builtins") */ + assert(is_core_module(tstate->interp, name, name)); + return import_add_module(tstate, name); + } - def->m_base.m_init = p->initfunc; - if (_PyImport_FixupExtensionObject(mod, name, name, - modules) < 0) { - return NULL; - } - return mod; - } - } + mod = p0(); + if (mod == NULL) { + return NULL; } - // not found - Py_RETURN_NONE; + if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) { + return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec); + } + else { + /* Remember pointer to module init function. */ + PyModuleDef *def = PyModule_GetDef(mod); + if (def == NULL) { + return NULL; + } + + def->m_base.m_init = p0; + if (_PyImport_FixupExtensionObject(mod, name, name, modules) < 0) { + return NULL; + } + return mod; + } } @@ -3724,7 +3740,7 @@ static PyObject * _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) /*[clinic end generated code: output=83249b827a4fde77 input=c31b954f4cf4e09d]*/ { - PyObject *mod, *name, *path; + PyObject *mod, *name, *filename; FILE *fp; name = PyObject_GetAttrString(spec, "name"); @@ -3732,36 +3748,56 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) return NULL; } - path = PyObject_GetAttrString(spec, "origin"); - if (path == NULL) { + filename = PyObject_GetAttrString(spec, "origin"); + if (filename == NULL) { Py_DECREF(name); return NULL; } PyThreadState *tstate = _PyThreadState_GET(); - mod = import_find_extension(tstate, name, path); + mod = import_find_extension(tstate, name, filename); if (mod != NULL || _PyErr_Occurred(tstate)) { assert(mod == NULL || !_PyErr_Occurred(tstate)); goto finally; } + if (PySys_Audit("import", "OOOOO", name, filename, + Py_None, Py_None, Py_None) < 0) + { + goto finally; + } + + /* Is multi-phase init or this is the first time being loaded. */ + + /* We would move this (and the fclose() below) into + * _PyImport_GetModInitFunc(), but it isn't clear if the intervening + * code relies on fp still being open. */ if (file != NULL) { - fp = _Py_fopen_obj(path, "r"); + fp = _Py_fopen_obj(filename, "r"); if (fp == NULL) { goto finally; } } - else + else { fp = NULL; + } mod = _PyImport_LoadDynamicModuleWithSpec(spec, fp); + if (mod != NULL) { + /* Remember the filename as the __file__ attribute */ + if (PyModule_AddObjectRef(mod, "__file__", filename) < 0) { + PyErr_Clear(); /* Not important enough to report */ + } + } - if (fp) + // XXX Shouldn't this happen in the error cases too. + if (fp) { fclose(fp); + } finally: Py_DECREF(name); - Py_DECREF(path); + Py_DECREF(filename); return mod; } diff --git a/Python/importdl.c b/Python/importdl.c index 7dfd301d77efb49..7cf30bea3a861ab 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -97,9 +97,10 @@ PyObject * _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) { #ifndef MS_WINDOWS - PyObject *pathbytes = NULL; + PyObject *filename_bytes = NULL; + const char *filename_buf; #endif - PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL; + PyObject *name_unicode = NULL, *name = NULL, *filename = NULL, *m = NULL; const char *name_buf, *hook_prefix; const char *oldcontext, *newcontext; dl_funcptr exportfunc; @@ -126,26 +127,23 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) } name_buf = PyBytes_AS_STRING(name); - path = PyObject_GetAttrString(spec, "origin"); - if (path == NULL) - goto error; - - if (PySys_Audit("import", "OOOOO", name_unicode, path, - Py_None, Py_None, Py_None) < 0) { + filename = PyObject_GetAttrString(spec, "origin"); + if (filename == NULL) { goto error; } #ifdef MS_WINDOWS - exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf, - path, fp); + exportfunc = _PyImport_FindSharedFuncptrWindows( + hook_prefix, name_buf, filename, fp); #else - pathbytes = PyUnicode_EncodeFSDefault(path); - if (pathbytes == NULL) + filename_bytes = PyUnicode_EncodeFSDefault(filename); + if (filename_bytes == NULL) { goto error; - exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf, - PyBytes_AS_STRING(pathbytes), - fp); - Py_DECREF(pathbytes); + } + filename_buf = PyBytes_AS_STRING(filename_bytes); + exportfunc = _PyImport_FindSharedFuncptr( + hook_prefix, name_buf, filename_buf, fp); + Py_DECREF(filename_bytes); #endif if (exportfunc == NULL) { @@ -157,7 +155,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) hook_prefix, name_buf); if (msg == NULL) goto error; - PyErr_SetImportError(msg, name_unicode, path); + PyErr_SetImportError(msg, name_unicode, filename); Py_DECREF(msg); } goto error; @@ -199,7 +197,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { Py_DECREF(name_unicode); Py_DECREF(name); - Py_DECREF(path); + Py_DECREF(filename); return PyModule_FromDefAndSpec((PyModuleDef*)m, spec); } @@ -228,25 +226,20 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) } def->m_base.m_init = p0; - /* Remember the filename as the __file__ attribute */ - if (PyModule_AddObjectRef(m, "__file__", path) < 0) { - PyErr_Clear(); /* Not important enough to report */ - } - PyObject *modules = PyImport_GetModuleDict(); - if (_PyImport_FixupExtensionObject(m, name_unicode, path, modules) < 0) + if (_PyImport_FixupExtensionObject(m, name_unicode, filename, modules) < 0) goto error; Py_DECREF(name_unicode); Py_DECREF(name); - Py_DECREF(path); + Py_DECREF(filename); return m; error: Py_DECREF(name_unicode); Py_XDECREF(name); - Py_XDECREF(path); + Py_XDECREF(filename); Py_XDECREF(m); return NULL; } From 8fa124868519eeda0a6dfe9191ceabd708d84fa7 Mon Sep 17 00:00:00 2001 From: morotti Date: Tue, 23 Apr 2024 16:51:20 +0100 Subject: [PATCH 102/127] gh-117151: optimize BufferedWriter(), do not buffer writes that are the buffer size (GH-118037) BufferedWriter() was buffering calls that are the exact same size as the buffer. it's a very common case to read/write in blocks of the exact buffer size. it's pointless to copy a full buffer, it's costing extra memory copy and the full buffer will have to be written in the next call anyway. Co-authored-by: rmorotti --- Modules/_io/bufferedio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 4133d3438253dd5..aa52711941d374a 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2092,7 +2092,7 @@ _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer) self->raw_pos = 0; } avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t); - if (buffer->len <= avail) { + if (buffer->len <= avail && buffer->len < self->buffer_size) { memcpy(self->buffer + self->pos, buffer->buf, buffer->len); if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) { self->write_pos = self->pos; @@ -2161,7 +2161,7 @@ _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer) /* Then write buf itself. At this point the buffer has been emptied. */ remaining = buffer->len; written = 0; - while (remaining > self->buffer_size) { + while (remaining >= self->buffer_size) { Py_ssize_t n = _bufferedwriter_raw_write( self, (char *) buffer->buf + written, buffer->len - written); if (n == -1) { From 0d221e9a1952949465df4e737e8d3189bdd9632a Mon Sep 17 00:00:00 2001 From: Animesh Kumar Date: Tue, 23 Apr 2024 22:42:49 +0530 Subject: [PATCH 103/127] Fix typo in py_compile.rst (GH-118102) --- Doc/library/py_compile.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/py_compile.rst b/Doc/library/py_compile.rst index 38c416f9ad03051..a35fa0ba3f7bded 100644 --- a/Doc/library/py_compile.rst +++ b/Doc/library/py_compile.rst @@ -96,7 +96,7 @@ byte-code cache files in the directory containing the source code. .. class:: PycInvalidationMode - A enumeration of possible methods the interpreter can use to determine + An enumeration of possible methods the interpreter can use to determine whether a bytecode file is up to date with a source file. The ``.pyc`` file indicates the desired invalidation mode in its header. See :ref:`pyc-invalidation` for more information on how Python invalidates From 2e7771a03d8975ee8a9918ce754c665508c3f682 Mon Sep 17 00:00:00 2001 From: mpage Date: Tue, 23 Apr 2024 10:20:14 -0700 Subject: [PATCH 104/127] gh-117657: Quiet TSAN warnings about remaining non-atomic accesses of `tstate->state` (#118165) Quiet TSAN warnings about remaining non-atomic accesses of `tstate->state` --- Python/parking_lot.c | 3 ++- Python/pystate.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/parking_lot.c b/Python/parking_lot.c index d5877fef56e4d02..b368b500ccdfdb1 100644 --- a/Python/parking_lot.c +++ b/Python/parking_lot.c @@ -194,7 +194,8 @@ _PySemaphore_Wait(_PySemaphore *sema, PyTime_t timeout, int detach) PyThreadState *tstate = NULL; if (detach) { tstate = _PyThreadState_GET(); - if (tstate && tstate->state == _Py_THREAD_ATTACHED) { + if (tstate && _Py_atomic_load_int_relaxed(&tstate->state) == + _Py_THREAD_ATTACHED) { // Only detach if we are attached PyEval_ReleaseThread(tstate); } diff --git a/Python/pystate.c b/Python/pystate.c index 06806bd75fbcb27..bca28cebcc9059e 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2096,7 +2096,7 @@ _PyThreadState_Suspend(PyThreadState *tstate) { _PyRuntimeState *runtime = &_PyRuntime; - assert(tstate->state == _Py_THREAD_ATTACHED); + assert(_Py_atomic_load_int_relaxed(&tstate->state) == _Py_THREAD_ATTACHED); struct _stoptheworld_state *stw = NULL; HEAD_LOCK(runtime); From 258408239a4fe8a14919d81b73a16e2cfa374050 Mon Sep 17 00:00:00 2001 From: Oleg Iarygin Date: Tue, 23 Apr 2024 20:38:33 +0300 Subject: [PATCH 105/127] gh-118189: Revert accidentally added incl.tar (#118190) --- Include/incl.tar | Bin 1864192 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Include/incl.tar diff --git a/Include/incl.tar b/Include/incl.tar deleted file mode 100644 index fecc1fb5dec534148d40b4a4c3f1bcfce411a832..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1864192 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%0DN$)T@_T(Wn2(qM_vfI#uE# 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
UW98&SdxSMC!PoVY5J#99u=5s5?@ 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%0AK?J9w$I*mRT%S zt`W7OZ}|!M2OZ4cXxK^qZ|Q_EOW_yuksQEg^Z(_gCr_4$|BUfJs{i)o!-tRm@c;TP zNT7}XTgsf5WQyNjo#p_h{8v?r$rBW0#e1vwFp($E&QPif&MG&HwQ_ZPxBHRH#UG!AV}DXOR@6>QJaeR)yc;y_MdsM9KrqrfW2J7zwEw+Ix|k5qFi7%1^-cP`RPQYsdp@sw;)E^a}YaN$>@JM4DXd z$+F?=pZQkF30JAGH}LlTukKnUYv+w_ZLm%#i1oMWe#s$)S!zy@w}F{Vi*z<&f7kOQ zU^Ac*h0XZ=7N?h$#$~K(E=yx0`CT`M`#I=eo{T3vg9M98lHD(s_3DA2_peV8-32ax zW@0wEgJ^ckSY$(^TL1=8%8sfi**i=b*|_H2GvXTMI~VxfU^8p)~jk&nh5Q0olx{XZeXMzR|t}<6)} zIv3Yta&kW6*AUO+Fjbe?^R4~Wvizj1loDmx>8LN+7E-rt6Fo^qMW_ny(0f-NN~(W= z0YTnkUlsSh4jFBp-jfR2yiEXD2->lm+_xs;K8-_L4G;;rdR503uG~#8A0g0_vD#L| zYdYYgfesWK4OHX=TG~3TW}Q3iz!0v3%%=bN%xv{mERq$;D_FC`;ZxxB@)IcFJdlWp zi*CKq71r7b+7wEvnO|dZZH{xLj%7Yt^t!1|SJ)V*_aB#o|6FuN@}>DXY;_L}1Gcjz zbEeDA+RhBl69#ewYT?EpSDa;z$PlRG@0e`;df9(F<10^2|N2Yh!lO(4&_vMbEHs(! zoY5Hk)>78H&QFY-x{8RNW2HiQQ}eH6s}xfrrr~D~J`&8tQXmND@**W^UyR;ol{rdG zGk}GNVqN$G#qA8XQtw}Se_xEa2WoZmlBmu4Yv-aE-y7fhqvnJ!AZW*cpG^$D*yiMG zHv$CY@^ftbezwQS_a>gk`Qn?WY^)2+^NaBi*N`Bx&Tgc}?MmXxIC{c?tMN=Hb0zm< zimnabW=BKLB9VocN|S@1m1u}RZ8KMhCqs}tP_x65#tA7hb?6fucR)?*U*RVGR9+c+ z@_)|)Gm^&yg3pG~J(JKDnG5<)1Jc|rcW^zYCGc727OU7ocvR8v5;GBymtl7Xg0&`M&4 z)_{m&y6fs#rwRMipHxk!!Mj7!k|SZ7f;ZTTOuXPH3+anpYI+#tE!;T8195sHoOMzo zvzTiX5+ihDq2LK(Jt*(#pJFerpvjL?;S}!@cvagZ8iIrq|>CiE)P< z-Xum<(*#k7>%(^9rSThcFfpmBZHDNl=YBvq@JhCEiAj$>5l9ru(mP!u&4UGFMt39+ z1Lx@F1Qcio?X28BDdLkDTn*f6;cYv%t8&Yd|I)JKBc?o5@;?1PUL@fO=l`)dqnfTU zf4#qGSZ{v4hGB<e_N6FdttwuXC-gOdBh?k?x<8c!OQrZLe97k6K$Y~CATBP@Xm{s zz158kdoD^GLbOww=IY$XYsQ@@{OsTkf}&;6LB7P@(hU3ahg|+LJ|vqGFEH+baJRRQ z(m%a;-Tw%qpqTjeql^!S!(Tnh(eQ+8=GWrILY{v0D0uG-E`RkXSHr8*JMFaToXIU5 zVrxWa!%LN*u&YkV{>BRA(o-0Ecap@tC<*MvJZeLfn&=Tv>;W7|Ctf_I(_X-hoJm55 zSiSQubl4aypy=Za7BDq+Fsta)emojrNpeSTh9;-ui*n4=7kc;M#&7!<3jKJ`!J22+ zlZX2*kTdwGMq2igs-OPc6p2qtrLNaovF%UReH?S!CVZg=o@6IENESKr(P7Ft+6Mr2 z`42(VuLbI#5>=Lj^!MDq@HPs31|IGP_MDmDLgjF-*)(btq`W+@Z(V3qytN&a?6-Ka z%3Je*hhXgrc7nb0NOwPL9LA5hijTF1jDI+{2v-tDuQvnUS$In*_|&|pT|&z5nFvKL z=u{mU`@qt;sczAkVLAT$%8Kcs^w@*-^OPg9b97jiNt()psf?DSfDCd}=)qzO+l`Te`MnAHDpOMXn}UsgEV|LgISM-%lQpFI3S|MT0BMyBXV z{=GAuf2)uG1YTcxb;p18G$DiH-o=eFpOh!~FS-v{5D48B%nb$Qb5b|&l~S&L+g@}N zF|pJz47pCe%009cIj^q{jTDP9ND!|R0%*oGHhbvuqNyFjzdV$lsdW1>ynB8rq#C0p zIM5T~?Iq4#Um1`gj z@Pw5aSc;WtK%^eQKEg#Ce0_+=mT{Q)`4bE^{favI+llBo#5w7?ur+v#ySx*xymR6K zwe&t_Qr1vv8G}=CYj8vMwk+Vs%9f)PP^JW~C_^c_*lTli^W+~2tR5cU$j)CKGRT18 z$&v?=nGP?|u}dj##`2#CZ-?~G4U{_29IOaq{$Xom9%g!;rD*;TsM$Zk&0TtGX$`}S zvQ%k44MhyTHJJ!wDjla4#wr41CtR#C?}E&L?gCU{MV*YN1v9#ed3uCyZat@k+0Dbg zZ;X}L_$YVgXUAb!mSl|m0c?4tNUb2W#t9(Q3ya^{x%nAK&R@cCs`==i9rUxzFFJ)s z1LZn_Q4zwLjJ-;Fcz%3JjIX>ci`CCRf3UPzz)Hvr#;zLbjt15qL=Mk2kfU-DCrcW| zBpPSKciQu85^+9R@w1<@c{QB|^9w1A8PhDmPKfY37#=B^T?W?+5_-X=IO7H&`%2=q zv1NFeK1+gEi#aDQChUi2h)|4M*7pEb{$^2ttzVNHd2p#JwYE@5o!l|PN!GlvpnP!4 z^`Zc+0^S&P{!TjjMta2D3C30#BCdx1WHY z?uMW-CjZ369rz|xm2)RSYT+HF&B98EgxH{P@&o)fsxO2m3 zWr+NWT31IaIJB#9Qram=`yan@$GA_h$;O^+BaM@^h{>w7aeg?hCpd3NRR|BWS}U9- z+oQGas*ZhcoAWO(Aado-h0XDQEj;y`#*-)E`gd$T;R_4-6%2sL6}l$)?g9=Rk)mXB zlRIxq?xLM%O`KcMlCE5G0U$f_DF!y4$7~DmQSXY$yDcg07~LFvP+CG?j&G$kByxB(5qh^!Yahg|wad>1zeJRYQMvvwBVL z!SgGhwYi8?`3%=^UN7HdgFDOi^=aS?OJQnDOA}Ey=OcV>&=?pyKa_haFkbeQPquhk z?DL?e%o_jDU1om-Z5ZvTlH8=xsmZbEO?tbMdgf7c09swd}pvSntI= zMak!izhsAXHys!qlk>!J!YN|JaCfY(?Da%iYBcfeDsd@GhbVT@tF48XWKH+w*euuA zbXr3nN%5ipRG$c^aq9yq1VZpvKuiV}6FDM(Ia*28P6%(sRTU1oK2 zt!ZX&N!${cUpj}#7gu8|VKYM}7ZE+H51~cc-|B%}HW&^^+to_!UM|fgA`3KhHB??F z?eYHB_Ny&6xVN!ZQD>9VXq#1?$-agcjSp3kOE{!fBi5+sWtW;>s)$l?9xbFA$t5IT zczQmm$uG(i^@Ur_%)d6#MtaTJeR`KIk+y)lvYE+CXs8dJ?@Z3(>)W7y)ozOBm%{-R z;C$rv0w>zMcrNP)raq|#ccJKLRCB4HgpXeuM+sF(C4k`<8%iIAAAeEKNF;>Ll5|`; z50`JUr#B%kO2z|K`tyuCQhEV)Bfl*9riV8I4F5+6%4lJ9VNYa#Ji`bSG+1=(7(sl5 zqAP96V&S0bX+r8Xe;hSu&^UG@3xMj89*(qmv%|liuPPt44FfwTaX0TJ-g@WCWk~?i zA$eXb?sMX?9+1Umt!YgxZZ`;%6WpRs9|#%BxfJ>n|1!HjCw9j93)(Q~!EWRea^opw z^QSt8s8dx_6_Qz}b`D2HIhr_g)p-fM?KitORP$x#?O$Jt7?9QysIuJK>8^%Q*BTO{ zW{VfBg$E&&#=quAK_fMoPsX9@(vFTpJ~OG}Q9Z17#19g?68CU{IcqNF;lkgfzE^J1 z9bHL5*`jXZl?%{iF7gPGE!?x-=qYXDA=NBL$&RDJzlR_r4`I zt`ZS^4$D1PUs?l}|J?8HV_N!$!s2rnEV>p4sLAc6;I9*DCxe93xC?`EggX?^)1#x} zue@?E`+t=VmYYepS)@eIDR#!lx<65NB+QD!p=R`|!z-J)^-ih@hBiy$c$QYhBNI*HIGdqHmZhx4n35;!lIjhh!b3lFR7%LQrK4Y^ zB!HV{g+bQy>^Qa&Atc`P@lt0>FOqBqK^&1L#x$DsB#e@IEumY#9><6DaydW@p~!=3 z&}4=SH*0N3&43`ETQDrCBgz7yEw?O$DCYXodomt`(4AW2C`e>4lXWTxqP&)E^hmjC zm8Mf`446maSjTRNg%Rsy>uIqK%9?q{h-GaJSwFE|DuX#sTzKTM4;Zh+c$Q6Hn5DG) zv}$NKs2!59(D<0K$u}?*tg5gOG-$X(F9inoWLGWbAqOdKDuq*?e>%uj8o`>+9-%RL z=)4Z+zkBC{5jr?_QD^Nnmj*J7ZI=$vG~jgvBSJ@6Fq}3m5s8HyTD=BJBv9}(soaOB z!>b$9?OE9+3mFH1Z0R!Hy5jy=)KH^>S~Ig0i>&MYQU2a>2y2;)x0oqHLgRRX#$*x) zf{?Ewn8-|?A682#^YapYGgja>gyyXIN34Ryx_<%uV7oU|o7R z!@5CXC*RcA1FyfLhgdL@Dzgj3%ZAG7iO8N9apb?$=t)dG#wOcqF1Fu#_Equ99;msN z&Q4U`A-wNKvh9&-MwH5{-;#F%ji}WwUjme554!B@AYlx%V5K-!V(!p5mC&3!Ej-27 z<%GOxp8RrY;VI59C2Z^`B9RAH58^eWaq&=Nim5HLrWP9A>xRnUu2U0M?H&~5kl(ZN zNz};+W^CyQv*SE6AR#vaj3LOnh*#H`3 z@=xdFFgqPlbs>T^L7$Xlo0}BA+}L_FubN>~4G;7&_1riS- z+uinA2nwslyoLhHp1yszc@(HdP{pYN%j#~Qzx{r`5t)1EepG>Eb$e#6S=|=wd`Ct` zMnuL#GYWJ`)(j9yh^CBeWa8oSO7_zLNtzGlcS-IX`DsGrc|BGbV1I2C;WHxxsDYl4qv}P(bBRX+ zc%yl@Tu8RBV(Fdgn-cRHzg8d-nH;-*zS%_8KXPhpRJe}RBCzq|IlJo1jCv`1fq94# z@T5r*2F@-FQ27noN$qpOi4js zlA7U=+u&By=uuI#{9e#1_09Vp#9=zMQt4w$`4#HaXi9iS*LS!!rH*nbEdBm2+i(4#P^}}3+ zw-L4k{$^hK2N}E4{92PyU(f=lIZN@n58O}1@}bUom5)QBy+EK|q5KqISFzwqZ7IqI z@lem`GgfKs)h(ym`*w0Mqi3&>=dz@g`Akl}pgsSsSky;d!9z##$N0D>2tpMW%*3DZ zfLCOY1iR{BPg1C&;QwnXLg=kXZuwwl=>g5{x}xa;#PH-OALvstpm-y*2hGVHNZZGD z59|Vg)K|DO#4i=^*!aMkEr#9Xl-yb{Kg=`1LSz>s`Iwxa%g`D$l%uw~DiO0jZ#T{j z8IvfqWC-?n?#2nF$l>ZY^~PZty>-0CCVUVk$tB-%d&Ah?n_7*Sk}5VP*Hp$LR0SfdbD%$X9sPxv-tggdzyyW>{(rTyOdgB@6@|Zjkg%4VQr)? zs&*=Es}0{E*bS9Pbu-bs_1ujto_14)24xV-jHXo;%Yt-Ay+WH&On9U49hC4q_s2g* zMA4Gjx~`q2M5*s)V4NF^BNj<}dC>YeQ{xLE{e2%vJ^auU-HU@1wKv^>vXhlZ$pfK~ zs!=D-;=dZrP!bIgKKuwp;xfT9DW}RmwdLBeU^$Vzt*Uhi@7Nh|kH1FL3s5uLU;KH9 z`351lB*B}sI&M4}o9N%vzR2g%6y83WRuCrsSvF@$%j4{;)gtOh)@WpMRH5*WD*+dfFoYfMrXw;7onDxX&oI7}Ol1Km{c`XG*{#a@lF--F z4v|xj&MKN_Lh?G1i~Ct6hY-OOxvNVnX^@m2Vc7EQwYLrIR@v5-vg#l`fXH}r%(XH) zRqDnr3A`&EmlJhaZU-{0>qX+Iu0XqL0?_S&#v=c?aHA84g2-JQJRGw57TKBVom|M( zfP{`ziDAa(eCG4yUO(qO!gh!btpNeQJ71bU%bbrm&{8Q%-esKA{-Tbw?&RPdVn%s{ zU^G?dzciI*B|)>x>wC--fOv9kEiiE0(-!hnws(K2=4B?xs}HAe0xboC&XK#m;7?0qWhKWtNGZb(4=1aRe9 zd!J31)=&7ZhZ=vn*=L zdLmvzPY6ot>C~kjl4A6JX!`@oD~{+6p{0|P0X_NvS~t3JjCLRjfc|vTV4+$M+ehOx zbR-x%GA_gZ+u$jWR_r0yVtFiuJdq*e=PE5k+F>@*58SZ0Z*yn6ojo$&ak!c0YwQ= z<0}I*=_{L%bOZ31yg!*-++7JCPd&%A-uPPRYE`CcL#vX_uBb5t(*&a%9A$hU_X60L zo(pTBqvXK&xFpozKmZ;b^7NpDyGDf~6|}f~ZAyl&2+CnP@Q49moTzg4rO;Zl{xFq3 z8o_93l4A#A$`vMkq_hxBuwExyU=_7~n(a91hnNr!uFb<56P9Kp^TEy!l%&MQV$32q zbKLfF4N`e^1gu_TaD07^MjKaGPArse%YO?NLiM@Yhz#at*{a@L;^WMn)SI*R2^Y;7 zo4|jbgm-2)aYfRB9lC$NR7ndMzNrKBQmLfGAs6E;M{rM~E(1B$GkN*cv`>T=h>I}4 zWjUvtcFLWPECNC7wbGeXUzRh4V zX-r5EY}utI;FZU$&fr~L5Vxu7tuQWC)6jH=tSU6*(Jg5QBp)*gz1|tsR1hdcr*}TF z;7VwaS2stJQCXEBi`TDWQ%r6YMd8$KlESu~jm~8V6rsemCR2_xEvs%9P@<=0KMz-2 zYxeiDYL&SQhHYjUXq4lVPb$=21}dp-3`Q#R6{|F3ltVW39+u=?Ea!=r%ae0@o41_| zPAjHp_rLUtQaP(p&mgX^@-k))J@X^cOl60zzgko(>S@-G&j^>R=9pOgy1p!G{l%P6!&$-629KTbg|a&Z|3S>uP|8p4?Q`IvKMkZMjYsvVA4w-jB;79Bxnl#EmGYy%mRTBU8i>O?KI)2S6nQ`{e{Xbu{&%dLKTFL zsGsVag8?0p$?PDPMCtE;e?OwcF=-eZ`a$^h2dKX2S?7pQFETS}H7E}7#>yWfpefeG zl{yK;N(rh;sf2qeMKF;_Cef72w}1w4#s`G ziTB4n>D6lhDl{7rB4Tc1Z1@ImE||n_1I%Eqb>I~mh`xjE(0uk;WS7-MKe1V|o?Ejt zEijW8b4BnV86G{Zq`msK!|58bsm0)gF_Sn< z>MF=pVXjAbwMp6{_q$LxxIH?{DlRH;*0l`}Q?lLe9UmMJkEB;zzx5p#k_Rnp+;ff9 za#fm-pF=yWJuc4(qz#8~FghcEky&llaEo3mHp7@+6LqbGWbDo2SX*zXFm_LdY}dJO zYunsYQ++k^n&pf($^CP81*fswzdf;3@U>pjSB&Ol%8uZhh!wew6Gk_QHa%GK_ zqr%tzA3L>jSWQfDE(PNX`74c8b~pAm@D|Uvx|>IV9o6#ZBpO6D>wG~G9n8?K`Gv*h z)aE626WHX~(*wF$p_`hKOYH3Z=d}89=9J_rz2#8KhwE-AuJCVxE((7lEYA6zdlD=N zr(J~yBgj~P%nnpF${g({~#?$DLkS&aVT;wAO@S z8k`CB#U|B`K#a~&0y15D9e^#3fnMzzg2hgVg`Nf>UFQihC5XVfTj?K4?LcAFuA>Bn z)mCC5k|24XVt)6!nOH6j6BRL&M2{tw?wFj{!#fyRHyNRJ8%>+!#wqUZNGwT9R+Ns) z=}E`q_TmC0$y3rIkn(s8>!f(WeNjqC6$?q$u?G~3=LGIW zQ5Y)_%=OeQ1?C5Uu~25jxj|VqC<1fgGJ+&3Uz;LstG)7)0Bvx|xI~@9vogA5Mm-p^ z>uuqp!o?{AOHu~ik~&CntB`yz(R$%xbAC=gBLq?)zn79< z{gU(-|EEv%oTCb@BQGKCU*8Y`V~p>~$c%Q7@!zT!;^WD491c*@DbAqvnIp&&tIND} z6=Q;RAXiI>AF4Tmco|wxggI&oUI+@xi^BXRX)E~5WWv)mb9~i5-9RgIeR}n7DSNfi z+qH+0^T8O!TW+v@t&kkB3TLJdEav3F8DVcciYtLIHv*7&{6=T(ZgS{3CHDt9ph=l! zgQm;bI(r?bh{|P*rjmSovZ_D{$c4fUfwD;OXR#Pr5jk>*h3<&>VrCW_*Cg9NH=b9w zB`UB%js_NU@S4V>Gq=T1`b3lph8+Pely-_J!J1VyB4M6)$X0#WJvi#@<@vmX#b8)F zN3bY@0PZNv>F&Y4sBcBmn;KkL2M}dX|LOu5jW0=c`#!9AjR`$6t}hC`eeez z-&)t)-cr&x?RO4$;B_3fqC`cH^%19m&sWIXb-KRx9hn8)diR98d>ePDbqGL74RLFV zh@w}=D$WRHny6wVG~77or0}96gq}s`^N0_h=8z}o>s0C)LhC`sf^cN_g3`E}HX=yA5Rw4|NG5h;A!>D0-+GiLX(i%&eTeoY;`%7rAMcC*|8#w2btPL~TVHIDGDy{ z2Ir$015)kcVn#Vh4*1EG?7;q=QT4x4QKHN%jzD*hgc--X9b(nKECS?lhTAKo`anHo zZQ(aihmr{ulCdNdo8_sjR$_ zZL3BhoTn!~aP^NiAIW?-x=DoF0_wWEzt=t5Kg8uTKic2l$-7&<>~rH7vGRhCvj|oaTq+wtx}_IzfQ7l#{rn=jdw z7_PCpZ4TAm(f&bB2Gc{{R2lS(X?uWPy2NnQG}d~q|5I^O+wY1XS=l-Z+w7HlibBVm z9XA(=5EQ@-mQ^8~U^k1*h4kTUUWEmdAR>7Tb_*%hd|UOx~6pV3)#l-3}Hr2{J!*i(On^M4Lz425j1nV}z3NiBijme6w0Imp)6zp$4+ zRPJ;zP?`%9g^ZJsDwy+aTzo5aF!%p&I)_k*sV8@H|2x3-O-FU6?bE^GzD!)KpJ`jP z&z|oR#lk8*Gq`tylG#=oEioo{cZz!m|2J9UIT}evetsU9A%2uzK%XR@v@WdoLl4(q zo0R4~?YOF%+X7MPIeQdYe$&sFn?vMb&&{xj6lTfT*+bwwy2=OGf9Max9Q&*61LcDx zbrr+IC*85nw%-%Wqh9n=sT2_+;3OTj_G1)1bcURO&=_?cBIG`|4<7(N^dk(gV8GEc zNMv+bid26lTIVHyW|s{@T;lVDA|FQOHmt-t@<%3`cZEN0ab}mLQuT3XdXUr2{jJV1 z_n-nEahW}E@LVw_XShwj&k)C>QV z89hz43XH1ww-IEz6Q*w{*Zj(FKE+5Ex`oJQBth~pZ{0eW?G(;Z7bZ(BcF9gag_q5D zyF@kL`=(Hi&#JrC?QOi+=>WqI5WGvCEPtu1>c5hd^gnklP5J+9d;rzrMV>{=5AD&%nAi`G2#+OW+jIzbN}Jkp1t``8!^y zNH<^}%0~JoWrDtZV-E+(jUz1AUm?4Fn-dj}zeJmA$_2$L|uxWfdS`pm!L691z@I|mbCPL^L$KID}w`Ovah+p6mi5>I$ zfaLMfyWPJLw;nq;W;U|%yo*?f%>GacWz7r#z3gAz$g+N9#h zWIR53HyeoYBJ@XGTQT?U3qrb#5RiZFng;u))x2jD-3SIDX@J=Ll87=J8=q`VLE`o5X+t4X0E>hw>CHN>J_9Kqd#7 z!Q}O-Jt!CfU{4L;iPMhlQEfcmBH3|~@#(D31M#`Pqd6|dz=vj3@?{~A zOOQC|>}^R4xx0a;^(EA5YkzO&heVB#Ryy2xwSCy>WGhV)fSWid2x>3|W#pcX$J8u| z!N&P{0;njlG?#7N-xQ){e&ZYM5^6~&OwKcCF2G%Tb((qr%76e;^1PIx>h}KOw-H&> zAiD<8Lrl;HA*)XVm5Tj~D8QLNR)A#ue5DxCleCdAa1qPluwl*9C_EKaQMFi#lnmLc zQ9KjQYl9$gUXXhy(!g-<(Lf`0`LpZ4@U`X;hz%phH$(G7%z}UpD zF4kZc|E|n>K!X6PbZ!7?GY+(G<7i7Y%$AK3=vzxmKryqWMzNU+b3^+IsSu@!n^@F{ zU}+=z(=mA}4ulJaWSXPvZ>~nCCs5Y#ke+ZGg&rsr#mnf@TWA5m8o&hOfQx@b;C2&i*T8}Z4tMnfzm6IOb zosFOxuwNd$#=t$dVDT=}p0O}@wU--HJIN7~kjr_`2~V4@skjuiw^mv~(wkWq$-U4*ah0De8BM@tc|rTtx%f3bAph3+^D4vlj z#~?Nu@>|GB1VI19b7w?o{flc`K{#65U@X7B>H)Ob7$q@M(+~R+k{6A%hR4#gV~W zMF?)&WP@Vso;am(?!~=@EW)MGIs&SRGzafyuzqSK9tqPMH6pF^72h#mYM4|j&bT9gvX(U5dwEq)g-CJFMpSD|wE*f)pZpOO zg5^MMM;Y>U`-zf{tg(?lGO(GBA+`dd7MnKiG=R(4k<|3v->wBV`M73lIXOFo8f? zhKPBFi|m$`oERB9$?(KOBC4fA>V+jE+P|5|@VC*TK0-0e&0=T)+#0um!&YQ;wez#W z&i8mYm$~zI2)Oc#NzPUwQNyRiz2%aBtq2e;fUfua5qtHi0@ZI&r`+tyBcg!pf-oS5 zhrcr+HiFySCUTinrHZTt`&{{gQ*&)WhS&vMk)CL@@%Ch32HTd(emb1A=r{!*T(ob5 z$A)YH5~#He!ZK}VHl|xA#GS|%SasFc_QEEL*i973vf9W@jP4)!czB9C$_xxBwF4Pw z?sh{DT-Ud}{ajA&fn0=|4nw+tH`cfcymEQ-@sJu)Y+}zgMZuJIIk~eJkn~eTl<2IA zqmxNGYTBXv zfs<;cp*Yy-Y?!pgnvx!$wN&kVf3VZt>>hc1>9qE`8|MV6V=t+a0*LuogK&9d2`0R4#bfgibV zLjQNlj995nD4o7QlM_{iDZUqk60kXs9N|@j)E7{T5bSM`185R&0vA1ZibSi4hpg5x z%7~THS1#UK>{z`uDOtG1c9UWpHv!RZNr&cLs>6*lgn?VH&%{MT-bcn)N8X1N1ZtXH zqOri+vLqi%MQjIwqJcfRv>O$A10Pdrau97RX!OUjxAxtC@BTi>-YZy={BG*?&oJ|u zI!4p}OM%AVt1kxR0h`+Fy$WXAe?47ZS&{$Ov**v&o~|!HTbBRV^7`-oU+)Fu53QV7 zU=;3M2OCE(H~06pyWdPP0;^W|?JU9Ss=fC!d?0K#zv%MIwRz}CReCjI2IGb04bHd2VLWlCq+xev}*F9{Rrm z<*(EKXRA+txBvanJ$;{cZS;S4U((wCi+>{#>XaLxUgfvD0|JE=F&ABP^5=9Mo;b?? zB`I#JsK7q0l>@O1G?mai%Df$)XscFYB7b2nl~%Oq#7CxN49=HYNYjE8%sZjk_`23S zPCHk$!|-Gj7jk``pEFyRPU3R6=wU%6{R=O!Me55$f<+H`tF7_eIK)EDWjGt|4V;b545NM$F{;a#;CLEKn0D-~3`R6SfO1>=u_7UlQnC zkItjnK@mwR)HR*poGJjnR79h>SBcAU?W>{p(Lbmzz)4r3u&mswUHZ! z*!I}wgx#}A#7LQyZ8Kyxv#Qe(;R4h{&VjGo*K`sg0NFc&dJ|M_cV`0~+ zI?qE`=|n2n6zXl)D#i_Ft@Tdt?@tH!0~nnu&HOLI>NM~FOEVG7N5%l)Pw_stNqgOU z?*C`c*H)|d{|a6~&wjuE+oAb!zqZ}~-|XzaK%wajKyL~M(5&>^@c<2v9;BCBF5|?d zCj<=H^n#<&oBnV&gko#7zC24C>W&GmL-6AKcn|BJt)>@HI67SBP(*V@Qp0e!i_}yr zG&^{Ga$T9Uk9_d%CExdC&H7?+%R@<9!^vxVkt=7;$QqJJY+gdZ=f+CKe)vHz+R^Oh zoxbOaMGQxw*NP|Ek*PG_j_$6|bXpL&n|IiA_w%cf62^Oe98xe~zWFKk{csZs7#AF^ z&fak?kS>_s6dYd9412v@9vTkz@hwHwUj85qwA9<{d{e7ONCZvG!se6D^v>f)1)>!L z;4@Llv52tbIgjDs7kv{f3e^TSR;2k+SiP7P9gEIIu8Zg?zXYi-rcD^D^k~fOZR~bp z)DU1DvaT#S&r?uP)v9zNf7+eS(f(e&gIf0r6nNFYWd%z%lDH{%1!G^&PB3RVkAnnz z3n23S_umtrk9BLOd?wt`9X5hP5+Zt{A<##4vi8 z-QTQFZ7HID@0x*4myJ1`M-t=~j+0T&L?#4hX%1Ip`QR@P;{UGb1zkscA+uyYK4(K2 z3-wX#5v1Ggcyz*>4ok@azRZ6A_h~y=+2B)gzGRtr8 zZr~7Y>IBNq;U#k!-IX)I;6hcxN|Wld`xVvHQ;`g@hoX`*hp5p~&O%%3a#Ad$<<<~k z(G`>5>MF@YSWj>D3pPCQXt=xaea;hi_q&LU%=w5q-<{~1k;I^I?nE`^n|acz zQ;>;211>G#l+`C3soB89Nu}j#`ja%P{5zxEadKKE3|mgFm7!^BH$@E@RNP<7%`8Ga zk>D0Y3OR(FTe}C5s$|;{sjbW6f@;G{-4+3f+s7`kzvbQvxLTdbvp@7+vm0(2{ohQf z&8&HfGQGl|z`EZnWj5u%a1uDeA4>szkNmg1`aG5YR`mY&e0BME`S0UOdhNZn$$yG| z|J}ynOa*YGP7_yyHnbLZu}mKG;v)r%4C9oSj0n^<22(~iA?k%fFIz}eL+S6Rbf$Mx z5N$fDScE>fhj6Cs_V`tuV3&$_+y_hpE5FIvcyMz|4ja1(AJ&NxV8A(uO7DKszFUe( zJttG1%}25XKt5-b)wTPs{(juPyXnS2M9z zKi*pJq5muEPuJ@4e^#IUZvXM|Heg0it@K}PU1y5k@2DvJ?I?ajk99h(sqEkoqp(U@ z?gn=L8rIZ;$wAwg!q<<)y_vQzwubh_;%UvV2NLc_TfRf zf=>PG!Q#!`DTy>R1ixR~-!Vo(gxS)KB-PTWP#)s0M9!eGcYhfU;dEX`+(2L`5 zs(Cf4tMYt+)F$bQIcX#Q-72}Z1KKo?zEU!nSb<(2&5av36-&#E_O)>7w|EUT3}<6M zL{N)l^tWb2n)m(ADHm;Yv5+aIl{?fyUb;l=Ux zHle56qyMMHza0-?*AsWgSc*TrH|f^MfBspw!uSRq_Hc;Pc`!?8bViGB;cO&zrMEeyvF}OUtRw_{^v(Kn&1ZQ)5H>t9?9&Ip^Yc=Nc^<8(autHs^aX@mh&@~odw!CwvDC}$TBB(fqyLvNw2 z$)WM&iE18kRModi^a`MH(ca#WK+IyckzefF!7W$vtE25Nzbxk`|Np@mkIg(9-i?Rq zDs4&31eR+NP39P#i zo>$*RFMpEGQ;*z*D-Y@ya*a8Z+yyIpWcky^{Y4hDIJxTgZyuGb1NVy)>7~F;lSPvX>uh9Db{yfIIusY%yy!enXPnAKqP;FVWg%XRb(6hhr2j zo8vdW!6&@^DR+h!N1oZ%n(u#$9P;#Wcy4lJF^6V}20tpC7e-t^X6M*@${Ouj{?FNu zu=J>_`{zGaJKOk%Sc>$wxLob9ZC>Xjw?mX5voe_n2~=0@iF6E|{o^C`wKBCYyBWrJ zH@cJH-A{ruf3+vJ_E6odKDJkN@WN~wVLPBI*aL8r~j{i*OohLqIGqrI7e0|~- zauKJSi;@3Pj=YwlN@vlQ#MdY~l05Px^Sq5N8xm9QbzjqnozNc2Q{qghjeWx0V5z_4 zA)QE99=BqCektpMYUGMyrRr(W?~BisAobB#*&b zLK!7-b(UOBvPJ`iKvf5G?5E4=I#)*Q*FPFm#|j}p1IL+oV3fwvYdzuBRS}&G{t8Y3 zZN4(#Xcf#jcHH@yD1!vHxU)3tEKF;Y!H@;K4W6uliso2Vz`9-b&5iW)xo{R9XP?BA z@HiXx-+F|DdD#f7FM0!xpc2Ol8NR$Qa{ZcgQZ#LD@#D~wdYk%FZmuUke4Hs`fKP!; zclO&abuLhfn);MvmUL@s99(Lgq{a9JZo6G9*M$Argkr=oZ)itC+~^TlglkYT$+pJc ze?%Jhh4&qmT`Ox*uq?&0v#Y;4_hX~sUs6jIe-zTi6KJO{C~u6w*u_pP>Yp&bDv+L&JoK}ra}+U|E9pW(9(+73qA&!; zo=wP$=}U12gs7YXm;kAJR3-Gld$QwsN>+;j!=^5g74e<4Qy6ZU{SgUOK~vOhNk8g1 z>Fb2MO;QDHR=qoh=8C}1MZ`jf*&uDVj`+3HyR$ca?kznx>E+nA8aU;C=JN|eu9`oX z`EflC_*X@RIv@g4_|8ko=db$#2KYIJ-pI_&nDNDs=xgOYM8r?xpI>p0i}(Qy z0azEW`BKwo$t^&5Z5P=87^8fm? z<=^H1kG|J!9YUl?qs>(a?E@lN>IDI* z#Tjth9=zk#X80uL$0Pu|zHfQr@;(XD|D_`9Dqm=RtmKVbHE)A@N%Lg48<|9l?auc^ zh_RG)*{U)G#P7Whad8j$R;K97UvvmS-^o3)&8zOw%dGLG>>w1S)%1H(p}V(n_(Q(0 zLCPF|1eOV(^Np>oe0yhq54aL`90rT%5IH61FK#8db`~ib<7S@+ou=c77HuALXYhJt-t2IYD=8EyCAnjdr?3Q_?EpTz#DQd0I2l=C-s7U#B%XIwtH< zOS9s8(lA&|k)JpJwnKK(je{&&Q6=B%4K(dgPrufS%U<}cUdTxaP5G@+==*82s&A)% zJW^WS*n#~~@57cEYS`~(1xrM`nxs3m;8Zz&Bm0|V_aSrZ9@$<29bvC5-gR3^wL42X zeAL~`H+MFAJB!NUuYLE6ihkxIFL4>^6y%o-@ft+-@d99 z>~!|LgkNe!yPcz#`&+!va$vg$Bv+2`Oem0z+Fr2%*@P%fX|}h&arlikA)!oDs%kqD z+GMrxNV44w31)h}u=>~9Ds`}zv(=U4VzJKrikM|Tw&0gWt5;I=v>GDRU;@|a(@i;L1bn~r~SVsK0WJ>AATeaPd zJreOo7Yl;>_j2O25h#y7)BU%~WCzZlt*mCNtLbirqQmY!w+>~E?cxNnX}yCDj?wCB zW51GOSOF3Pla+aOwXs`FtGm@b`hl{>R>d+Sc#&^eP4{bm2TBN|L+f-~_IHtLI>v#l zrXVc7$IE;*gc}Qu}*HXxe)=+*%5zvcQp*z(TR6eMmMwDbcl) z)~sAU6p&>3$ahoK%D>Xy4t}8Q;D_p`TuGB?dB_o`u>7;Ew$;Ho4@Quam?ghADr|MI zL5Vf&k46={MM59?y-~sK^qQgVT{Q=zk9%Ck`ZoIhe>fA^~R{Oi`VSD39 z;S|*mJtPML{u~;U_qw}qOj+fxq_tNv;?_IpY{q)Uhe}n;7tbikd7@wY3g@_|#>F4a zhWSw!{^RHsH_BRa^k6RY4JD$_ir>n%_Gz#4{gD^yw_4#V+A58zSBQUAD;2%#muiu& zWerlfmG$9=ZU;)SeYn5tt8V$0^mM#&NW9K{IGiA*tR+O`o3hl%#9Bf^lCnZRSxd-B zD0e;!lH9RuZ`tazgq(Ptt^LFA@;xGvisN5>mQacyBtdy^;wLN} zHNjA?((S>l>=1?&9A?x6|BCXx{k>S6AWl+z#I%blDP|bl7~$yfIQGy0D;#Ay!3Jo_ zY6-o6xpCY(;&wCUe)U-cz|~sZJl}9btv6s?t>(=5>Usmz#;g=uwVuG$Pc)o2$TEdn zSWjSFR)_ee_xE}N=qZ)*r>r0W__S(pUh4_ar&U{_S_1rO)!+%%lRcPLZH;QlCI}x7 zk9Q@ZY?>-Z`3fLvg;ToF4QKQ0ZaclGE}>EU zfNn%HruU-K2X*4aXI4jE;{lzCOik}drBgaN?DRnXYE%CB3)qo={lmylv^~^Ms!Ak$c7d zoAgRsXNv+of1XmEek8k+h&@jNA;MOo}NC7MNH>@_8oDir4u zXPeT;qAd2BQpKV$^!j-ME}JHS$B%UHex86#Q_nXJ6uUf2elNjiADK>3!GBLG=)9xw zL26KDS?4Y7oYy|qn@9#&{XE$WZpC@}!E7X1Ud9oSxV(zKWll>@*;mpL!bYC1J zhwO9h9(K33VC(L!(K3DGjHKoX;?nBp$u5^2iUO9kZ05;^PpzjVB%5E>Ybq%|Pw=2o zui)~&ND!h?%XoNa__Eb6QVg;E)viRH#}}=8#&Jw^QstnndswYp9lLc`4~WGNhW(K2 zQ~cDnF+EKBSVk)bs7#yiMeAl+DWLzNb&G7KuGjgZzBfTzY|2jqZ}OowM<>Nr$$o7s z2Dx^+Tw1GN)Hm0fgkm^Dgt=GQTKWW2c3iFHdN{M+SWBO0n)Pj+p<;cvT{gEiHObt* znOwe>zPl8kf%;nd;!+kYQ&8V5b(F7AP~RsjSf!x8MOLszL49ki;28yVP+Gxyww6AL zl(TwHLH#6H3n|DqNvLq>=ve($+e|BTvApcr{%)&SR7rX+zSSE@+%z2nl60~wg_M@Z z@3R^Pu`P_3b{R@)jr}W-spEwg#8-eGHR?w{)ChEBEmi8<8hLv_I`oSH%Pm(6xJzU}0jot>Sm_^nnLHK<-8{*_ib&;upK_HSB% zjyLG1P2cOk*DFYbrLpSj*LpGC9_U@jYlOe*m3m5QqUQ;(75^-&?ZGGT|MG))Zcj;) zmA_Vtw-2RDTT7o~8k{=C$!SiDjU8TFPL8xn#jk{atAkO1**2UY z;r4!3`77yCmEr;tB4O2y4i>+ajSf2pJ1D1}s`~uX_X_99gGMg>qwJxl-0X)PW5V~h zx22g~OCL5&54e`TRp^Up&*CphXY>O~?V)zq5G&Tp=&$;vQrWPOD*Crt5Rul-k#S1u zsuY|H2CCXDXf;)}uGH*xw>oSBiuASgK?S}DU32IA&gL->S(GJre~&LgQ@obGp_Jd* z(Uh^Gd4gL>HDd;Fgh^&w^zEBxH+s^dxaR9koXUF5+U4gTMeUhLasid!b^WEUBS{JO zU-~$blyCv2Pa{bQH(>fIl9X@-rVk-W33p)n43d;^38pU}NeQ=L`uLHQ*a5T^w|%U` z&Mv~TVpjf24p{BAD%2Z=+r}&SAN4ABDR_nIt>E9>Fe3TA-acsf*V31qP`xyP2(wM> zB-*<%sSU(Dsx~kwimyqdR~Q)d_)qx>`Rv91{tnP4f77)mqb&WSUWGt_P^j-Zp;G*_Q4Jp6yMd&og**v< z3)P@7{MIOpHyW@^sClR#3thr)`#80~+-2)}8~Zw=(JLfxnWDrQ7c<~}!%ND>Mtl6K zRc_?Nqpb0zsI1^^Zro)HeGiw#s`c0Zugo&rO!fXD-&*WHhl4Z13H;OIf2}-!y0%=i z|9p-E`0xJT|Bwx@b=u}~7@qBB#{X*6d8lb->Eakv58SGM_}476P>(h+izj*E_uDJX|xzt5~Ya zmfq$=^kn7a9XFfd)Pm0)E?qHhOK8?DzBk+4oedRux15@{IramW@8OomQ_(>eFC0%~ zzga|LwQ!emX`MVgiM^+~7uk$~wd5tm+TwuS$@hbEB6p3I{31Wz?5z<_Uc^hkit(`jB(dcM!d)5EY#>Y3f9DZoy?a>u3 zOCQ#{JK4m;r+YaZ#muB};Zv9DO_XdlsTxrr?3KAo`-Z;%e+>n|wT^{LFt@Hx^Z&$c z^HTz4<9vjBcFa&x_gzcT#k^EOfC&+2h$2+vo)6(I7e+Up7)p3UZ0fT&Ildv(R07Jh z-@>0H;vv2_XCwf@`D1hj6w3ZekO7+*!X-su#d;u2br0{)!u^AVk~;%$qO;M>JNXx# zWD$r2nhAc1RaoG=)|b~@6CM@!lQ^{n3+xbQzsWEjzaf@q3wM5`wQ!E|@o;i-LC_}L z%7_N4DV1k%8(*Zk`7g6`b|ZkTa2s{kd17K;<3n~fhIGiE4}UaVWS|vtQ!}Tu!4Usw z+@a_COP5P3zv>S!Z*h~y9~bv?^Rvc#)cnN^0=Tn66~Zw$$EF0R+k`2#S()=-V@)yn zSFs;NrW)TizWNl3&vxJ;wO1Bh+IoHfa0J?t2HpoI^;$scAz%_f@bkv2TEW7=3c*Q2+DxEy+r^Z?0C z;;Q3tcOnPbupo2F;7bTo0_JV>HoIL5{_P>Y%{84j^gZ-(U*e)sVxjvz#*TE9Pl(Zg z8}d86DTj--j#7+@IAb|m;xXA~G1kV<3jN^#i?1)iQ+#%f<;%-8E)7p}u5Ux(=sm5r zwgz*cmM`fTjpV3Q6sWt!i^|k3`fEP2nVu|oQX(^(_?`v z_U_5gLdR^%ac{05-RffRm`_+1q&y+8ug3B`{SZp;1b#tobc91NC^`F{DfC$3_s^m! z&gG1b!{H=G(^5DM%wMsJ=Dme8G`Dg7(+N@H&a<9_)4P>RcjZ9T_yeyM+xlW0P$d+@ z5*OauQX{^d;)%)%Ch!0Uphc58i&Kz{p=V}1LVMm|P%xV^cu{A?woPPU&MW9^~0 z)@;?N?C;fU@Ty0?bo}}Kr|b`(ebNc2ESsAUvf(x12ZmR;qL1;{t#_H8S!0i3-$IW{ z_23-5am@1d6yM2L;kb6;^N+C$btdK(uTsv;2i@Bn6Q=dKqxiIaGf1{AyRx)ZoGpG0 zhB>He{Mpo{rL0tejunoiz{k~<`obLNA|7b-*rGt9YY5p~cG;|Tx7C|r9T_S{V+6Po zJ5;2Rm2S%!ttWoyr~7=cEPj8^PdOs230(TBWykt`7AYlye=Q$mC|i@^tx zJs4u*XA)J&M{+m*ixIr0;zroWs2vI1REfjg{Ub-maV>BcRoxQ#o|&Z z!ya6-2XY+{kAhowBs9O5Ic({&rzq4HcUQh6DKT<(&9|haUU9wgzaq%X)p=U7Z5)!4@hhJrBx+o!|5?6EE%i?~RsS=$eFm^51$Fv~l6?sqTWdE#2pZ zi@_MM1rX;BV)l^6i0vK<>#@g*l8}hcJk<@o)YAigs+)K2;?H3CK3zDL+JTDP6)_|i z1A&c);2(A987hqQG0%Oy*Z<*1-+AI4MfD=W*9UD?5KWAf%#uttCN|7+&jh(?ms^d? z4V=7mvk}Ey*#9+CMGBBWFnh8#%&(oRBy`sc>=GyG!{+QXnj}-Cikn=SR%KW)F@afB ze7~EUt9N1;Q8pH%5}oPBn8=e;ShU-bpgTYxX?dzl0U_=Q-S^#q&lvebGIq{wDDk(ih;9lsgFnbud7tP!!~=aeH!6CqeQT2NO|YKp~@ z=6zCtvs@UFbv>|^68O>xMuCSK`ke4+!yVk8EHNFe0p_{rNoxxeA=VzFD-@O@dU~Fw zlWb=+dUJQvQCg&V(`{Z6up2Jyc66t7hk~N|P{b_My90fhEDpH-K(1N1jnF_V$WnnPHL-`lV_`U#cEBifWPbJ?rNnQbk|C6z7KwrY?0cMDT#e8=3BeV` z?~2%~D5xiBr!BOaogwLQbommd-Xb$95F%|9G_n}=*AG+g`OgA^LY@&nRr49`vLb2Ks- zOu_mR5!*$Zh>5!dX&aHV;ghUK6t53crWqzCF|y-nsy?Xv+h{P{7>`dHuPT$i9zF;` zRM!$Z6SsgW>)MH4%8f&iVEOGBh8yh&XeUwU?t&=Ko|#~wv*Z3@z-{Oi&J;{>(mar!Nu^jcW2 zY{B-TaW$ln4$wBdsV%Ppaa6-R-imM#Qun99WFW3XG#dDliI|jMa{1AV?VosG zSA$bU{yuT*4>DM%z$so6%BPFGYm+^S^ZX`E(@$AhuluI@8VXr)0j#tnp^Hq}?qb#cj}1jEaGb2Jps*srEg zG>d@+cHlvM?2~iwo_=aXx2e2JiEXK9tI*sYQLoEeD_MAgy&*w6>hp`f<)r@remce8 zy6Hrh;M}IXVEC@sIaJpC*FL4m5f9$!)7>P!yVdraD=_LR(5VmXL&*}SW>^dxR-gAa zQN`~WuC2+;p(1h+mYNv_YEzO)yVtq^C+2kIzR*+QzVXyb4iR)5AMlTD5mf$;V=iVU z+<*C4Ve+xDBf4qGQV^^HJynJ0t%CO$0w%P8=Lj+`2t_82?c~Dx369KYjQFG?FXr6* z6aEI09A&JLJoA)G3X1Yen`;UD3WTmnOuj@?CSgsf`jvqMOdId6lA*4#n?gf08ZOzD zS|WWiJI^gXW1)yPJSBMwvl-O{5B~4nu@4vIfY+Qq&kfWVm zo&hhGO8v<@4AQRssZN8?Kl-MDo$pe(u@#0 z?oeTiigv`UR>>}ZGYA!dMN})5asUb)t-GYbShY<-aT~2=!z+k5g;p6|C0Emd64SR5 zE%q78o95hG^M1&oU6Vamx>u05Z?-iX7-|5|zeY)$$9)|a0?TgNu^PljaN$`3hCP|g2**1r)S zHW4vw)ChtJkrFpj^2-g;`S}d)P&bju039(5F+t${)%QlX+e%Innl%{>e^VxSiQUX_ zHcD1el`NZMq1&#cPW(8d&IGfeLlerD_oj&&DUeZjNMoj?6p`uq8FPIgu_;=cV96HN zWPdCwm-qSH0u6HPx<{tN@{O6&-UQ7!p25^xE9q`+Mjjn{G#FgLbHhfn-@%3) zyI~nllb{A2&`kIpNhWuFju!u%*MqSh=_`fHSqWRCK-o-p9^flgN7f&a~!k z-(_zqJRD9=#`gLneIW^ME*Jw1`0d+1YMlhXC6bud&vM|Pj8W4i5@oyGCkVUb!y;`O z^sgB-ws6tBGcdPP{%B6R`;2%FgD_uXSm|djFtpBR<@lMj?H~e8)|CMqtlz1pnXyL$ zY~jRa(~t5{1xRR1vbobf_J8v(jqoU{d1}rs{Q1Gq--U=uW4%GCUS*>Gh~;mpu@lRu zW6Q&IPLC9TJIq5MkCK{YoeoC-2Cs4d+ARK0MTmq1>M+b2&`(C!#dj7NX5?C)H&Hsyr)Tkz&SjgF7Js zz)C;~+MLkKrQDU|ap!XIe%S(;YLi1>jU{mJb>CtGg8)7U)yrYJ$^62`>TCB*d9G)E%wL*H9+pn}R-* zqgd%k3X0g8Bkt3hhOj6dlyk}T6ahu#0dsdH-vN$zKo^i%5opBlcnO z8!&;%t*?=c%_liHFOVTQ`d}Ujkb*MZG2EZ{^j%IozU}nk@V?_2oSb0s>?T+JCF6S~ zqZ;8QvM@0T{mfafv3-HaY<{3rD7m45yq204M|(U9h#004al;NbY~BR$roWfv61!T{OTOQunxQi0jPn`=Y~R-M%1MJJORs35wv z*c(0Qfk^bqwf&SZKuHBhZ!l$X=Q&wJPp~|J;7N?&)i-+v>W=9&SnDvUb}yt2ktDJv!(Yh zPEda85@g5Vsr^L|0v!~F0$eya5bq-q7ogR7^cscMS6MC}}5Zt{ZuGoQ`P z*}sclTibhE;=}I^%7zew`Fq>B^w-_0H;&}YTnCP2;}Z{qHg+h?B#|5Ut&%H_vqvSh zBP%k0Yf~O!PA1XHk}>J@HqqXQfSw5-3}~s8{V7%yXePv+Nl>+xi)X=C7*prDe{`x# z1bk%&vnU-Ko6MeWr(=mG{|fvzKW01CGZ#^gKWhQ5GL-f>$Lu4r0NFy>x-t9elxJhM z=}k+Bx6S17^nDQ4bJF+p(ksIS9c)2?$A@qq`V~I8iy6o5>f!Xmj@Sc=nv-OcM+uA% zuec+_^MteT*Jh*wffh=NS1?}5s0|}I8V1pme)I-@8F<&g_Rw@N1Y2dyNJh>3PN;<* zBeR5^m&ciclg(%Uk8S1oDEnLZRl6F`uTBE#YUix#A47#-;D(imZSJWZu#IAUSK_aA zff+)&WvSgt;&YIDm?V!gfab~;{&p;)IX1VM6ATr&&fLMK);s{Ug)xqtXy{4MR$Ac^ zX&aU8xqPGoxbTA_*E-7DM{mN2CaZpGlV}@3mn`*%QjZT|cfECmWJF}JH*uIqvlpCl zxJgJsTB!UWNF{_D&JJthRqhGM5^3srE8&s zDH3tgd^S-?C}v5qrV~!CWFL6?9b2VoalLJ8jQrBa>?_ezO+hA8*Vw*I*)f-3Vb^pY zf|T3bqgbD-_9kB-r94-;jty4rYCZJ?TT=9*6IU9_t)8cDnJc0r!tTq+XQ9#p{^%HOrTmI= zR5!g&`8+6cWa)o{wZyGGVzysgqN7uOWPMjMzF9;(66)8TYFaTv5fo5E*d z8dHgok+Xa8;#HtyE0No5p^W+Q&`)T8+}3-Q{IrcU^_Fp8h=g>CX{tX#qVpR@3TYXN)#c9kT{Z}3`!Ml z*n+;em{tyDC(JO)fjO=jH~c(MAe6$Gg-Mhs^^coD?722pc{BMl&)(>^7YS~7u=$0p z3U3&xvDf!qvlwDeyQTJ~XA2902YXyIe4x!#`z(+i8Y;Y)KA3R5-5{)J-9F+28m4@4 zeMM3>e&4ml&4rP&xliJ+i(mgdn7;>|4Vf(v&mzmbcGZxsHt~x0pt9eU$IwKqGo=cC z+yC_3)WW*$q9GRwcjNqF_08r~+W!;u-KO`@by+;6ZV8Bj7dk6CEik zMw7M%w+d1-r>papAWSGs)CU*ioqWj9r({>$v9XgS95%c=-U|JZ5jzrHpJ5CK1w94Au7QW`H9g0Mqs}wTaEq-^XIJHI@ z5{at4L{_cSOL6nRy9zCTvAe;0N&CK@TsA-QV0%88++3OclZYn=BrJn-kT8(I!)}Cd z=sG{2bpe35yRt>bvAYxahpXzW14@eJVO zOdpksNOR(>oIO85-6<5_F*@`?{2B!1i{J%hl!>?0OQ?n4kO5hJhUPz4XUwCIs4bSTY}&C{Pk>@7U_I{S4TCW}0WhAo|`qH5YGrg<`r zc5s>I)Jo$e%~>#OklIY5L8BUvn3Zle1u8MZoI(zyR#(cBfuq9 zJYAXJIz4OpgNgpsp@>5!OO|%P1xk;NYeJ}zHLyidN2~{bU-Vgg%Aq0tAl^o~;`MNm zGcV&#G!tW6fHoGxI4lM@$J1Z3RJe|Nl2iUe)J#z@AQSSZ4ZfM7I z6t8G{y)(gP!sC>=r`LemaSvg$j$7t7Vs~(y)s2+YF%>4E%e_jxbWRJNCtp__c2mzxvv6Dx1kFxyr;D$#kKh?=b zHgP>3muqHRAeX;TYdn9V2*XHD04t$7JPMl?4br*YtJ>Xhc_Ghj;tPLr`=wpM==UDW zVuEKh(G0gTP{aPu{WJ8qCJOI)a*ms*F$1Mv1bxdE zrNE*HSELVYC75_&Eg}Vu0m}U7&Ne-SErbn`0NJC~a(3 zafpa|GC`9Jf|P`M@hrfwykCqk4N;cGp5kis{sZ!9`pNt>kuZCsx8oDMxfN=nBvr8^ zyDapiWY0;QV2gH0Whk;g&k$Qvk*`Ds8<^}@E_{obFNuMHEmu&6F$qzeGvvRsf5Owz^_+;_Pf{KBMBhO**)>l#`aC zBVl;}Ym|~Yb|oi$$L))}Mr2O9QyAq~9u;+1V@X|XLBo?FQwFUA)d(CxeKa_mbfP7; z#Q7SBvuRgW{~YvaGH})Zl!)GKYNxn-o>G#Ha0ahZe{(dvAT*$YoAIx2j>1bT6w15Pey$Tth*8_{ z+C8;!6Yhg)r4wjhs8Z!XE1Nq!pFP8hBCU0(@Tf3lj@4OwkONJ{Fkbuj&#>YDHDfgW zKM107+5bqMA3n3EPoJ)@t!4jodw{V*Mn#fEI%Fz;E2yS|H~_D&sS^yU+e47SAReM4?V-bre53mKltJ3rF64X zNI+WLJR{*P>CxsRw55Jd>@49K@IKXGZ_ z(aTjgCKT6p=6yG2Dh7cg1#;!DZ|;7!y(&KSHX}AiK$~5du$Na?T z9qG$vlBh#(*a%^c#0wij_b`ITA6>x^q5M3G? zf=VNH6`Gl*2t{pz7Iff|lJ!*Kvs_+YT3JmeFLmL1-Ub1f6RGCe?1)ZZi%HlcSpxR=GGe?2?EJU~9jy1QGhFO_TBCv$m7YmxjOpUhp=>TU$%6fD zv#Nb23-HlVcehh1_LALw-sJZ8x|?R{dOhOsjR?f2jSoA`w!^;N@^FR9UK-k4l>2>C zVd>1vCqf#2QzL_simHMEW&z1!j>Smr(5x&hf-I8AM`vP(M#CrJL}GY^>Aq5{3>$v6x zozk{3v*3Oarr?~p^|9cVYSuO`8bt!?oZB()b+>2A**90m4D~9aTp&bY*rrY!{oG=o zcguU?ze1@%=&S_;!eoxn0D5R2&T@!A8)s8R#l#wK%9!+{Ax$DMfbqInEUoBF5Dr2E z0IdMo7=d^I+ptjsH$WObG|?p@4)J*ZTu0EqIO_aDcc3xT_F2b$-Wd#~jurPKa(84j z`6Ul$#MrSqVbGEb3JTB=JE*XdFK~~?eVu;VGK^)&K@G_pMw?4$Oy__=mxXK=;PDUm`lBSBNI_9Ik~ox{0L>#uphYp2CF~ za32!r$=_eBKHaF^-B5o8y5wr-L(eHixJop@cW3fJe$0>-=b7l0vHxP9DKrJNOGCrb?();Ne1608av| zQKUPf9P$Xk)F&iwAReQhO~@uP#1YQ^E=<0PnI7-S@?P7#e|&_W5e15}bvr*tFALc+ z;$QV2_&2>Mx*8K`>V_70^Phhj6dYP6bCEIf7>JhdAZ@h$x8Og_OjgQAo|euAiKlW1}7eY--~>fezA3JiGU4H&!TG?3qHXjm>{Q?jClwWP}^P1!Ed@W&<0tYFg)( zUj+yWZ6Vd_&Njx@6HS>NB6uM3xasFdJw+JsySXJZv_C&N#8g2Ve(VvC5%F!al z%1D)W>?d~(4!%V--%ZskkH`->lxcT^)8PVjcdN6%d0}m4~Y28 zq2(%!4~^wbV3SZJVSkh%MD3*e^i= z%r)MigT1VTbw&yOm^JC`$qP&7AkMBp^QU$J-SI_<^ldt$E|KC_R7~uy;!UmyEov>v;7Oh)h^rIoD@x=wN0f7{=D(5)8XzHpESw?Je8a+`^ z>yk^*etMw9zxKySlqXl1Mo@l%eu(G8dv-2CvXW4jqZr*ITn*(1-48J z7y>In76ss=u0vFMn+vo*!VZ#I2-ei-h+0C06?6qhqA4aqFUnst-)XI?iZY^ zeIJV#@g*-m&boy%$11XZML(A6QK@``;|uf{ZZ7<^?Rkjt^;Pz_B~t=?WojF2e7sE$ znb->eW8r$((ow!Y?8v%_Fvx1U(wJWu2n6HGd$TR2)KvwVhMINbWgd1Hr{3y49xKvr)Bs|jxQv%B}6!fvcT&g4S^yNFL_ zfmFc)FX$^WOGv_Tp51S`&C(yVy(PYou-ePf3>+LE@%XpB-8r1{t~jmggWnj#v(}>n zQ`uTb$7D(`j=MWs`6kbCQWBe1CVPYkI|WrPBHA{EJwPvNQnGTg7CK~J&joE`4bu1D+2lnDZLdOCO^p#q8|!R`#=>U14Jv zNenXcr>`>f9;+)-wwp>ViqKX3qBJ*b%6r}a=wx#%&(;@~F*&mTNcpso+2TUq7UTmW z2@c2pzI~C+sYMwnXE%HaeN^C(z%XEVIl5qBfc_h+T=@3I<7|D+{?VlL=kmfX|6Q~H zes2F=UQhn9wwcCuO>TY-@b^y?Y=NLZPZg08+&Mg zE8h4N0Hm>Qd+~#)fZ3WtL;>D(z-Obi;4KehH(Yy8WR|IhB^aRhpU>)6fvV10bI#pfbqE;eg2U)AeF) zl`=rGyt-0=D=k|QNS=LO%(GG^n0#I?uTln3R-S%QKqW0(TC((jI`uU!DZN!|w?7`V zY+OkZzs#nSTh!cQZ=3X0UF??bA77;_N`TQUJo-D7zQ@_WO?v1h#dsyiX zY;xR@7J{=Mm`=s0v}YM-KCON!0%Q^e^+l2~<6oGv>Z4Tl&g=$#}s?ovJIf8}yQ{L%U+uV$M7lp*6K> zpEAqzulQ3t11O%F=)=I+wmSh2em0Vn|4^2!{9*c}U z6i9t&6Zs;HnT0qWi;B0Lj#H`C9Fh&+>TDi%w&zYmE6uPm5q%6J=yj=k)Y+|U@?-p! zGxcCoV~d3tKPg=~!l$!c5hu#4=c@!XzT#M?+`QUOTK5GSC&1t6<-Mar9G8oAgf*1V zhl{d1bPCn+*CRbF**m;lj81mk+{QZc>(UsvC}47&;ORnOu0mp3vcN!S)@3ylf`uVO z8z@eAm%O>njtkyNsybm8%O*I%b#gY`P{-zE7?f~ca>x=meiMpT$Z)@kqy@e;AvyxS zE%bhpmOX@~MRfc~gzG~|K(Va!WVTTNBAATFIfA_t5>%zQzT`ykBtWQ%@c5xM8T?r% zH$vclDhVk-JA;CVpuRulNP2d{Atgg1qA%&O&UH_^Q;UeOP(seUVq?3dnj|TAaSdVl zexq}1I+71NueGB#<8U^(ltQmFmFH+Q(G@4j*T}ocjFr14V0%I}QW_ueJ)C$nc$X(P zdhoZMlm5qQ=ngKXmi>!VPRT{wehhn-*vgNgb)s9b{`08p)f9-sMSD+T{1(s$z17mA zhn(OkTvGw9KV^`MsG!iRV!m;BxPj$CXYZS%mvapkXFgqV2|}RWsQTwPNMwrMlbO1I zE<7$T$Ic5T!p~313=})p!Y6!P+d_B{?J+9b+o(|tu|)MM*bpz`HkJ^SwwI(%n*LNl#x{ zg>nkNSWghGFsQ?^F=x|llP&yh3DqjNWasz=yXc$N9H5nT()ML?Z;)j zKmOzed2M50n(<~uUs)kz;+L~O)#=WAaN}v!xYG||yFaV)-PZJ1vebueVJG%zhR)qo zgzqIhey>d zXaZ9o1MqNTExMLOrw3gAEsZ~5koIT?ru)d zHcCmOl+@_j%X6(WGgtQZRkkcOKruZh<(Sx8cRFO1$}6f22^ZOlM-Q9#HhFcK>kkpU z=-Itk5+1(G2!wLmRnnvs^L0nSr3q{GP zye`>@zArYxd-M;pP&&*ZT$RcS(4v?4SmaSy@8Bv|7s4J`R6PMvGb#38_h+&t_Q0{A z2jXPerR47rNx>d3Tp~(X1OeBe2m^WMO!qB5>!{X#cy`hk*l{UaeHF!I=S#1~f#WTNsY_ zpZy2TJf)>!6%DmqV4vb@!k+rMui(zCBNdL5H;z>M;jgSM7nLNSR!SV-TxXEtlBTv3 z0S*HXqjHg$<=u?FoFx~o&F#;#|6>fHK8`uff4g3q_Ftn@rDPbL{W_bk6cDrRzt*3v z@$TjMKc78YURzQ8hxN6mzx#iuF#JdTo)}0JCw>3L?#2#w8&m8w(&8o+`Dgim7uNWN z={`1U+08rd3A4`kNaPUryK9+fBdzl$i;;n4#Eg&Jne6zBM}Pg1^kC7637a3&a0L#X z8(Oz?FfuWb_hqo&axalFPAjA%g4qtnW`wF$B(ETTd&3xg>12%a(JevtF!?nt7dnHt znlSzsAx53siN#k#hDObU{XEfiF`+jTy*V2p`)q})8dBHdke%!i3%I&0;^A zAJ*xZw}f@+11zjd0eaSXvemzGyKi1LG264d+&ft;lA{$sN&I!Obi;!F2GE49f8f7= z|HEgi+26B2E$Sz$&n$4TR`|77Ba_Z>(H9gkYjKgXa_TnxE0E0c5=%JlYGrWtAlwoDIU7FBWAM58KNc~X26_8?r#m|1PBm;5L z?4EMw?fM30bKmXmCP-jS|MCYcK^$D!w;*o+DhshmIP;^i=u=4x$;;r#aE)(EHb>Cs z{^F_JDGVbXj^d1b|5{sDSuD5sMKtT)A6BU|3~kB|UcZ~jJwIT?m)YU|?vulfU3Ok{ z$t(5D+fElj1j5|p?a7UnsZ~l7^j<|u2^m($IofN=?ya2J+r!T9dfZ9Dtip*nrz5k}*5 zheCtsw4@!=$G2k~8r_FSL;%O<6TI23;0UhVLeE83Iwr8RIoq@L%h3qOC5%dnz7#j~ z`s9sSgs3;`fJSnne%q(z?TFVRSQa9%g5@%1$L@(B8473&ox8&-V~Nzi%NRN>r~`h> z4oC`_9WG_B23+uXzXFvvS#K%(x6x~?OHr8cX@ClbbF|mz`gZf@Eg*fKy}+(e;jI^h zuaCAo1W?us$84iuIlcrFdUxZWaHtixvpL4rLKu6<_VnLAiajvf12RZ2Wy@cD@l5y5 zr&r92)xnOj`NOPo{B>j>XFY5x`et9NMoY}aQ7@QMzUm&m4Ds*to$hY;s7Hn3bb$?I zF)$YbP!igUWv)NpPO{L^$37DRRtXrfA@E0+z~xlGx}&G+Y(vc_b|NhO-Q-qh0#qu` z%;fHLG5iIC^`{qu%df-f(K+!WCU^j4^5@Y3&tI}9(k%gx+>>~bA9nuzxYKjj*xt+i zovom86!L&DvQu{cSsi(x6t2x;66#+iy~<1t^>}N$Bl(4)po~o|i^D<7E;MFj0Kqd6(MD%h$5@X3`rW)xNQF1}xqrUs)AzHaEVX23 z1ULH1o@_;-ABDvai?OvT7mj5G6xNjCw2Q4Xcih|8PzFRZ5MLfHhGDirdRhcpf)#@` z!RdoC8O_H;gwU}Bm;$LKHn=?)w<{oi``QCBzag};c`80~fkT~4`k<$BE-2uP-_r#h zKN*h+kGh|#@i5a~)j4n~#@F-U1i$ojQMj>h(_58jX(2d4yAk6Ba-qxB z=8lHJxuH)uy8?i_ZHPY0l2Y3d&`PMRp`3JEp`jpN$vim1m1+@0vfYA60F&Y`eO;xQ4xV z(3US zx529QquPF6wl&>>zEyvuQE2;-&3nYFwJ)A8KEuVf{?qo&>a3Uh`|Rnn#b?XSNwF0&T>grgYa8TlTmP3%AOG zAr+GA^AsxGnLJhBNO^<64!~s;975nI5G2M++2@N+U`mF$H`?f|bS+=fp&Bv%) z$u4c|bidi#C2mQ|Hbw61htXZI5SE0XxIGBD=2RDShVQ7LJJ&B@{UsK`lC-D~_ZrOf ze7?V(f4AS=$`3F(dkZIHDmT$vK0kX}~)-#v94UAc-LNC4H{J}SCl3>oM* z>lHQpmpYYs|B+S;-$B|QmX<5QJCCczaU<-3Z$Q>X+z}Hat+YvyaY5a^tWUqmfyRM# z*M74X>%i($LlZ}!B7q)(Or++b7+jP1TV9_jyStPLWfV(@Q|64fTreG5u~VlP z;|50=xB~mW$UjABmpD*{}3 zZl|@?`r}d9dy#uJGaKC8+358Mwu_CtQGQ5p6XKDcMNcmZ>;oL`3ZYNiFKvhip+&+%fnkig^eXBDvT2u% zJ%j{Bik`1TP$j$=h}XW2Y(FsE|JJ$a5rofIVEnMZ0g0DBMZthl$`hTV7c$CBLx~h2 z3ACndi^V(;n{q}8K{hod=bv@r72J$7`?`-3)N;!8e(2$oL*S}!I__mlw}`wbw>4d> znhv4f1RawyhlJPJ-`~kMwzdxEZsr%ihQT4>(FD25hiL|v^r$ke zAdHL>51v~Q8;Jt`pe0bKhs_j_ZPl^|$sMs5{+8Dj#k=I@L^(?+UW17$6kEb2{n0w) z7S4N;`9tq^|0hpEIqYuFyknQx-$%`49e!i>h>yBEbo=#DuZN3V*NZn8u4{NXe|mr$ zIKa8^s=&8|8y9JWZHLesztAWmW{f3+_nrFu^u(H2Gd(#y4v~d86&ho(4~ZZ!D0Scm z$8EH7W!9o+%(i918rK@%y>&w&f5n5H9NC}ac0xbgIVh}`bZ3+e7PQ@I0L5&?zGhnZ zB{p{kHcZ)3OS(`IKv#qAb&oKsx<|eJ?lBE{k)w)woUvP95-*Z(uCAthlNCy;vB31e z7{C#WYh!(beSI_~QC&Fl!rCMvJ=->M{}pRy|5@6KC#%R>CYL(*6S;LDcg%BoxZU@J ztN@z8P$I_t^P|~rvZk&m9-1?l&xFSs%n)>R?`E;)%`}$Xv(98jVu~A zSBW1rS0EfT#MqGO!`QB6S+=s~W+?C4kS3bh!HtHFl5VX2#2{UwYWFYe^FH$Ti7K;A`U7U&k(z;gEA^4NFl3)nn#cJs< z#x?r~b`O$hEH3Uv-7Z0Hs?@lsH>PK2SWqVsf-Z3{fhw3(cvDmFX8@nZg)@g$=zxpO zO{_QJvB5UH2NuGB3zrEwwoZ-##tm<95py5GUvPa|{4g4kzGpU`MMNVoN}4_8A22U zg+w2K*GSP>3=*VCb{9ey$W|g6EU|1%+9xZ}QdqWExKf>@@nB*x_?g9JADVQ}D{{@W zu_VpePISN_y77TAsxcQ>x)5ek$bNnx0WBL2cs~_P!W~PESF={;X1`Peb+M8F_T3_$ zcp}|sRX`2K?TS3FX$sBYf8;KeXGPJ=zJ;7$ZecN@(wynrN43xKo)dyn+&yW69}G;5 zG{cR67<|EjbS+xMlIdE?^9@rHsG=&4!E_h54{)iDe)WJ4XtA*?*ywFD`6y9x=Qv)}uRs?$`x1z^Dy(sR5VF0SpH9 zJX#9L_Pt|~?;%)Di|^fVeQ(Jic+*bCZ2WYFKO8+1ccZZh(0j()FRxikCqh}V7J~hQ*FTI1J;b^g5h6yC;$0f- zuZgkYq^(`m!x?{QHfadq6-f$9AGetOn}@VV!}<64Jv#C~_jeAy-p5NBbkxoo%KR#Z z-ye!ZpE0{IWQ2;?flVGU3bI>8`)^*$u`Svc3O9;ey;wR1!*dT7ez3*Fj`C%j(6r7! zq?X9_z%b|8hQ;lV!|^o-Pa!fZn6w;wLk;IJ7R(8A_<{NZ({AO&c#yEsGQB|f5GKY8 zCZc6;?f6gQ??{l6fHlT58QJcN-W8g2sfr5PFC$|`{I+ITSV$qF$Qhxq z?pBL2xnx#I8cC%a-@(?lRsef9OmRD!&oqgh?}!OQh?PxT-pZRWxF>i5wJS~QtmD8a zqG?0mVr~4V&3k|Qo0~qe0gA4oju%nsEd%N(p4~9g&k>>Yf#dbqu358LMwtMD8e}bo z712v@@j<`gZFG5ygnYFgJE#`MMW2I*NsOb>v;m3D2YQzVD+BnRVTr8_=s_FYYs^v{ zXM@90pvz4WG6gj_y1bg-LZQNqesgibg08F81a}5iMq^C$(s+AkKL%J-u5>8eeon(M zu4Hji-w71O8ZwNSr`;R8Nn+Z|sOWO+>*@4T3|w2${DU1`a(Lsj%`l3CceuD3o>g%h8k@>UQTuoX6e`aI8GHC}@i!Y_gGFMJINXiOIok1-80*zu6E^+$BRm zjmuOLFotxJ;xDm|RaLYp5>+GY%tMVC%9YY>0jS&d2D-saaMI=pHspE_!0-WbLZzo4 zT~o;hFYjm5fjB>y-zn3N-M`c>KbBkq@#C;(AOS%aLkc%zhRn zrfX%Uf$}lAw@upsXZ-$XqU_yKufq?`=hz^hN}YtG1ykV|yJbKvx0XEbOhPnKk0|Em zeT3@~=;2YN2ASwWjJa??(?NGeFzYR0Hq@Ht0Y=@939zk?KbmfS{Hae|2T{{lVR)?& zE-u{Sh?z?8(d-VmM5Zui)(Oq|aAITonO01eSwxnT5O+(B9_s)aZzwH_^#t^ILW^f3NT?-R-W?|dCkX_D0bYW*nK4%+l{na$!HL@Rk_;^_ih?20~%Cnm8EmB;M$ zWKn%UxDPc9!b}mrP~;le@-SuywR;`H4gM?lu29U&&6T~}*T_(F#Vfxl#dL}+HNl76R6PKY ziGvj=xChc}+|kx15)3M?QSqnnE^2f3(W?ysysWiG5hK5o$ z7*zMJIR54ti7hWj376Nb`=d{HCxTYFvW6_Wvlp9p_qboKh`lKEiiUvN zz@3${hD97Jju4)~^Pxj*7{TvIa>sSCQ6G5F9{PiVK+n*C8BPQ9k$Z>-))v zFqzP&?{V4-r;)4^>`L?p_u%^YY#san?ifSjLyvG+2#dKZ5tnr86KsijC@(a5)_m}V zGwDdKKnSmA$bL{|HJRU$XuqVXqYP;u1P0*A2`lMI_(au ztjTaNTVs=QbPAi&wwPqTAK(~*o{NR?~cmcc?2 zzgO8KCe*X%2h$J2jic$Q>0^2veT7&@JCfjb;tY&5sd#>Q^8)AHXxYSsiflKUmSqGv z*C@mZ#6XbBIBj#l5UDIN%~16%BroqO({IRH46zf>R+B&=V=ju$WSh}(gtQB9Gc56s zT(Hgu>n^H6co5DNa7+WoU95HBeOy~hM-Tt0_>5ej&+Y-{8GN6{&y7`%*hzgF*O|E_ zj(%S;BYvB!4VTQ4D;%EY<@r!oy0kw8^+mTykadqK@;w`B*v;TMZB!Jb1}EEXAUh?@ z^oRbFQmkEAWAPFLrx}I2FA?8B1`}-}x;R<3&(^R|1-svpc@|V5+(Jp}$@a8uO`>DN1rSlL^XPH(ZvYfOf8LBiZ*6vXe z2uHGwXri$dY_98|ax1XU=-@o8S0I!k2A50{G+h>9m-J%z`3P15qUMG)u|U~-a{Qs7 z*(;)@h&;V^F+RtU`k-MTYGUs2F^e~?B0k&LZi){`2 z93-fy=+({aoNP5V=2`HQOjN}fox6wV1rM7Ta;|wqCaVUJ^(9XByR#Lr*CJmvV*@zX zhkx0EA7fTnqY%GoMfuQf>KJJY&hXGcj7&-762QAQS6z2-2fpLP+gv9{yL>191_)POjPx9ItIJgA$ zEFEl+J$qgbf}MH5D5z6xp0&YjNHKt@TXsMxvc-+0-wHK`k@jlK;)fecRgvANJ!R|` zgZ;+drAz23a1&pr!42TflopCmqKBd}&lu4FCk2h;hT+Jbp<`$;{%r^0YAt#a8J|={ z;^2&*23~Vor_P3BOvdpUCNg#+zzwYVakl#s)+EI-gT?T4B^=x|he5xKNRT?2$+&fL zcmd;LC$kc0W`D(q;$#>AOLf#od=zc>Dp885MRG`#IvCq92Kzu(R<_Z4m~%7%jbz(; z_zV-nM%e@`Z5aW9GQLqnJKJ|N*@TgfJY}ysJ=#5bFql6WJYY{6+$Us`&F~+b*EZ`d z5hhsoJDhBk2u^cKkmT?Qd1|=J?(@~)XgT)(5Ie_*UdU00=tT?zNmw)oUBBWmN*xsQ z&sa{!r(~L#g%!q)Zku3oPzsZWH38dduy;ovR?e~KOY1hnG;0XNqmlkSBo!@S+&E%0 z0yh+Z<>^QPTqh-@788g0(OIe)L<^C1j81%aHGQ!4*#;ihT3Okr6Lw_Q!E1o43Ct~J zXT_@NJGdfocxJXrj0#&Dm0}7CyOEa|sRH$NX2D^}GAKC%avoM`BzD&;P5pjezmZrwQZl^8Mx9 z*nW>F=-u27A>nDVmBNyS54{Y*Wj`=uK&y~TOq^*ruNwsw=`Mk5i}iy^(u+|ih0K#^3!22E8&T_NKSftc+5}s@`kno3{4DoDh zhwlZE$v7EHR!iSm^nE)gPkl`%QPc{l2%PL-NOSl`M42t?%(YT=T+{@nS!mQm{edRE zf`G#r6q3ghq5$SLhlttQ$By*m9`CnT&|Rw2G|`1Wn1&%($zIou>t1}j`{I%`>${qB zTFYDfVO-Dye6R~E6=)fDc9Fm#dB<%a5sbq*?BT|!(U~vt2#{>z^QF8cguXOpZ*cmK zI@t&;YZcS$tY#GK*5(hR+ZnT%xsky7FL4Fw%YD4E%co^ED8Jvd~4?x=V*SHUWPJo#7$2R@>0p1dJ>A(#FeBd+6wBZUoY&MNxU-ONRl0`lfTBZ;t*y`7~ zPm->#wMQD$?PL`+Ln~<|f|~-+G)!$;gTTnQM*%4YlmrytWo)XZfK|-oA5n%*RkEol zZCAXCYc)2=v}0{Y@t;InM3C)iUU!KPozPt|b6t*4Pq7u^`xu-C^G8f@kVW_;g;>yv z3t5Sf_IrMOjK1V^+>8$nORmqD-mv|w=}%TXkAYZCY_^jzYA-#e_Y7&r=OKW6$fa)U z2J;rJlBj0Y0_b3U8MA7P!bHajnNxQUj{5rtJH2B#6=9Q~MHiKT|G~sQs7Q21+dDoMS%Wio zYHV<^u-8!j)MR4R(E*WYb2Gz;d*)>N4G|AgP9d`t5srztAJ*0aqHyu2JM4)=6S&Lc zQL#nmEcNNd5W|KUF3)sY>(JZiy(8jT){U0`EQmbIW)3XcM1u5Z7HujYGhMS^rl2{k z=nj%{o27sA6_e&GRczH^STUvgidDgK#a3_PV4@!8phs!nFrX`}jZl;bvv|v(o-kD~ zO_*FWoTHYq%g@Ao$@Svf&5#a5tLJH-eVR;i?9S?J(;B)W}+HT@-PIMRx+gw6RkXMI89 z>8hb;DL{k6y=lYkVW6pA?Y?})6Nh^}>~zi0=;J^b1m(OephljU=yzUbjs_f+M!&s+ zL&L}=B?28s?EAEE>XSUf%FO6`QMw$OX}Sj;VI)4Umh5>|vm}+{cwn!s4pakT84!gs zmPJ~ScrnEysiaG=yo&I7;;>ch-7F_)h}Ao$5|+FC`-1l_U>t}|0A(*X5mS4o6oDZ| zI!-~#H8`-2*w8}nz|{%!hGqy;mo@~#+3^P3w_yuT0sngam)1`8nVadvYfh*5e zLH3diZK(>X-B&@AFIfdJP!;xUxk2OiP)q$@P`jWNGW#j|gpCgg zi4lw14z-`QFpOy$!1m;cJt_{4#p-0EQcA(rN9Y608!&?`4~(R?=tQrBt;m)?E!Kd; zfW!VU*YRH9_HE<=fyB6(?GIxPWd_;v4-Fr8nqm^_5$ExsyU{434o#=Y>dg`+3A2qZ z+om&+#sneMNLA=)*cpeLpemCX(qxLv2}xsqRp3IJ8D84n_GV=6CIjk;ghTcH1#YRj z=yP!@1^PaP2LbLM3aElR3fOg~Q-oX!mAUaB%rV*DiWpj=HD;1O= z*xyV40W(9!=NiYHQYtK5&i{3Dfrt#BpJ6+@YaQH%B~Nk13`c6X7{7x@$MJGa_Oh@w zhNH~9%Q3T8{~)S_1lWf$OqAc-{qNatOz+{B6i2-N$^5)h2HBf!$AN ziG8qbh($KGwVXeWPSm{|&0jJT**-jdPO;CkH6jk=Tbszh#!&Z)|I4FSiRxau?p>O8 z!i0z^n2(5-82{mI429UWzgm2@Z)2D~9^8a4>mQ?b=rAkjaOG><2T9V>30yo~64!t* zTBhF9@(#f)wzOSP%EatXClt?fRgK1}vtX92;1$5$Pjn*{OXAt>-5eE>hg+mp=mZ$6i1m@WML&F`x`QQ>9?5=U)r$`TPUm;aQ2*iU^CMUO7BS|I1+rs`QQ$#qu9%J8U z^1e?HP}^8$U6TohxCHnDM?*Y4#%c+YipannX1;uX7veW5E+L{Al^lwMh-1Sjvc-R9 zmE;5-9h=Ac!K2sYDXWM2jA!pu-g--+A;Zo!vsfR_f9g|6rZup9A4wkWeQ?H?=_M}n z0X7$6R%vLYD5)MohDaI&Twtq?EgfqUIm&>qmN;7vVEYrC54E)EbTAIx3Yp5{a9*=l zNWPD!k73IYF3IT6ahI`_OXtGZY0>r(g?nyF)6ZP1=EN?w?J~SotOLA{zOuEL^sf*| z!&#u!X4xiF3B)Ah)*Z>A-ljCN{tZzyF(`ZqS^R3+aBww#ND~3;dtM}93B}<}50y$L zJ^V*5M&N&xryp>~AuKH%P{nydrG+g!uCp#SMAJ)w#4|6Z*C!M^Wvwo~BnVWjlOM$Q zzl4bUcO4ZyP}cv`E82(XU*hq`)4_bO1UsNo|92jD9&c?L{r_~c16yFDgBM`8{;mHj zhHYtC5E`;jqf<`sTH2>%__pE`igbTO$8BeQlQF%16fua;d3be8l7&{Rf1w}tJ;g_K z{}?gV?BS5occ#2)gOfJ%-?N!+jR-Oy`Ui*G*m1+lSts3{?nyVaLUIsgQ{Slf)$LVy z73`YeQyMIPo6S#Y1@-X!3sSNE4=tv2Wu%xM93xKf99wX1g}Qs(KRoWe**U<1233cO(F5cF9-TmfyuTQ~zDL_Va z{N}KCM7{m$U?&Uo-@T)Qep|@y$;nX`W4^-wdh;61E;ozPu^B6CwWBwOCn=!g-pQN8 z{)=6#<@UbG18nd0y8CaE)d&V!!KR8I!r{p`>Zr^O-a?EF&>J{F&G;HlB#jLN?m)yV zd>}YTLWi|!af{b#X@0<4&A)MtIxS>{srP$0yb?`{m6pf~>&`{Q=J0$?YP)9=iBoBg z7tebyh;zEf-|TPqsRvA)j$vhS;S`%UD)% z)_c6SyPfXhtu!m3qT}tOHiIH1`a8SZt+>Dxd)YhL#Y+bZRJgYb5!|*rxOII<{{>4z z{_Sz}N;87ZvK{KC|7GtRD2(*9+{9k<6n;8&f2@cME>8_jR+lf5tB6aim!tq!1JT^F zmOOKH(4aL4LNo~v6C>`T_)pyZ{g+|`g4f79BNV0TlcU}Jmo01Op=exYySx1=JrOn{ zlD47Tl4z+>sV=7ief;lWyWhoidw9zUDxZSh+hcjo7xszv?)To3w7_Ep#|t1rzn4~};3(2#@nWRP$BWcOen9hoe=MNBF@`X9L8J;4SfB*2-+ zyW9QEB#KyDGb{K)on)bS`bnW9)5GDX^-N(JG9e# z(S@0_zz!cz zf#r9)x~Pi{{7&zv_aa#!Q$besX5e4$9X#)*4VO%b{qE~@*Jj{bEDdNe0Ivt$SxPqf zi5n7rStafv9a7v)*ka3mB_)yTt=|RIrUdYOqO8p zZEyPx)LxR7xT||_cWF_B|G-?`{xVsnMAO?7Py{yy^j5M!TnQQrk&5e`Ut=+oED={> zO0aG@KJ0BL3&qVxp+44j>4qn2VBr4CjA4>3kX;^SOB{9gGmM!nl3#4ZMX;dlcN;gG zq4%*Job1sg?yrHp`@G@65&l-h2)Wkn2>aQIidPR#wGK z$FAKs^q?*#1lga-TH+Z|D#d{@Rf~su3>mAuvS5`cs%&X1xfHava+X#SD`;T8dV-K%>|{*uOJ| z6L|0Misj@eV{BEn1P6gI;o7sn5q1-f;G#Id!gt})%?-q007Z1QDGWt+2#Q&uXIwk6 zjKqdhLqB}`*$|WnHf|bqW$XD6KIkf`gqm4GkLKVu(BCQ(BDj5Xa&TI6OMQKJQ6p0UE7P zd=rlM4$_h@-&IWGtDH+9S%0Sd~>IzBy8$wB5N#;*Xht zPE%nwJPE6|I1;WB_N!JXymCw6ho!xo^l-)t6hRO24s)A(<)%;t$G!jarkC3YiHq!K zEUcJY$lUI|-R>PW6S&$s&l~tLF}hUN8m}%?Va8V#%v$cLLO55Ldrr zNbhANOHe>m5`R1*KU8|hf0^p3vjr6);=tmf+(S^8A? z>dLrVu6fKN30^TYyQvq^6l%V_Y3$M@z^scd7620L)!pAefO(9K*tFP)y9lMS@~mo= zLFKIAWWmnnc#=&Lgf??Hm)9o}4wzLyrJ6W;kiapiYR&zM(pl57qD-~zm@e4dl<|R) z$v%%og$M6fn_CqHJ&t6R=@wPkOX;ez7D*aB9~JXBS_laF727JY0@elc3$@BpycW+b zA4(;^&IBx}dDw|JU``Hj(Z)eq1H?UMU=cm@b@!X&eq$|W%eAg3*YX@;jW-u8MUBNDf1{GVV+bwoJeA zXv77ZZ{L(ketpnyUYaGWn3)JN>>j0!%~%e!a7LPQS;-!MV21PK%13)V$eqJWL^ShF z;mZn-u0poV@aR~io1kjy_hg@x;BCNj5;~p_&n%yb+^}50>>&@%xOkEYqy0S!GTUQr@XE_@lU0t$L(N`C( z3XiTXDdAv^2Z4is+0$4Z9v#_D;?QiY3ohA_?0x@`Rhs(ybyAIaxzFLbn}Xq{}bLA!Te8k;e_&(}LUTBaM?2 zu~CF^lG=P^aS~iqNjkDPT_7J>T!R0tL>9;9sSn|8WS@HQipb(p<9#@CQ$?-nX}Vlh zLB9=~;)8@6Z$Ya{vXRB*<}WR>Sb0H8VW`{7k1USollBa0uqP?AL=i+!kg zsx-O2<@7EB&yq|X6H6u9z-Ha>F%!!fv!zECm+1eEL>9-*uZ&rYWvT^kylvqMWLFs3 zD)N!V*&=z#2(@j+riqA0#8Rkq9W2@_SSn zGe4e$Wegdsy0T!ED5`8J6>Kb*0$S}nYTr+S=Ks~mVx?sg=T3tz)By$gFoep1*C?`^ z6D=@Q1SmAdlHKR2#PA!9Gp?k$g=?Qr{KF!zk25aSn2j@zXLb-Z+-P0~C4K{O#(wgY z_u|cIEZ`|@ieNtiTxEG<;0mk1g&&m;>BG5*ePX5Jg8)K!YtBGrqJUs zNA9y=bkD*ZzTM4K^fb)kMZ3Yb6;;(k&-9-k^}1ggfTvN7JH3NLy33hc(1|L=4G?tC zC1-Y?MAhOV%l?fT@Sak`_*elBZkG6e;GybTf|392LB9aQNNBvx~v|8GPVt zdhFG6xe6mQKx>?yZPHkYcUmKL441}9T-O?>W7RZH;@8$V9h0YVGNZRf>ZeBQ?)xVO+5&M0-(UVN?6rE)H zFcYardiU-y9M@c<}-*f#S0WF1DarpLrK}ybxjN+dvL911hu4F** zQH(cR85z!>v>JQDEmO(!ZE1|N)^tYk_*q!Nk^8)%FQHHQ+F=o9L<) z(Zn`AVNNkNr!b91&Y>(uPx*XfhMMPhk+NJ1`8pRx?i$XRa8PnlL{*ZAal_KMBkt1D zw7yO{oVjSNVb_4AaFx|^a4}!q6&2f#86?&WNzFJ4U(OVJzP+)L=Ele)Qqr$Fp`n$- zXZcb`OWP8sq=6ygDNjnt`6s-b2H9STj9{iU{kDMRy0-UG5uP0NCKO?fuSX;W?ZLU zfur*R?dmA^M(au|d=F_S_u_T>r|WX9Oj~ZgO`d}eziEZT?b5lOgzzSchRAIF>b1Lu zC52ht#(67uwZ74!RdsIvJ6l~FA!Ep>GVPM%SMuVQw}4X47*n0ZYPM>2eJ?N2Y(o0$ zQ&H_8m+o)az3#@4R;_A*T*9e80rud=kqrK<>Tfgj=5~PUD$1h8-VM;coV=qX4K+aC%@;H z!IiOBTv*dmM6kU(f-Y@oM~Bkds@LUh$*N6~v<(oqstP+_{?d-v3iKs6cBwU$I|vIm z$K5iMX-O;gWMp&+O)f@0x_v93%X6?M?=D>ki5L(ORR5?#XFO zVVho74|is&N%wKRjgsnfbve&3Q5&9OIMR=X=IYG(Ihz>^!PPFj=~C~%2TN=?Q@)I# zt#6n|T#wxbLU*+$on z9xE98%xVUEu7w#(D_}xVVDb)Y4t=y%vU)7Q6CHEUp^CLy5|=(B%;%VwhK&w9EfJZV zdtMqsIuCs(WOBh$4n;JKMqx%wlGCdT&rTDi%F+F;DD&q5mST_w+^XMK$`F;EvJ3Zw zIt`VnGp&H{DyhN?sWMgD<|YLaT~C!M7n5u!^d00@Y*VK<8OptqB0V4@xc#bOdt^R% zl7jX@^U(X%cSO}-KQujcnG=IxTSg@pXtg4$S!c40N2I@g$~RLD*vVTxQVvgMWq>JS zN&b@UT+9GB_am>Z%tc>AKZLZJCO#iQv^vUAHa4=qvlInZx;} zj|`o$Ng`C%?=Yq82d?by`$(Bq5MqC~T&w1&t*T(^GfI9kdr@>|P@9i3S9#}-3R|Hs zrTY|P-NuNQrfG^~r!T7=7PMko(^S3TNJiCylw@au)M%d`&v96`W@TUm!)?&Y4Sq|* z%2OmaNbQ9g3Dz8K3-)vC5%-t*GjkEH_y;#sz@uG;X8(*=(i zL z?bF3n+1(5bk>~h|y~51KmX}B}Tkl4%y(Ki$Cm9+N1BUq2H-}ix?H|A|xO=d_6nzAw zbooM#xTLjF?vE665@xr3?HrlyD$3#gWC3-@?n=@eq1na9Vm7d^FuDUZQ~z6EzhV)? zrzOve!d~HBQaH=*ONFA5=P1cBao?0lPmVMX#uAq2dE|F-y;$KVJ+xdeg~I87W>_Mv zbrTL8!BoAfZ!~-j1pp7{_t_g|yL(@Ezd7z#SlkM8NgP@%&kqiAw;MDmp7)(MDP0j`+N5~J zf~ZOH{5hbi()zyL+=#XrPQka|dkI74tDM)%8rp0e)`g@QjM*I&gRIP_=E~gO+f2LC z(zO}aM%VG?YDoLk7OH~he7ky-F18viqPxF9AaN6{_J-g))60g5zCAdDu@y%x98Qx` zPqd`aL_OF{D%#S@qha(^uF7mgN^Sj?6?k)Ed+*>FH$paOfU-KoCM{1m##r{SW+;j+ z$7ZvF>kx!wcMiwzn6YYP8JZE3L#p@?bFn*kol>{&n}8=RJP5C56e6E_5iiM_WGPuF28l zbbRJ7w0_-v+kb=ZJnS98(R$e3KgI&Sc(xK+KV4$d>(QaAsdqQ zA+?w9-u$`fKeupj3b9`Z{b3o-<;53JI&7T?+siiy$m`?URJuX?pnGDG-p56szABH- z=4UH)#$=N!0c;T_Dpa}I>Vn%Wn^b8ER8$*5B&&9pLaJl)O=_>|;}EAMu)6vs^|q_J zuFJ9DJ2~oZ(|zq=mWWdqe9%XHepb4zhssowN9%+#E=O*_4gV& z#Lptl$U$K+a1Q%VI$IVsYbnX8LLGqb?&E!n#?XS?Z8Y@WlC*_+c6=Z2uN0e5^`w~v z3L(tfU-pj=yW71?jlq>l0ZjQy^!s>WrPwkR@V@GcBgF97Qc4j?V=&m!b&jqtV@*&l zV6m#!z?R%SK%}zG%2nun+|BAEc#Ctv>QWbrHLpA@eFsv^9bL_8K3Je4h|TaeLswNS z`FTVYxUDQ6G!N3L5teA z1+%6Rg^U;Ve{zmC!Ltv(4Sy^-+U7kz))pFH%nye17usP}CI2_Kb=GKN91U}8EA4*K85CS?)VSHm;Ra-r5 z5|_O&t^&p3H<^-sjx_$Ndt`!-Dsgz=1h&$}aamLfGLJ_^iPRxt&^)GuEfSBIy8kVY zN5@&zktDErTt0}R4iiD<@xXs`ydBTWOzQ+Tg)6!*El-jI%wf@ST-9gBl*>#L7ZuZQcTb8T?)r1HJxA-C|OkR?Vpj@giQm&hd&ItTB5gjHkNk>pl(ZN?_`8%v! zSH!Zx!P!2DarnEus&Nop4o7%ZS2Z3Bo59tvNd%U`P`})zK1r{3DJOXYS7n=`5(&ES zF0VZ*kj2C>iLx|T`ucYKECvOc!=tZ)sKz6ZDLe<=oqqDthdjbWkt}9+Ekq4Ez*XVU zw>&sZu|+FhMv8S7@W2JhF$p^F@%`cnO&_-#=^;|LEx1}^u^2yCNSh~y}MWMx-pl326ck8WzX8@b$1F=9(aL~0qVqGt_o za9x2TH6G8Jp7p&IV!e-Nyt6}VKv~7=OCTH(C>yB28X_cn=iuloGoTzt&SxoMe;>RK z)+pR_Qi2Y&^)iQB2bZH+NEt7|N(aWP;HOOq8aQS*N2V60g`hRO|ZcW``>p3#Ofuc**nc9ADihUOQxRh2FSNJkHk;IP#m z=j4q6)0adz;$miys;h|84YrC7gh9#1v!7!J8;zMj=0?fKpQ?)#TnmzH78PlLS*({P zEUa)#p#=8mvV$zK4lako?(ftP7Tk4^#D(*f_Aq1xH4K$3Plx-}MFbT%9Ap-czjB}k z4FP7c1Xm5zATqF7T;VMQHOMS*0-L*`Ad3PJiE`w{)7KPai+jKf7Iqu$zUZs#Un`LX z@a)rq6jC#pDzq>#t75lZEI+U~Cn!rCo8=k>oo}kGMPFp#h;LgHcR)>5{~R3b_{YB|CNqmT8?i+CHlM2@}|!S=EqF3R73W8b*VQ)A&0IOMFqK75}=qd}9H z_(Xfk42*}9)kQ-&C*Gum_sA6`K8n6SzIOfM8g5oK;9atOnEE%S?Tdz znKep)(3J~ius7PEAdK1l2|1BTOOHCb+|lzCEiRLn_wh}fZWPj1RMs~nb__cY%=+2Z z&1~gqk7`ZWPzv_$E5ry{wz?(;wcyGvdL*~Os>cJ`E>iNuXZCr9Ch)~G*%xWNpzuZd z{%6Eh4Xg3x?-!+oi)4y*8=;Q{tp?5ZOM~4@!IRm%l*}gKwhA&!O`|N}G45<(1C=k|FCE-=xMGg2aULD@4)+kh zE1`N~CzawJ%jdjZZE>?TXa)J@u$dg9bYP6FhW1oy##Dn=P?WGTb0ld~Qwc3wQ8`j4 zhbSF~Q$8G??QIR3Xj|%7cnvOlhCGkW9tp2QM4reJCq<{jD{vsF{7WoO@;K~zsAl-1 zv)A?bQrqb907gi2yW%leYE!xnb#8~bggZR_UDva=_xdNcT%u>#cUwLOp2b~)4{^G4 zoW-L@>GO=?!O7wI;JR4%=NAvI_6L`vZ#z$);ap_>vB-+z>eOQo;S)VDz(W^N|8zze?HuOk)V>)6+$a=v)oYS|T+Kt_~Ea29G8%WN&z;p%1caFth0D!#MU!oY@{Udjs#?R$a;+}ET&vEC3OY;5 z*2D=hkP8)aP@Iwkb2d;2%gN~i2#r9{#cRzOimHq*(~$)PaHFZws>B#a;_j!M}X6I9XQdEQ(Hq zMF@X3Zxi+QDawl?=uG*&y<~1s{Q1F~{T(`4{_0={de@%%@)$AzArjd<@Ge^>({2?= za1ML1@@v1x=M zbPalc=qE>`K-8d7EK?>bWS-KY8>u)*4r)UVTTwf`7u`2|C%lj4$^uZ|AB7L+>0 zfw^-K0^>f*0R8~TYJ8F-0c=&60!2~+5Iq`I4WH4G2Xto`43zs$fOzc=-4>jENC8`A zq+yY!K>hgyTe(m1U~)_WopSh%PV|QgOkr@KJCtAn)sX>)Qr{7X^B}Go7*2?QoU~Vg z{}G7ymRUrS5`kG)m<6Km2t>>oO}3;sFc(!XFzzz|@Q&+Mdd$f9r!5FYv&#|!s|iLE zq-Zb=fZsaHhRv_q;CP=&3cdH%Ki>@yo#X(^q4TRzfV>AiK{beA#My44SiQ1sfj}Up zt9m|rHAsoTSUlONcnj$g6|f60KGxx z5C%3G#UFQV2=uD^vUoVb25d_I@9WKDy>vFeMX_qu97I- zVvC*_URB=_h?{5XonQx|Uy~)Xl&htX+u(`cEV$o2G8R^;sD{X+F=kJ>w6}qRJep+~ z=Q6b>BUzK3n(0zBgOkN9Kb4EwoMbVf*S%D`8qlvYlZAQzTt7t{77w!X2tc2GGci%# zxB-~Sv3;Nuu;_j09WO2?-78m)IDXlVnVaUuw?9{W` zH0xj(c0r;8wx>T<`HY86ruo6#LqBw4KbTX=X%r-uE{$BxX9xA@smDd4*~V$uXXb_- zy*ZTSeks-BWQUGFsj{lR0}y`*ML^`+fg}!#a5wSvj1HcJh0LD)szBnal&u^G4k+{* z_+;oiiULSI=jm%8?^g<{Tr)}2FbqIp2{X%u%`z}JvZ0E{*;xcC=)PRsWM&JqrR9%6 zlo2R^1QK`JKo{i1GBD(wTKK1_PQuioQY0#-!Z1^Om#R|1l~L+vCRJl>a=CyFuu#C1 zR0iZ~ZTP%`cIiP86{_wVqY?vPbtkMKHVGjR`8+)?c8vxAe)+`{C0KlMid%ZQub@0- zhoR;|OqgCS;-bhEIH#3CUB$i~jNPS&MRYuN)H-(@$Hju@i<;PCRi{R5a)aV(1ra(r-J2e_fZFr~*1nI5mJTx|BsnPH!Ww6XK$bfH;*GS5(Tf1ziL+_m}$$vaOHU zgV+=g=HjDQu?ayte?H3vG@J77I|Q*&%|Jj9^cez}AY_Hbq=aC0Ls-GtBnxQ5j92lm zO(G-sIarcU>94vko$UjRIbS|C02?eic9`LU)D$?`+)QlF5D(Lp?VZX<)!-~_T|gVv zlx{+BnP&WUcyz?9kf~DwFdI0#>K+rb*`-IqR)Z7=hF79?kEJ)v`(8fFKfbjJ`@VPd zRnIY*S_g!tzkK;vTq^nIbx#sJYH##&3-t?F5m4}w6|iwhmly$iJ734zS|H~o(~E8T z?R-Y|!;Cw}N@6+YB3H3V1pZW~aO5`wAAwGEg_3Bkxf;69RC=~DsNpk2bCg#dk8 znGwe0GGsYR<5V6?!Xuv!z{S4`RqnG4faOKWGM4x|60uQkqPR1zR3U9$sbptHMMTM# z2-#gBes2#5lEB=NBxmpV&k#pwd#H-Tj6|XEM)Or)0k$~oUFV5n9xkrT=Y++SB_bf9 zDI#f3!~4$=i{G^th#*M8B>5Nxoe<%XumbXes|J{$0ZL7R^I{VNST167Trm?{xk``b z*hCXs$ED5hC@YSLT(#kNDpE2oV&AQCu#^x3S)wgI#f3JBnxIJw+|U-t=_{QOS7x`F zER5P?(y@MAnNF~H$`OC7VNwJr!F(3RFL_LKnQ_RvFJGF&^Q?hj$O+Oipf0)&bq4T3 zpT&9JF`vxI)#YN_QUv||z-m+0`5~SvL$}Fsw0#v}IL*44{XjF8Tps?2X zV^gDAJ`r$`>{kRD50|iL{%p|rZCeehc1m?}Y{ljBoZr~CRu{ChIGyK>Oq&mvo!jlQ zX?Bk!>VCO`20+bOXJ<6Mn%{wQe0k3}rPxR6r&6Nj90`=9IikSm(*oG|N6xk%ai))X ztOqml_<1ER6}FfMOhhqOSMMSZT|{FZxr42x7t=0^Sj=N}u+>UDPUf}2}$i~W= z>0?-Y1evhHeI`D_Oo|~?+4LC#xQIfj8{I)y*PF0puFz>of#6RA;Gzlnhf9>bT9QX9 zDH$tBq{VQVh`=N$2n;T3FX1u()?Tm54`aTns^dtl7?oQ#iFHHSewBq22hydS41Uw$ zd~sSDl!N&q&`tpA!uC?M%QiNb|MF{H%l7IY9>2x0}53SkQY{Hoo6NJ0o?SM3IbK0^Sn zrVU7-AvqN7b?@jUs}BEVarj6zZm$0{0OU0b;?{x$1q3seFi*_mL^j3-Xa0c)L~ET{ppNJLvpDAsG@@f~?; z$Eofh%gmorb>X}!6|s{nnUNyRvP-EVn~^Fc*j=z$P?^e06)ia%g2F*=wm3+$foA2> zCNovohM5J0C@~3K4l)bNh50EI+8f|p1p$&0L>(IIRLEi>fO;g}`%r;Mfa;Lht*l35B|!7Kl%He69dSn2C$YOXRDd=>+W?>9XI!EF25i|rUUpCtX%y5nFtCStZ$J9Yv1?qQA z%NPR{ngMibLh`lllN77`{8vy>sEs_;VS2fUM;Ddx89^bhWdtD59+G6GzW)j^xUDY9 z*E?M%#RawK?+`~A(ozS0IL%4l{M|2_e?srfp&1i3f65Oo>1>U=oSqJ{%5n50n%)A7Q4|PYT2)r2$r93@6gX2JxQlcS8Eky~V`s7G~l|PIor{lByl}dj&9i5FQqXKKX zqb{6N$Gzj?|8mz42eVPJx%ub61mB&F=zBBz?nK{P(f8x%`$_cuH2VH5`hFIDNAzt) z^le4-ZAJ8LMf7b&^le4-ZAJ8LMf7b&^le4-J&x#m9MShUqVI7;-{XkB#}R#xBl;dk z^gRyg>vY2UJDsrpPA9Ct(+TVEbi(>Oov{8+C#=8IiR%yhrxT4|CmO#_G=80E{5sM2 zb)xa>JaP2Wja`3Tna!_nhV$ZTHo7^T_UD7^_oMl&_?c&bjioZF-)`YzF+|^tewvT2 zC&h3&nazuIc^|%Y$cRq_@3)&Bpr{YxYK;^#Ur7Fz7c1s)(1XsCrz8}9#{Y3T>1TiG znvo!)qgZwO$W&d_1C+|DrIDj4OW@^052_0#VRgdRHSy#c9j(3G-HLXQ8Q8?AHv=Y(QwK?l zA3oqw0f-q>r-f$o!F)U{#*+(DMenB5iV ztpM8>|NN(cF24A@z@2~=kY@e$XnunUd^Wh4jsD6r{UiVPYRk;$}wwTlr`@ z-1Yl<@%zKu{x;oZcyPFVu+yWfyt+HxlWzZ2vHob~cmF&79zFu+Kz0u<9$noIr`MzY zaC$l#&K{mGul*Yv8&4lUE`Eo9KYRLw|J~@wHj8__SZsiX}F}l8nbXlFBk7vdCXmC2Z zh8X&voALE%M&x+lLJaa%htkw@czf{f@1x;-oy5{Mv2A~EI{o41YE29gxzBVo0Y{G~ z@9#nAK3XqMP#A^^fQ#AHXgEHDl(itmU~-De1it7V?mk>0DY$(;8vZaV=I0{?`F=1a zV`orYjPcL(OmNPM59j0Id2u=|Cet|;9$#Kvj4nqI&jYfI{`TODceiu2(AD{F1R*;r z2J`vo@@fu3sUj*ly&7FZ2}~zK#o@(>mLEVn0>l8~9zpOUqH>6vj_BP^)_WWB93 z1{W;3<|MN&FEMsB#QCbYf)Q24RaovR)~C!xCG>WL${EDCv+Bxrh>Mn688I&p`TWC_ zMtt%|@YHaAGq||8E#_#J=PAqC_ltKo^P)eVKBQ*v9(;X0xB^#UObSdojA=2Qpz!eK z8tCT4OWgA}m!s>4)dROXIh*!hj^?|Q;We}O;6j>w9d#~Gwf-33i}Yin8X3lgs%c>u zl!W2`qc%ZV|NnhFU#9Yh9)w=3(*K(qo1a1dKi%AT^5n@@=QHU4Cr`IF{;mIi2@@iv z|Njfm$)}aS(1_Fp#S()Enjo8*l0@*D%$8u7vudRcN`)4}N{`o%SFL@(CQ=%4%0hGIb!>+7)ZhClSLrmRLO=j8kvM#(YOVSt|_dp;tO zk9;yWs3*3kmsjJ95!KN9X*9fVyk@>!FG#NnN99-?fVj$lNv@TFy4~8INHvY$` zKQAsullSv;RPf_;d}=FraXqTUPV^XWCb=_FiFAtXq}2My763dgfSjC@q5UOT?%#F% zhI*hZ{|B>QR{nqXWV5pst^b}pecbuC{Qo7`1Y+O?WLPnP^tvRM6I+w-M-y6mV9D_A zwm2MI&qmje2D8(P{_x?|E!GPutwG^9X{}*$e!cbLAI6j6#m(ucST#NlYRkj(RV*~j zA4$*d@y;GX^8Zi&Rj<3_HH+~)_b;cX#XA1epWj04TD@a)XY0VQ%dPv?(*y28^O z^xrUlG`YDf`kaoX4O{W>Oiu@=pW~gAV`!Ao=XjrJXLRv7z1*tdQh3NuIK6^zyE|b7 z2iKqDC0ceLPOnl0WQ~bc9g3Vvoj32O#@9C&^Uv{^+v~xcf8x>bo$-&KuK zV%OpH!{?u|NpJfw{CDs8e0(W-_?G=RV;5GG`E`co=EcGVX-C1`(vycpv&i!F@ z`(b*G>0y4Pp#~S@0o6qRq#-_x;aGqhq*%AV(r^$|!}C7x#;*I{Y1k`rtiZLsZhoYp zXgc@D?HX5VhohFZb0mH=j> z|ADa4pZva0U#IjZqYrB^D@&LWVilAzgd)v;E81+* zvWYViw1PN>P{i49MVw7qHgWMJt)MalRpgd36y2q~$_9`hZIQqB921M0igt&fs@Z=~H?XjZh@gQ@lgiK?wZdSyEonA$)NDOF9XmN^6unnUs^W!Z#z#Zf_=1ya4J zk`$3Db=ibk?NvdhfG8qef+EqSEt^24IV)&%P>M{QrYP0P%O*BZ-WB93I7M)nsz?qq zDv53{B-@KeZ+TQS(E_RVsU+1nm0H=d1;j&W_*4+90TsbfvLZUlsU*DpkQ9ry)!J=! zO%=Gfr7ksYsLNP#J3Z^I$hwhC#2?1kwEP*XvYU$$f6$7BJ)YPc8vkh0uz2ZV@i~H# zIGqTXxlJiB5njM$O76)MvWE%t=Z_JrV%H?7&IFf4)f1$IjoeJgxhb|KVKzm50wuEb zYAwWK{oV8wOKQrne+&@uOkkJKJp4ymk)rLeaBcDSm44JcR)>krN2t+|?vJX2>o9Qp ztQAVk`<@!B8bvL!)ku7c%KTX9VKQ}nEPmurJi{5>yTTe4cxQCx_@g_!oeWDEV3O^N z!EELrQ!G*(ajcNx4)#sJu`Zuj4|l;~?+u4NO)Z3pwYt0pWd6dcxqI_omx9ZnJDKPd zb9A@>bCU`U1 zs-wYpW~)P!POfhaKC}iO*ha9_!UKS|!8IWOosCo{?ZW@yAZR}G_lxW4r749by}X#d z8(f(0WV80MyE}zP&%mH*Bm>MBT6H*>&CC~E7|*fa@q_tHdUm$qpc+qZOfx&rlw=@w z3q*tGzm~FLdrM&=ixLt8Ol!$@RA*7d_LLy5C#>&UU< zV0Ob%k%_q%dRMSD6{=CJ$H-W2S`U1?VI7u$;Q%qKJ`1XgOzb+e&6v03P%hTZzF9Q` zq-04{BaRLZF5;CTRsjF9gwxWcj(9s}2yBiFVViR~d#}e*RzP)Vxoe%Lv{)wjfM~noOk|s8@#5i~jWNY&J6EPH8w_iv?8(M`;?CjzFo{2k}%q zNBF|Ql`KJN-yXw#N`#n2Da8s*Y(8z|(_X**HaDWnklO$54KClE4x~8NySrz=CSO?Z z?u>_K4UPr-@yPs6Zr<--Wh49A_Vjh*R0*ijcK29pV72P@3!-zDuo&k&+zK>hlY|MxgMFeb+tPUr7UCt!ZJF3AfL@Dal7SGcw z#fNVEczijZI2f^9a04s2k5;KRrQ!@bXCVhg(>LR;u5mVk4(RfxL_`BgjTIw}Vj*eg zFQm}&I1V7f9O%=jF%JO8bYLaa(GWGaEUlbzQHP1o_`&3el^-?7EV#WYr$ibou~O<# z+ZLxf%5OZtG>V)~Tn=8#7#%4p9=%>G$Hjr6Uhdtu3P?a^PgY3yqT?bpKb(PqmzLMG1u=@Lx%BXsAraqfhmKYU0a;(lbk`@@Gm zPVNnG(7 zfc?NenjgG>+F-L0bKouWGsN}&W^iq^RdTu#a`9DJOd^fg&;6D1pxhVN_c3Avusdqw zta1lixcD({yud{R#*-ljZieTtaZDdbM8YM#Kwv^H&l|!52Oo)`gdCO>xJfvrYoa`o zz95U~z!cJ99j3i@RQRk?&$*%NW&g=^w{1WUZ^$^{w8gAaGn^^ z4?lc3?UR9Ai<1Deead`W*8pF26bobr8=PK;!*+K(`Kf*MS64?D?Q9TOXsfB_qytOt zC)4pFr&z1WaV9Z#ex@LWT|VC=qCuNY3ObnSDqXO&ob9plk`8xkxcMO167m$94(C4d zvX`lmKn)SURNyNs>fmxdqyt&USi?#S;c+$)%5%I0d{!ZQgymMNdfGPHFC)F$v@N$Y z^4;_%bb%U5>sYOVSzYVzfJ66}9t55zOV<1=IC6`VkfXntdyFmz!|N$-GCDiMjZOu5 zQ}~($n0({On10Ug({)DX!W#HQ5P1S;?ZXvp>5* zgJ&xTf1AU9vs5r9nqN9i7uLE<7feXFb*AbX1U(oy5}Uo|dF1pqaf~ml*oN@Z$Vtsy zT-pU2m>P?Yvp7vCu|w+wn`Kb-uM0Nk)r;?8TP4C3*CKvI58D%^G$i;y-O*4~RY|KO zQ$RH%jM8+CsY2x1nXvLT8^|>0-l{^!EW@y9kC$rl+pi7yy9$rr7?q;orl=bgf0`lc z`ZyS}N&i>T!=oLIkDe-i5Nfex2FYA3iEfjTsKvuwZPsH8j1;$MS;NK1?mA{RVly#T zVKi#N;iwt;15$XL0&j6)zRHtK1~J>&jLHu#UwP-_pxbu)Qo8%D-7JR^obcoY#-ele zuCz#OY)Kr8du(9|a#yP4Kt-M^t0PR;RnFINmexo_6%Uf*Zo)wA)3UUrF(YAk0@c=~ zb0lui$==E^ujqIq!n5B&2>59aEf$I70FacvXk!3B(bDI`uTK)+6}oHCTvaE$^I zua?XT-P5-BRenVmwHziF4P0u9WjODdYu6l!Jg%MOdNA_MvVEZYrH%u!KbCD2`MnJ< zdhc&uEXPV%LJF+b6z+9eF`93wM(JkQrm5l0O|}%OoE>NbjhEF0tZm!&LyBNVq#Ik) z8Ce`{B@!Pw^W6c@O@;%S*~FFyqTyB{cf$LTut_(kZCiHF7HJ6XhoxZql$gJJE7~@J zg0Ds0S?{tqunG?J&J9h4-dnELv(r*@XPv}xQQWQDmF5bXD#;~M&1mJZMa-BJG}$E% zJ6s*>nILpCR+sMDA2W~~c^)W$G-1>l-OaY^wUCIoD~+gbd^kkiQI8!=uhBT1J)qTu zX4v@I)TF`iG@!NYorq1P>sw)%SQUvN3U^w?cVNTelT_uTbe!&D;kn(ZF4ZHjgb}J6 zA9E6SshvS{C~mkF-En$-hY+?Fos#NPLJ@IuEr&=vzT;eqg7mD5*!=|$AP7+fXO+=!`$V z;Br@~(w3q4I)SCs+?toS%|!*vslCZ$vTIqh3nB6UYx)F%5ey6{Dwdg|EX0x{zihsB zTpJO-54p-mZXD}c$Abk-vvP)Lbe-l^%fFfxBeu#TDlxjH$o4s%4RT~tP;lN`!lxSo zotCbb2wqA9>WDW-nbv{>6kY?HLlXhTRr0?j&DK0fcY?ZIDe7`LTCtYc^s#`lqeI=O z#ynHaa*57yI3LY$Y!VteLan9U8gYvHH08e-m(WoH(Sl5)h!Jc8*bM-cnh-8Y;uoO3 zl3Q}!j^h|5$|-=i#M1G6OHoZSL-A9+ey~GoM1?)h=hy(082KE;w;JompJ!oeQxrka zEyZqc-4t`oWw|ZUeOogtbDa^1b;~n;-5(8!JtgBB0=D+@&nO*UP9;VtM??{goEAbc zpVb;)G{Q7n+O|v|$Z@S}%y8MJS#p*zR)nf`v-pURYfsuLXy3<+bTA(``t49cN0(Ys zlON=}O1f=6+ca|Yh*`w*2wiRD8xBa7tkWDxH2ch9sanz9WJ)bE;B+F&wTL2xO4RGn zlVHm{*(|?}PSo6WLba6-;VCQEE;XYN@@kH6Ifmu^ngB4{}VS!=~;j>;t)6AcFQ ziQAk9u?!0 zNHblo%lWXO<83~`=#)~yhZg-O9aIeDXSym9JesZsqCJhM*WTJwu7D&{#^l;d=xwA`L-tPs2bvQitu%{kwO;N+lh1A?MZvDX9~6V;{>r7glp zFEqqeGoTHz)T)xe^<-A}E=^__K8>BLPBt2g(dXe;F814v4?$x9n9ZeWV6AvR0ZdA^9m;@K zv?VCF<6FbBu^~`_sYJbO2YTB1TT{-{RL|Q1AG!>rXN9fPl632h$uz;qeit|6DYr>Z z;#k{&gr8@k;CN;=8<#pug?adTed3xuYK2Vm)7Q&KIjifV;pQ1wl5{0XR83~$aCpjB zbmY@@K$_3uIgsgU!+Wh4SsBXQ>BrKNCX(WsylT>j!Uh_-hNVn9=^w{kxi**+u_C=K zkf>GjRrVU!wxQ(=sm0fnSIkk(lCcNrWt}cT6YDBgJ>Zo*9TIISD%?mcxks9I2%m>= zlLtprjUo+t!A|Ttl`M`d*AYg~yA!Hq)YaX)j=Kl^nblH{>Pb@}j7<+OZBD~3O{j`$ zPgP|*mql53mXyV@^~vJnS69K7zr0FeS$=T6EIG5h`Ba)p9C&JuEPDFs0E8Ur4dNWE z%{G8dm&PQg-aiF7HueLfogph^N4JzQztmM1u4hQR_G zpW=ODLj?gnTDO@!Sfbt8o5^?x{J2^O$J-EhiMNc$6QZSmGr_>jMh}O@`Xh_mQ)_An zkXUtP>XEZ%bZ!|ln$B=EjpJPc}BT zijB?BHl95F_xtb5>HTUfn8gp4__wk>y}IS-x?*j3ujp)SK6}vFz-7oMK$Fg=^& z37Xkxa6LT7rP+hQq}Usc|2~?moSZ{a{#ShQIkDO1#@61w;-CLS-s|J-J{n$pQEdKsW8)sTd;3p++T3I_%68o4m~S!a zPo|K^y^4|aBsx4TC>waxaRw#|P0KQEw2HtJEZ*$H~)H=vHt@X%-51&G8b z8m^0a^Y!lj%dfXO=uhe?49V|pJ74eik6(3+)(mg zT_d(N?gbJfeKAVn>Yaq?gRKMvtOV4)88iU`W?*T68Ro{I-|y|bl(8ZF@rYZpeBG+q zY%0;E(f4#`*dk^;95F4C$7oEa23S<*aJy~CORqz)_lGomo_PHW0+ceTpoeFS+^+s? z{EyMvj5{=&-&vb&-k){yKv<-`pR8S#X1EhZnj-pLk~l1DAasb%+zeouW?3zmRSV3G zfUSNU&&Kb@Si;?|t)c?DsdV*T%w@iN)MRNtAZYrgB z%Yiv20{|;MPx$WsNpG*eeen8lcdvKUfEvS(QO^W3g8M#43(Xo!a;bwg8lE?msKRDt zY!QtT3Y-6aOT<@DWZP$^6ALdZyOl^vNU3O=dG6wj+G&uOA3--(=G(!|0@-Fc8v*lr zv84eS&b!9^x|@H3I?&`U>;mgi{zW!wyf5 zu-bT=bQu}P-Rkx#ZdkNd)17(*!F7{UvUrV5139DXvjNsfi=$mB+tW71m_GK?GFS2A zbbPu_Dptr?lb+-b#XLkhOFFxra0!NJo3Hq86HYf|jwaxpTCUm*pzys3cKw6Uo#C{nPCZiAZ%ZMo3{8IO*{?PTBL2$L;8%$7BiHM%y zzfJ3P1EDIWz9-Lwt@WN8Q`?F~#&38&xMntj`FnbEC7bqzq|VA!xH^T8?poudRHYxV zPg^Y(UH%rauHn@25GIbnxQaYeyl*=eKvjX*C#` zqvVR|e|^0B-#wC(MX|Qoc?Of%=q(4~0g5%3=!&h={F$B!`$10}7^sf~e zGCi|1^7eu`_18LLU7e?(!% z{fX_lJBTKTyInGx@OHwToU^pU4H?F!P_YIY*;E%B1zVx?&?70#K1Aw0z6b#h_Uj>n zlW!(7xCJ0=FQ$|C@}G0;2h87%1~6KrHxZDkxFgcT*Q57vy^pTx^$=eXkq{(M&Fkbe z^Dr8{Q>I>lujJb_y_sL#%%w4ic*M@G(cN@4P8*s95fSTAt{3>N(X^ut?ZbVL+|RT{ zj!%utb78I2JUk@ zML9RlrN0#4qs;fT`6V$vr|kBcolkErP7CZzQA9wl|E2w0KXKFojD=3riwxT_SJ%@a zZY1y1?dz&%8xIUNN8rzji#H!wQ~q>1S!`fT`Cp)a&Zb67uNR|>!4>UoT+T*A1U8B& zUoWuV0Y7$_HoJukyELirC)EF0Y{MH!R~+8Go~bIXMuQ(XWg%4H$IG!>GOiblt&}); z4{^@#H6qg&I<`a6>i4O30IYl}QkzFR5ncv%dLP>*$c| ze}#?~4_M66XR%Sx7-=8^@%jk-D`pnU3(%RvphjrJjOwlb#O6Fkqc`)yI2U zcAXXHI2d}S)y|PBsmloG>_X+A;5D&Tz0lU{6|u1_A*Ule(uWXYLl@8xj?B6v^TyS7vKsE5F3*cOuIyq}zE z84Y+|QB;jwuvzE#Q+O1`tcW|u%|j9k<$9fz$Qvbhv_6cD7)DHSMnYQ3R$?`nhdD9#*p#SYk2l zcEskO`pc3gqR{KYY){pb#G8fHG&uo1sg=%mCyAJ!w-767y4#+j?Um-;7IK_)zco6` zd}rh`{p0$siFI71;oJn$%kDvfPI7WF|M%#6 ziqjf+C>LD&4=m}gM-RAe_LcMM{(zhUxU2;GX46Rlul4kryxMS{e;DAn6b@~T;SE=g zgH!R5|06)n_zGaM9HYfWwMMypjtf?53~NGJ;x5QITXulzjA+9-{BlU9)ts-)&_Hb2v? zC&7{EDY}y`%@Rq%Akl4UyKJGkzt~vXNs}V3Jf@DYCaTbPsSI+|*DX|^>eaHEOY~|J z!d+8pHC)_|CVoRlu~|i%xr+(G3C0g-!yihzY@x~A$O4ZEGc&pgVdY+JI>luz-C~Ld zz2;c736bdu)okJ~(-H_p)URX;pu?)2q-kzw)!}8Xa5Jl|kRUcm3W+C+cw)+uq6z;r zX^v}PE74&l!QyrVmF&WNx5GXTwe}N4u zn63|VyF-MlKf^(i!fY2941X0*7zO~bKDZ{uobKnUO=Z9?BuJgWKsCW7PH|(`2s39K z!0_%C55l-qjv3*z{)}wx$1%b|1{ZXY%#@c98El~u0+ctQImO_|!T5p#MGZy@K5>YA zaXJTW$mimdo6C1NMvoS-UgN#Fm}LIuNKureMx!NkYk`oCqNBm^T)M_rbar!bA#7tx zrV0)a^>=Y0Ma{`?>bR@H=_&n7(Jhyw`2hFs3?8n0Bw@g+fX9V4?Ch={Gc9qIiwG5( z={RK<NELjVoMalLax~7=#Ohgs&Nso8!JOY`z4JR!$=!gNx2g2(PWt5yDLnK#YX+ z9QIcM7d2(QV5n&na!Ksp`w35Vk7=bcxNrnzU5R$4VjGbdAO} z;x#etsYAU;w??-zpp4w0NKG`{OqKrm4WhuNv;GyL!H8A_;^N@yk2ozXQ;O5w2!W#q zbWZ_2)@T6c=o3ULO5|IL093}Bu}S?t1jy7&)VfNW*XagGRjON!2Fr@sHj^4-HbQNj z9CtHK+zc zq`Et9I#o?gKOMch!Oh9%XbxuLWH8HfOvLSfVPQMNWm~i9aLiJSqwU=FAjbK?X#Y5K zg2QkcC-=vveF&9^7o=N|C@}c%;Qwdu?c3TqlC<&pn@@4#T*(NBclyIfecl8%&g|^-ELUPl=X6(BS65e8S65Y2(Bw5N zy%;J7s@)aaRaZl{rA=@>Uw5bN-c=auo3oY^9~niEnWX;xP=e}s@)ib5QI|K@4EoHA$Dh}@H8s3OXfga{kipLwj}fNr z>8LdwRd(VnJiI$E_Ea1yX9t4jP!b_?2@u}^UIWDK0!=`C4roj_1mmSz&2YfS?6Uxk7N(;Ds0b&NYTi<%2g1m=E4{!19g?SR`5zGw&#hG!rf9g2tc#uLv#-=JoKxa5?GX zU=-nnQY78AD5is}^3Ez{ka?dgAa5xY_D1yIztuK5Y&Ck&Y$z2h-F&;J-5~@G6emhN zdpyBDC@&+0Mv+cXNeh3dr#Ko$P%*U}qF<=vR%KAQ)mM>W!^)sNxZ5jZaA_Q&sQenqh&9#bjEFK zPKF-3Hg+Ylhy>cuO9m++CHoAoB%?*UGPsbRo zc}!I|9Dk`WVgwy%3&XC}pGzVFAF5q}Saj_^?t!c`04~)(lMv)zpAd<2VF@|XQ*%WPtvISRF3xEx&%7dFoYa%_NG zgbGM7$%I^fyYF6aA~oJI)8XZ04(LXuG>mBqHqn_b=zK`a21w%SKNKtYDr?M}kk9oW zXf9$yoHWAj#2X%RT#`~Gg+&7vi*yfRzCb7$v%8~&#yt*PALoh3+^691GjIf$8mgXt z**tc)>4xc?pb!uxg{DO;(m7xgr}$pY`HP}lz*sreScWs787MjRfaT#wFvdmy{Jf88 z2ph`rskWh*jZ#onnm5*p)daaHdI!}yScetyn$!Z~39q#gH;=~Ut%uVfo)1+@}; z7mJHqP<#kkHU7{CCd38}TnsUfckOktrSm>S4X2b8kH||P0$N%{OUFZ0LrfL`)6M@=&rmgv02_tG&^Os^y(iP#~Zea+z@CCO`i`> zMSmonJHk&j$5(^lhoab{x?Q`@uuD3~PDnCi$swGO5v+(~4ID3+t{HhhZ3AG_2x`E2 zw|`OOKbUFg*4`ctu%BZ*VEkiKNK_4m1}S0h;do-)ohKohS^j(EZH0vp_MJ&ivg40P z;enK(mxJ?RSB6B65~CCl*@{^3?g>o3Dbv|<;qoOxL9E~|4xwQxirk?6q5n+dW5UGh zI!{nSa_x94~5VRRM9%d#7Cl720B( zF=TlXp)YVpG*%H)(!MTg;t{{vGUCU|6}r;zspUR}e^Q>QoNb-1UdZudFENg$(y8TrFfj z;!0cuRa+8ZBvnqAU*wE9(#}r)T`eW_b~z8F#Oy$DHaqJL(C+Y;z7_+j^kdwGp(dd( zU}1@HU_i#Y54#T}d?zHOUko*t&N@r;>G=}iKPg2{AjHkF zug~n0-9;y=*hk^%BjiUH#f$(pP-!e|^tuSg6LvZQHLKdhwLJ(0u*xcXavntowah%Y zTp~6#TW&OBVFMa}O2;-y+7OO=%lw59g3KG}=<;Kh`%*J@w?t!9hsS3S>6U0{xIzkv zK$L&Z7)HKsoHtRVxYe;c9(O+mkrdgw>Z((nMK$adJWc~^H)4?-j)`@E#b@Dg12Gpn z9EK%WP%91Mc&FO$NRl{!RZ4sg7UtgsTZbEJUE;>(Ziq}Q-{dcqI0Q6~Mi{OriDHf~ z7~IAdhWz1ZlINQ&zyEcTUB*@{z>fTOaaf0iy=PF}HIqFbsG{6Q&w7Jj+VCe~M$fxQ zA9E52YX{H^$~_aZhFMa}xVcWhlo4oZ@k4Af_R?rQqw!KnZBy%*F$#fH{QzRh=cYxz z%xo^P(~cCrU)w7JB=KVt(a*82sX$w3pN&asDugRE;d8k%g%f~<4(La<7gRqFkXfOF zSD0{}?8CS_f)yUBWKgIxYRMBU$b)bs0Oyy*;mKmOf+8Ui5;DLvYOXo5R`Dtdn(8{t z{bgB%TGU=S*^$v`di?k?H#a;`KErcdzGCTzM$m=P5K6)3)urjJ>%|X|j7y>tAsFF` zu=%Ap)Hk2oHXzpFusAi1f1uc}wqlb2VJwLRwtxJX#UQhAiSu8SGRU`0T0|7FMbTX` z35xL$6s#4<6r8Z)gIT!d4E}jz7wA@p+${Qi5|XheUz(tS^QsFj2^$F7NI#~z$v!PA zgX8ErPep9tUF{SIcv$aQ;=00vV681&3^XphjRrOh7&Dj=Uj}iWm%ysAfAA_eUSn}G`;3`Qcud@hwiOKQ zqNT-wbwvQ&+QPMn4WhuZ6@YaWH(R2`Np^ZZJOlzCWsNB#{Y8J%ovTd$?$!$y1*8XuU=jBs|2M z1eMFFu9u0Zs37c4OcEN|3TYxo=Qy2wqAX9@!BfCfMkO9aOs40ytaB)IIDoSb`p5?t zi33f*^dDIqg~|6xIW_H*#7f%_AY3UnLc03?$q5!){PCMzeOiH;xAd(e5U)v1Vdlk5 zOa9hAAov_`ec`(f(+zm_g$&ePhZu{Z;~MHu8f&a97|d{$92`6`DPYOOi84lqhi0&S zF}6XD6{C-B_`kY(iZhTR4-naz04^}`ZUtcSp*wN{>7x#Vz*(8I);nxdm`N?$v@<zYr#V!xD?ZTCkF7YlZD6_Gy*{YFDN$U6JNf9NAPKyOrIRweM+Sof)wg& zqNYL?9Ke6sx`YBZZzvd@q$MY~)Kxw^=9cRu^0aTYG9b5Q7f9vC%Nao*b+` z{Wc2&0ooQO;FE(jyse!R&LC78IXt85`$NoH0uQ;?%7J%N>#u6$Fwx%fF;J)!j;(ksaZ zhz?oY^TchD&UO>0M(!6YM0F1ds@1;!7gTNSF$?1t^zHxa);fqZQlYWOh21~YK8yH* z|2e1r-zjo&ulNUeB+6;eH;lMw8jF-X%(RyrLDQt`!N3mOaq0DclgOI#y|5wW6PbR^CpRkr7id)Tmh476)^*RzQ?CM}hXj>g$2#lkiudyXr3k65+ zW^^*+qT!N$=KOeqom47DzRi{Mxc0YlEV7M_>}rW9n&yE`mCbe{Cub^!G6$nYc6d2n6M&{qA-`oVkD~d(( z&Mje^f=Pr}6D%6JXw80~eXB}ABs`A4nUXqcz5Z>qo4PY45uQqh;4CQ%XIHNy>JTwyZ*0j32lxrlLmSy|3y|4i+-Wn#OJF4XT#5thM-HT0Ne< z+~%lo3WE5ckL7OXRV2O1nXRCTUbVOYOcbPVqpKZfh^7qeH#84VG^G$wnor|G@5^I% zbJXJM59|!LB{bt(L6LM~csl#J1u1Yly~r42!d|w#;orrFEw&DQg@0RU~F`O>mnXR7496 zv$-^(AGjlvPpM??EM<3>8#J}+1Z!;{zo>w%Z=qh$Hk747>7OWY8?d0!tFkmSl)WC~ zIst6^zF>o;$q4%#=&q2Y>EV1hME%YG{?$`pX;}^fNL`ob+YRmj%k@=0`RU5a%ESBj zv)}OZfqky5-P3P8(qFcE@4@QI{RgXS41F?T zIHNv_ot(^g@BLsW@t4gg`7iZq=J*HJSUS5E&Y;JGdp6$H@m~dRfGKSJ@84g&x0bD} ztvp;={Y|!Vt5$DV`Tz0p$NKptJ#^-t4@V!7O8jh^wT|YqwUyOJi)$-u>kHZIkk>nV z3wuy^d~~*uZFLa_{HoXgb8j$r0GlgyUuwvRBR-kJ2L|U2ABUF;7G~l)EYN)f55uDg zvFd~4Wo&0Jh7kH6`QUPJj36#((NKiP7a^Q1d%bgz;S{9<1h|;ydFMllX zh($huiC5NWYT_sT^WNN@S3A$QclWmuI5w3sF&-iWUA4K(4){PFUz+=pL|laF>g&`--`BO4N=Tp2qkoPC&EdB{6KZY(vOGcm-gidnH(b_*wLK(mU%!wSvtFuA2B8G z#<(Gk??~{hg%hf+?Pu>^K3yp!kAh#QPUV}co7}LIcfX#{`0pxZw|J10Vjjg%~$z5r0wqux;=v4V^11D zMUTZoZ#-HMb7pWvyDk10@eZeyJI_I+GU93R*batsWY-E#gno|Wk2|~Th!~rVH`u!U zZhyP|=HQ37+nZba`OrLZuuEr8)5h*tWbyeCA^dOLhf1@A=jZQa6Qva)Fcy@_i};^HdFylWgZ^ST)!3q(GlotH^IR zYsrb6+~8fIhq6{gR6rWLe7*rbr~Mdmdw8*QR3?T!x3(~P{_|*h)y7sEAJwr)YP3J# z@@o$I&8v-j%p}q7pVZdPX16&(Djx-hSK3p)$Kq4^b65v1K_DDi(`%Bf>cs|_ZcVtC zYRJS@s-|Z&N9gcqu2ch=O}xBFl)puzV`NkA^>}@xoALXDb0*o#3nf@i&Mr?*km(?Q z$sys0l8zWp7aHi7M1->RScCyhvTOlKR&1WC_x9uh-jd(Xs%xwS2uj=Il+$!-TO(`m{m z9+nwKHkLRv%P)ZC@`^(fzy4F4Ql5T}1%vGi_J3olk`xSukp~*Iv-4I%q5}5(I8Ny) zzJpKkp-B?Dbm)vrR)Pjl5e(p9a#-3+b@lpx0FZ}=3jW6hxHwZi!kVoi5uSGq1PL1Q z4uzl+@{6#9_X$S|7tHdD9yu!`tdBfhl}msnCo)nbaWV6-BsAtQKOJPAV>Q2%!Y~!n zBIO)XRa+hxoc^Tv&uXhYIe@?B7a@m9QJOy}qF8)+*H~D%m*59TQkq04f7YF}8A@R2 z1-SL)Jk2`Xzm=Rl6t01)^f7v0OXB$A>y_$Q|g%r+2btl6$MHF!tTVn5gGt^KPi=6Cg+t+ z$oL{tgRx1XSvioYoW@jkCL5Ux8LO~mMQcur9FWDdHry)=0OYxR!Co=wVgo(1&#}KLBI)eF z3Xre=AXhUYf$@q6dEXZ-tQ(qGP3c8p;$)PRexdc9y1*aASG6WzWU+{j#Se&yj zmAd5iJD%rq@d93w)s1+_f{C{TBgb(BpidJ&X;0`0?aB*RJC;J>)VKkJ6gT3PZ%mTh zb6AgE|IQ!6iqb_6K)Y4NLK?I97Fn={y2ZoxA$LXgfSsP%Gy=7PX3NjWr|C^4&dgrR zBgAYe^HjUZWYP0{`q;N-LJ6pZ2rvn_^3#_Lu|-o`*MN0mkRyta$s$$E0jaTHYLo8n<5zzLZB45q;OjdV3b}1R~B2)uK5vo$|%EZ zqUwBFU0t~0{V}qm(MA541`H~IV$0+pdNj8IBn zFluJ>E6IldEpNwE=bWtECV8nFH)N4>G%A30)Rwp`g{FilWY2h}&{^Z^bH$^c@pgTa$Upy+)H6Q25sU{4I(>q7EW`#>7bj&~8{eZAwuzwfF z6|z+3Es5c#$T$X$s?No{T*A^tY;wszW4cH{vdckgCt9i*$=jzr#IW{{%BFxQ%}7mW zaNE(iNE36!MH+T-kf-R47amwc(3?tZrolq&3oa=t%bBVdnHfEt%JzW)CjZMCqmhOo zAC?)oUSX}JSE6zfYsBFyf?H>y{(%EjNBlpj#prUttFbB=RTg5QA10uFfUEhL&xoHd zdyMPE6)g) zG_om-*JV7!b@1T z4F~ce(2qPKUQ5MLU`iiWq_}mrNY7M>2t9nO_RfYIOWT)h!zUI8kfKp-7zZ)W(4d9} z#Zt~^m4{ZlN@plRFzWlLmWQRtuk{2b^GB;-Xf{lO!uZtBe8g|{FRBffAcfgN10U_0 zn7}ac`NA=oEAJ%{oNGHsUuiNtC`=7bJS+xMbY(;5QtmWI*>p2fsK+u~RPxG_uH@Dr zT~#Ep+v?l_77p|%oh_Qa`5s9>!}b8Ugs(mXgJDpha?JyY%B$n)Q%>HG;vOwIX~PY5 z!dy$F%?)ZX6S3>jZOdj=?q_x02yE>hDs4~%DQv155U<(7kkcAUgRb3ZqE>r)0*2*h zE>oR@8?aZMRMpFOIkRA5r4LKP4b?)h+8r@z4R`5zJDBk87tq!h;0=DeaEpgT$r1Ks z?~(iIL$F8G7jPL9ssh@0+6YZ=13b+H?TP}ju4v?v%(Q?qi&UuIq<7S61Rzmr_U}+^ z7S)=LR)!QAV?p666KxeEm%}B+rv`y*Vbh9VnfvwNW53IK73vq%s(AWS>3P~SDQ3On zhVFyixlM2AKc^5>mWUBfHE%!*;2C!parxpA=q3COvGL8PNznPpu(p+K)a&g?&=D$5 zNO6`{ps<9idD1)Lp)aVGEI)a*p!mjP$2zW&1K+zQpP zFr6QbK3d*PIc^tg;|8NxpZ>$47iD4z4y{Y*0zAS|@@8-xHFe5+blwYm>HPuPHN^&% zauHEll<^kz%#$cO60N2d5s_Gf3D!Y4EslUooCN?Oyp_WA^E{(i^BJ4~ko5dkS8mZI z${da8m-KS?-E(>*{q1kbL+EaU)6^pg{lT>#{r9+7r-hgS{-N&SW&eB%hD3Hz1i7}p z`U>wB6lqtyrLS1AxhfCgS+jReudN)%+~J81NYzYFYbz^jujbWaeKR$22+T499 zucdbUX^FtBO6ti~=^y&}(@){)pZ=7Vt#n9b?I}x^ovi|tNV}_o>sAf8$S=WTu&t9< zr+CDr@Kn%OV$HeRd4$eo*|x4vJL09k*!wERADhe$r`HL52F~qPoDNEEB0&IjCmbOh z@o?BK%*O37+b=fXy*i*11tL9RiQqK^@->n-VfPR@g(uvox~hpYeH4RN2X2T&t4o0V z0z!6#V%)Ljdi)2%z;6TPG8q}dOSM*Ub(@Qv zz(L!)d#|@&rvTvkMkiP(QkmG6);a0D~IZa6G;oF-DbWES|%aHp7VV zdhtcxFP=lSs;$*~Rj50=f82Z(fSNbXN98FTnmq@;#r=T4LzjE0Pr&3w#l&hblX} zI|ug+kt-zHNd7OEdSs=NIt$77a_Q9vD()p%Hqoi#>YA|k@~R!m>qoi#+I^w#<*jz8V85hVgd{n1jK>uv@R9|)(!gLoXONy!Ns$R} z+?Q~L9Hzn6u7|?}#(tgGq(JnI;KPPgp41F4$mvqykh5CK8$8HV7I$@r^gWd3ct~ha zUdAGy6>5EZwXhPdaJ|C9Or&-uS?3BVsxcEkz_Lgm`VT|gD7iu*&$e&{49rfY0`n!; zL@C;A85)xS;pDdsKn1r%<*4xVNv+mZhNb^1Tg+Cm(j(2r3Y03ucpFMYM}oo5k$cC# zpV6RpEU-GddLOktJ*Vf0Wyb(^T=TFN2r^cSRxH7+3Pd2oif4)cS~=?TqwE{Q!+;f# z-Q;!&=2<2Nos^KweKJWJHP*fy<$$xvUv7tN-oQn7@*ep<@(zKn><$&Lq?_Nusy=z| z^hQv<&Rx=hN0o#IlfPu&d5v$gf2b;fGM@$|j3*t*NtTyij+o5f&A(b@8|6(A4tEv} zZb~|q{Z}F$ShX-|3bX?$ZbC8?1kg=W|3Ow;k;7LLR?29J6eHpfUg$`+Ea1D zX-Oo1CddcgOOlphRC!xw9FZcWa#CSB#N22|@f0r^ z(d~A3=dB@*tZ&c@Ejf8+G!%!VsT~@nO3fhHsu}ScVqSy3ycL-4or@AQ{31mnqEu;M z;QXcAKbO*l4ceC!Cv6r`2q(t;fp`@C%iPdw8lIeYPXQ*( zYZK9!I#6!QsKc6Mt=GPmMTS^qPa*U<69fJb@q9iHA*=e5^TBim{P*G17KK38Q5lh? z10hMRjSZ|-rYrq?iQ{;?rce@r zu_ee6%TN=#GN?GYjHzKzS#}Fbj^si{*c;v${~E)XTr>{J#jYS%;v z{RSvN!cs;Vf&o>$B!@@ykLsw*HZeqOJ82!d;h;92V_SiG40+AnZ zDxAl?-exyHvn9ObZa+9ank^n9p`#!RI?`7Qpwj%No5!MVverX|2;s_l+elg-^$;{| zUUj~&gbN*+@-}igoZPytMh1@e$Fq5HS zycQ8abLG8cM1f_N40u&NPL!%q_Fuw9Z6uWp`&-+o-rxlL)|ROf>!91=kSlhVF$p@^ zoA5AK?`IyPHjc6u5GbNFbL}&nz8!=GHlcX-W^-$62bvn6nnr3I%X-kF`o~vTBZ*d> z7A%oeGit2$#Gt?2-fwU1yxo3&pu#SLI68|@*=q|QbMJ|tQ1MSevE8?WQLL^=M*yVq z==)&a#8USPmo4yac5L-vPSK&@1bgd`bn*&MQGNF=yTASN^)~cVb~S7DWrV@zfv3&k z6c)0)RB&FK2!!!6)6xJg*#`y@TH9~JOh3_{4kIi311Mh2yu0|+N?GKPHowq=kgM1pn___FH)XBl zRB^t=fJH2HMd6uaBg_oRp<$TR&Y0b~UMhii>kx~N8xaego^QEWr?%#Neu&W9!KqvH zVX6b|Y7n==B&x=o1TGGGLUw|PeMq>)zxu>Z`9?JwL~*QTsZx0s+9J7PpIDijL@($x znn-o6l!JZ1x)O`=+Q3uV0t0dJ73q8@g?+LYxqeg)tCRkClDbnH6N2aXB_~aMEI(-o z%M@Lk05Vyq8n^PS5YY6SM4PB4kf2I=iW&-`_u^o*T3-Lax#LI>Ybls@Yu8Jahh#6* z3+!l35>Xe!Di!4IOBlx~%QTEGZ^ey#=62&2{39T$;6#iIw~ofJyu$^ACUs<_fxvTr z99Uw|6)s<8i#8q;d|+Q6O?w90NK}@>i>iN2L8Yi6*a#xrZ8{D_qy>}v6;AvB=O=b3 z3~2rm5HD!GhiZRA#9MrNl|yKlnN~h1 zB4$=_cNKdjWmv&Y&tw3VbSNJ5s375&&Vjr)3dZH@#-O2`)r{p^>RjM}Zv{ZIFpB>O z^Y2w9DOh|&DePxS@LBY8cC=BZh>yce5-&b|&kLiV!6hP+^r(#g<;2`#=&mc-$(^{f z0Rvd*jd9Yyf*$S;gSy>O+0>}^D_j`U^XU8%2Rq?NGL+4Zk-vl|2H|K(4mM-hSdO{U zAsj>luS->sHfuIt8K&-Oc^!M@vPJ~WIm$)}OArW??#05YEQCY?Cuk#5{@%_g5~+}{ zp@k{x#UX%=U2Kh*zyy^H(Y`H8*f7;-T-^Li$R&-r|8#)a&~|0H<$-7}$3#pA5gFv* zjAk2mbva^glM*EWz{rY5@m+NGph&7BH(}lc#5|WxTrzn9_a>&qK>)&e7i`!1R!Xly z$03$+_f^sm?6%oI)(!8XU;@P8s4J6D8O1hj$2Y_?0=gZdjwjZ+A7~EhHW1bD%t!XD0D~h|!x7sh>Zg0a@0<=t_G47b)o`D|OqX(09>swaDn!(l=61$W-6ee}b%WMrep7R>@ z*&IDRF$O1RCj15~&Ge)&wOJrch56R>gbcZIwPIsEnHxD-iPAXb8iN(uL5oPkjkvh+@cy)hWlu#xknml71t0+17S zI7Uktj{Qc9(;+<=;X}c@t^Bm2g$*G$0G(7Uc955pmT)Z6Oce(EoLQBZprWH_)Lud) z7F(=Xy$V_h4Wrjdc67eHrRD^!wR_vlRYz!QDiB3RIz>Hft9lF?#}nPV-U z@>=I{Y9jXvYHRRbj&E_4NCx2OXxPiDRAC%r17CzpH3ShFp@%^R!(0K67=}*6arWWz zBg97MnkE<@d@yrp;j%D2SM=-gtU={@Cx>NYWB1)FT%+kj6%OYpqE;V3gr6YIDz@CE z0bb4?z2j2dm&~y7^rPm#=2(~pV&C(hy!Kss-hd^#UqcYrtJJw?tN&RDLKjOdtA_PSRk(O+ajCf;i+>^)kcL^EiU z{49u6K3IGzjFxa)iq*S`vJ#pI^mpJM=IU>)soFNcAy6m#1HggIcFx4eb$3+?v`A_|8)SIB2#hEBv( zhXmc&E_!mf3>Tl{)Cg-Al7rH#H@JKtvgdr*M~sH~D*)_VlzcRcUR=UH(K}wsUNiXu zLbi^PaDoR(bXSJukDqmL!4M4q3mONwGsz} zS|Y?8{X2qSJcXmeWR8!62^d(R7<#4mY!-GIB1IoSnuUeef8n0IjSNrcm*!qW%n~gu z7I3&Q-?Uy(G1v%j(cTW7`p`Q^NMRX`Inw74SsK*u)@T(ypT|LOYqX|sXbR6pYaKs( zqmtp6(IAb2}JgZZ$&^Z7u~^+y=}PJ?{D- zpe+LEk*W9=Ryb_dkb?k zoskM6x4GER)dulImxoN63>tkHqEk9}p``>_-*Mg2u_|@gCtUeAzF3$eBk5okyB?Z* z;Z%g~V_ZW2X;jznga@D(wZ6%8Y3@f_X3RoEWX^jh(?whXY0fdmL>zF^7il0B4I+{$ zO~;2mXvs*V?ic}@LJSU!bf-B)X5Q>YA1>(UN@4+a!GtktBNPe4oMDqCY3_Ui7yL_D z62#x*-Xg}CI)ExMFNk~QoPaLFF&G1Q<5pnE1B@HqPI}1aLEX1AK(>^QJC1-9;AgGK zWD2hOaIJ#0Kv%~^ey-Dczm_uzd{r;c(NTn+A{@1a={OH0rWjdNXCuh4JLsJo^e>Wl zU+ywR1tBaQF!W)4nc!mjXuq??!;f7;l&Ssvxv(hK7aXC%m_5#LCg`V zkr?3>8!)qo$Re|XYP(|K{g?rmoua)ADr7Y0M#CHi8F`Ce}7qY}e9C~E{ zc*qrC&i}0Q+~g-tUDV8XhCrSE$2Eu@o)aU7~8sVku6>C6_35FAh zj(;^ofmwGmkU70)gxHwrTlEQ37DO;zQg*)C;75jQu63^zc&ouCi zAEHvD6CoH>M9KKm%AXd(7p}p2w)!W{uD~{{smfio=(vQX z$?#5l63bzxyIIDHM)Yl1G8-2Z=lcAfL1;`lgC*g(W%W4wA#8GhWNb;2h!k<*Gq|nN z#U6~dz59G`Yg-o0S3CO$cqi4$Rk}q&pjJ7=b zlGRnVuB8O35DiYQg?5ja^Y%8hxWXX1a1w>eARWN0d5krFa~ zXFK&f)njuh zD_7tAay`qv~D~OmWBwm{Xeu{>}k16jB6B^R>T+=cQR6nf}7G5FAEBTf<7-_+q$1fVEO;V#Bo(jp1>tm56{C_KD3! z;@cDUiKQ+S?Y8O5U$X}($#2#fOcz()xIlD#PquW_c|7NvI11?$fBO#Wq4{+*k5aVP zTclD<;#3Am`O-#0u3XTi&52wA6z=di*1bm|3qlDuOs*cxR2bL=6kO2h-+cC;m?d;o zR3I>a*o8qYG>BLxJZ{G5V&Pl1IIn{(9NEY83-t{{J2}RE*lfd^{LaJqzSlEMRE9X+ zM$Q4U2Tu2okqzP&lCs9=f=&T=yc)^Ao8X{C!*4oGano$yqCy#J>61c<6vdC2okB0P z`03jc{x$!r0E(5u3Q82}H#Mq^_8mMh%`bG2LxqFL-#hjYuSlYUFwI?e@G4H?86C&n zL@mwn$oJuFB-|#Ww~$)8Eu)?!&SQpt5v9HTge>mGiBr7T8mh+cB$ClDFGv!j4BF?n zqy#c_^ar%+>!pyZCGwYAA|Xj$P|v($7oOdLH9=RFeJS{*B{(W@Vg|ott?rgI@dc&* z6$~>N9&N%`AAXssKivb&I6SBEF}AKiQS;CS_@cdvK<@OST| zqvnOz9&&iS@bB&&uiX3H;o<7~`s(Ux@335W9a%%5!qs&KiJn4do+I<&B>NF2e%K7s zo-iR7_jWiHK=wpjCpf%VhSqwz%=>1SR~{~}uPzt6vicyw?%_%AaQ*(;aT%-C`$?fk z_Z}Q|A3Um{PDnB2)aUz^#05s+7V4EIhoi2Hqj?+_a5;9t~_kzdEsKZ74p9 z#pb^lw_|_8MTC+JcTU8cbC4Qdw-x3$QXotd5+qry3&pj>sS=e!6bxah?M*q01^<6F zl((X4fLc&>h*B9Jt_ww6!hFLE_c+G4TE9iYDm5vyw8F4`WRbcfx*sRPz0gOJ#HdjA zrJ6|<*%M7(n-b%tgI4e|>09Iy(PLZUxAY3G%NthQ3btm=*gE z$wQIp!k<}GaGn& zhY;5$w~@yW$;WOugmIuDWspoQ=5XOaKkHBTaVGqhdH*N92lt{D{!bY245>sW7R;-R zB-jpI%LVNs!Y%G07QkXT7nDjM2VGi5Y!I2LmFOFqgbI0G^sP{X$RmS)7Ps7{zb}Sk zCiyD#g%@vQ8FPwwiJAQsg(3EA#>|)t$n-}oaD9!3NH%}LELf|bjW7FuM#!Ieb|4~< z=^LfLL`7_JiIaDvCpud?nm__BAqDdi&fb?tUAjFlANLLgV`+4JLPf^0aI<<~2<2-I zMSogfqfLfVB+FJ7vekub?GgURf4{@8d-%lv>-Y~Z*Z7!)?&A~xuRdJJ@b=MyYOk{{ zo~)wu8vn=dRRVdikm2zfK2`x>72x?5ZwUh6euwIR_qC`f$JW>Q*o99-+0yeZBJ^BT zoCg)}Le*S(`0)9&`|GRk;2sDybnT%W=Nd=i{4f7)BLTz_@PRS6;VO)Qs0cEN-lQPN zMIv!H0{KZ~(hfw%QxKCwwrZn5%8Tl#%daFg#)t!e4-SAvOykF4WNo};>XlhzaFzYd z)q7>`%YSNw@}KuOVENBS#h<26SH?5U2P6~qk$iq{^ZC|RaU_3@HL`6%|1rZ_f9lEX>Cy}?Af^SHzr4$4cQAD16safDxh>vtMv zYS8FQ*x!AzPXc{29x7qu@Dl!1A7DUr%M()SceGa=4dFP&bg=aFf_c&c)ji9r)+I#s zEiV%m)<$eKKP*7WhVLIV?H@to;fHWd*5nt@{IWhrr?4Sr^`YcTQ-xnVcbAH^$ik-N{-n_TRpq zha=vIiM$E4wfTB0`;XpW{kyF7kF}LGY;J(_4l+BRXFG7Te1-5Cd$sy-ehIb^cTelX zTd9|Q4dZ}Z=tg6FzrU_H$uBk<0T30=lk6+7$-&!AWcJ(M-F)_HdyB`CQ91o_XO}_) zkCMFe?VW#n^q`nf|8@J{9^5M=7{q#G%4yg}%lOAZ2T>JVaWWZSlsC>gkI6a11C)>R zI}*$rBfV>3kncyz(CrO$sIY8`Dd#)B^8Cs08)GtjKF1RJTy7tY4;m z;cQMj<5K)axFbkya#)W$*61c2ainNCCS^P!U};fH@np}8#5bXNEh#>q3;g8#10 zjKKUjb)oAx{EL5u4%wbNPTs~;pqQx**I@vuy+QW!`Sa!HuW&;Kg(EDN65PnPggI@( zutJWM4CR2K5`P66e+r*fBf-+3L9lA}O|rTvNfgWt5V{mxx$R;e^R=O*X1Z}coT7Eq z6)h9yLK^Yb%*Yqlm@UM%JPv~`;kc{`h6G0qj70Pi4F(JFS{Y7qEY3x3Af+qiOGMC6 zQ1zmm0so;dg@oS;aoFv8GExfOjyB#ei9zd_b;)+F;JPi(&xiA5yCx5-a56DFGx`ph zRoC@&I7GzjX>lWBd?HUJBWfe^FEXC#hzPMTASP~u-2KhJ&fn59e|DH88o}Kwe{a* zE4OXc5*V~J$iya>l{D-hy2~n9iXB#%sn5DK8_Vo)jFDo zjcN7KB1RMTi`V@l9AF}l13S10B0G-G7P74_wsx<2{Xh2xF}zF;h2c(}@3W7?OOLBU zw|&zKOH!kzDw= z*81ZRC3M29C&5ke1lM8A-C?qi-Tm!5^z&nl@eqO90t{s&;sfK}7YRejiODN{M&s@& z4*!OTAfpDNRN$|7n6Ps1dHdks-yn_T4~ZeV^y14ZLQw}JS?Ix?r=Da+(TsA!wl|7R znrQ18#K~jU#v*C)v9wNRaDeAA4pU*NXcyFF1lA(s|IU@5Lf(XGhSe*744u~)6Am`D za2GsQJ^7YuPs=t#j0ev$(Wb>OA&~Fva`2u53FVlV0KiW3vj1!z&aAja)?yavPN@6R zDouMz07fbzgwZ?4;xGj2j}3*+3mv$7PA-Ay$LztqKlGn*(|Uh(4d1NA+722Pp3q6k zF#sfO=FD>2Z!k~fXC#y9F*IE}{Q%wJ?9R+=?P;+HmW)^=Izm|33S+kyvflJ4uW=_3 zW7&>jm(K3!gx`;VwPQx387^DXp-tp{81n}>5Nu(lF$dD)duzA`N{$Zw=}EtbATdls z=1u@UVQD2XU&B2GSz>Jm!32tM`=y(Fcl>dQnm8lXv(b5XN`uG*mQ_zf%8_Lrhu$%v zcxt5m{cTt!PQh=yA1B#-c%bP8v%Vp~4I;uEojX*C5Pu-uZoZRDUS|JqZ@$`jxvP|` z$?Pq?$%vC^H0`#3m7X;PY)jU&P1B6L$frp^0SA_M#vPS`d{q5)P-fn~2r)Nk%*3`n2O6jr^Yipb6*u$;zqmkovs5xF-C2guCLx8AfXB$@rt5oG4gi84<0k1%se9SU6y zU25z0S1pC@b}OeuwO>_I*po^VRRZvW+1P}LfB>5k8PK4DDVh+jG}DAn=ox5o2CmRF zLGcL!V$YuvMsFYxiaDX*L}DooaAGaol=t%O&hA#W zN-Qg{H}^N~j==iY+XsFd-f9V@{e#T|hUKmjAF2XevF)@HUT8;?@8Nz1@eJ*0n62?2 z8GLau3(h<-_qFv_!K}pq>LUo|3BtM=B9fb{5rSUCS*=!3F$t8@MK?nBrw9#)QgUjx z?lK^&vnq*nddawMF63Blr3>;pLZ$00HE*@n8fwu4xVZk;x4N$S7EhFi(I5`r?yUha z(mN8Ntzs&GN`*`d$Qa3>@DP3*QW8*ymVZn#&@Q3xsa3`A*lLzs2f2iVIF>2gqUmuz zD@?n;0F+jeuS_gS3K+C}UV_oQf&3=Xd^+H*O$aWZI4r%yl|1lPE78S@*kHhm5tmBE z*(WBbEbigc-DiXWYPtyjTN#r6RFHuhJuakcT_91Gp^uKi@1&FcT9?4WXtPw zd?a2BVNO=~h~u;(Tign?X}>^x&c@y@XvzbGgw{f;^womZI?mgXDRZ4FBHpv-fpcS%* zl6>g{$U3g?IT5`v=w#_i^IV)4I-v_nzUQWf2WI@W2>t1ZnHkER@>{8fgQi}!p~^k~ zgZc*4L+jKlX7scUV*`|+O}5=uehyC?X}c(4?PI{@2_sxHiL^3u{xuKS1ew%qKi);Y z28#`}x#u&q!{O|J2gu?#?oKH*HysG}=toa30aolD0zvdZ$#AuUQ-T++2@vaJY`~7~ zq<~2(fCAAWDX{B<$21fU8W6Y<)g1>hr3YuKGJ12bF&a)Lee6ca`oHuiT-(li7uYTE z3Qp|&#PlD!=h$B|Epp82ae*IMmk4*lW|-HMkB1+TvIc!%>wXP_r(3~<>P_JaWd8Ro zU>(!U13oGKgj?(av!iIE<9l3emGX3Ch&$<@b6tk-DlTarGZhP{WAuOS;d9=^MUM)sLi(da(IJTVy{ z1}zDah=8H8qYF?5d%ogsZ)3wZY*;!h#=c`CgEbnb-O2>cH4sxS*?{6ah)Idi7F%G2 zACSOB34%Bf&$;9cj;WpKXr8wv^}!rMK-QH^$%TB!*`hm@HI9s-ghob28%ou}{jJqO z^dF+zW7(Eh@2d)MjQLs6Dnz_&dM*_qvO_(y{fHFcFok(=5}`y+wj~knGY3MlBJp^A zn&HQTdv=o^<})MzDf2@_1oOq?)-&5>`bgo*+(o*QAjc7mMnG+RkwMD7-AVWJ5TS}l zNZJB{ZqnF#V^#PDV$VPKbt9g-f0{muUn>wfGDToH=E^er!a5wj9>C)ZBZKZRw-2I0 z{1}(wlqY6vjHAk12Wv>AB1)(ai`V=dt#+UvhZ2QB9U9EYzis43Fj|y>*7PR@iryqZ zPQp>7(#Lq=+cK;OPow8^fxiFoPInPsef>4`sp6ZR@P;pJvDjr7J6l_lG0#H59LB@JzfV4gG zk1H>FyNW}YqN?*cDS*PfBZyYY6e-wABMcOeMQ$nlUvu9GMl^k!o32Hyjh9EbCE3id zpDR5e{seo9cqgo8Oi+bwT`=XjeOUVn?fl68(sU^NZG-gSo@7U~;o4=g47OrwFiP|F zHI^ulDPFC_BLus|LS*xQTC3}D3@kHBECHm=QcTM5P7B zRRL?g4|Gcz_VxDG&b!ypqoJ$RfNW(x66Ka@3DsWNO!cPSZ1u+24>PYXbTpZZl8r(n zkEX1ur~iamhkSS#zF3&FtYw`|8j4c@_C2kOhSIJEm<-{sRxJ2zq=dAF=+$3~N1pP& z05j{-@w7N=n`1W@_W$KK%%y$S5G1&uwPmU;Gz>rTNpG?z1?p`!K_$=vS^+A6 zLT$JS*dMiiP?O0260m8@%V^D4G*&9G&#TS1m~m<892~x>_sRWpT+#IhL?wPGC#v1g zq1K@(sCkjlkqVkrieGoH`WHBQ!12Q&_I=RvDf?-OhcnLvrm)GVd&KjJs}b~H`OspA zgjH&FZR!3u_<}fUo-OgXBNvg+c6Qs`8=->_*WbC}tVF#WbDR%6xPO2B!3toQ{uj^6 z;$rwXs3y?!9=izkN^`37|>@B?WXHAcwwj z`cX`1t$)Y-=9ZDs@1oImjoV_kX_|#dD=O&*UwA5XODVZZH^7wea*0Jfa=x`jRfDIr z*1T_maYG3jRQgp7pB>JA=rYS?I4{LF1yH38lOpPI`{ldMx0|~M+sVlpDDsG{<%Nv9 z$u^terW9->utTGiDpIa+Jj{OMIFTVhpjI?XgxreI;B(d~f+>@tGGQ1Q!=WHjpQ#*? zeRxocb7k4Rb=)Tleoi~1^DP=-)dTEeX5s##`r7;*t8-d_s;NnM6N?#E+D`Xu%y~iHN zN-zzD)krXR*9Xtl8#gj^9& zvZ^YaY|)SdGZCvrsI(CY9i*a72iEQh2@vhw{&wNU4zL#7I2X9ij4mh0@@|>A+}itKLl8}i`CIuk{lka)Ae__KM#vvW(jwdU(T*;jzvv)@`FyVj^j5d%ST{t%R znPD%m!udxrGS5cQT}uNE*9Bz_%32-f{t3RDv<9qn<_U>i?|?tp)ec;lE}2Fb(ikAV z!pI)r2r%-JwTZ&)mTuvhI8$?OG2|_6gr2NE1^$Y!2;uZX-dnidDAp{0k#sz~{CmbM z3Y;HFo1mR-)WHbB!HZ*=O}f0C8lJE4I)RbBE1SDnb9nrwJ7lmhL_Y?1SwO~Ziv?L- zU%6pt?J|Odq}TP9?`wO?7tOtl4*3Vky-u8X!Rp9pFtR>y@MhJjhlF+|&>y=DRi zSX0bIKC#pcGkCH;c8m|XfA&^nMC9oLy=lVYElYeyv)wtDHCQ*^ZmfFp-GO=jBhH(1 zJ2zN>EN^R^OtGD$*A^mGfQ4OsdJdp9>3|a_#ekw=vF^L7Ho@~jKn9@F5ng*tWb+28mjr^Md~`KSw(94Go5Na6rfyyeVM+@+EF zxFaL4!I+ono6QPc;%bn z5oR|LTQ6ptO3BJW3rm-XoycDCPY`tCbRdoPI{J>}XO`O{dxzBTr$8Ojlv1dJ-U2Zm zLLsTo1v@jrc_aFPV$g$ltpU2VXzawz3~+dabn0Uyq>sBP&-BgbZ7fQ`@J&@i8QmnnVB|aDZ>f3bDeUK&?r=!6J$i zkkjGNNQ0wbtfaawH?;30I2b}_gad~#jTS*|)$D?RPI4KgLOcyYcKH0`_kqi^z>d0M zw!G^g6(rI?FCNd1FR(IF!-AOAJG&6jD8+(C=1#);9WuAk)8(_Iv-U@>2rQDVeSyc& z1?Di~K;j-kMbXR&Z|hR%D4f-an;*(oi>%K*@(2^v%144QPffL_o;azTW>Eieh( z_86SVcdol$OkJ2~;-lPk0mPA{9pHj1yMoMmL`J95E>9n=Mx5==KhZ0a>xbmL0r|l3 zr<{ko>9GzqNGjLU4tq@YZ*NT8WvEq98>9TK_Kva-IMJO47CO>WXp_wysn9rkO zo4I(C8Nl+SbYdpZ$K)VnOM+_C+`7}__?p&3F)r@5-lIQZA(o~bd0f8|aK;{;8T&WY zfaOSfd6=11z9t!&otn(u#MiD6y9&Y@vYcq?RJ~+;8@UOI3*aTthW!#BXbC9?F(Ue@ z6&_>3^rKX#t!PlF$toaow7F{+b?%swYPTmm4zb50V~D?H$A`!SAFH`reCyCkW}UnqIdp}ikuF+ z=P_{&iegy&c>H&!^dnV~4#ROu5+1a^Ta%EHKekjBGAb-i$;lCNm@)!5dcBtLE;6n2 z(@(2N3l*6uw;ajdCJp_w%;KyWt>V54<%aPP$|M$$I{8_REY3wGGMH_(%qhQdG~C*O zCXWagI0%$Kl%+u|oDQ*$VLqCx0P9l`n)I11G*LQ1X#uihK|%r`-e8KuFBdQYl0Ur` zl#bW}PVVzn0%f`*mxVubosa52Ml2x2ZJ2-%A)Splj22Ed9$*jK3}sWH+F*85=i0#I7r2x~RaT9$`l{ z>**vP+T@f zNx78mz$eX2WIuD)0M|u@jj*IVTIKSGC6K#x)`~8&3L*jON|+1~$_r)pHU=;CXhb)Q zrK9q>)1c?Ugcnkmw3p-tk_`iB>^1q3T#mVf{O+)Wx+Rm8bUaX37Mc=W zsDTBvju4D$>EYSi*fHL@zy^VnnNAe+gB1^rk{XLnjWWp<=!z3+RQ*iGNlz&2sHD}Q zwaVktFa>glk-{N#$}_4J{wcTum{Sj(3BqgpL=PnAQhd@IE6n}P>l7ez>gqT6}jGaPt<#KImIJqhV=CXWf1x|p{#!HPrZwp#mr8Bq@q6{u=>uxgEWvID3fo7MR zucW+&Nr)RTW%HmnoB6X#%Y+tf9BtC>u0F6SqBUzicRUC(HP>jYmR&_+h7dM~nz}Be zM3$rGoGIvj?oTSHiA``-?>-|lh+3WcKX7j+N%b9(|I`lp!FB=Bwh((n4# zodNMojBUGIJLvFBPpM2{JlGfm>2{ung*u}VZAA;o-hPhQ9+Dflb^uc4g<3rZ zLs|knb#QdRpbhn=r90ZquG6{DOKsSkDw}VSv@J@V9F#DnV>?+07n4FjE3RKhBlE__ zVc^Na#z`P1FK5NE-4F(_{1ywC0C2TK@}P9BMaVno5E)DC_L~(72|;M8uGs|$korAjDy$)u-5V0n05SlT8O|L`wzJLn{(3_zZdWgg~cH45` zT+9nRk2+$tx3LA9^{mS`Y@x;uSP&*bK=}G0vx$ue`RFIiQ_#Ao3Te1 zhhPL~UsM9}j3w;*-aeFd+j06{g%_45oj>Vcfdo=K*5%9qewUWM&X zJXb*#d0hv8v4n@?(S-V$@D6zy9riw9isma;KA|e(!diU&ff*%m{@n-R%AA^)8C{M~ zdn`~CGb|AM0A&cY7cTy+*bCEKScQLr=%!l&#>f^Fq)>v&RsH*A%+zJtYA5|nlpxx+_R z@Wo2jxv-wOB5BH!k5fTMs<1ly*F8llu_$4Qt=%>wRJi53p1vfw}DDD&gAAP!;;pQ&bnqEx02W=PF2?O(t> zOVkmO1*LFM6ybDC8xovDE^nB-yb;xQxsU=FyD}v6nld{$*a;fBn4NNp?ry}wtX^?W zk|y2-;sw%TDLro|iF?x1pEx{NjO;I>YeJMV3}o66raqkx3Q|%=VHcGeM5==h5O2}(4DKkK_IObBcj0r;wnspeH5q{wc5a}|@QDo)o4t;uX7$(6c79qh z`4Ew}c^MSt&$OC?KYqaJq7I1Oc&caVG)SJ0_#!2V(D7~1x^*Nj!}+FVkg&6X4+BaB znvml{P2S2iSI$BTC>puK1~S0Jz9@VRC+>9mVE6HX8EZE|GBtr(et{(?IXrj!H9Rb7 z?NN%1DDbAR1)ZL$)|)(O2B1c7C)--MEbPL8^c2l_$Ls1rT2T7g2|5f(p1D|_Y(myN z%Bakk3Li}axS&{CP~sCoZp-a>q>ucg`51K4^}a@BKA;f~T9fZLmMlI`g5|#r{bK=+NBsN+jo4?J#&ND70j5XHqQ0mb=K7bza|z*+k~|1WEkr z8VNYel2mctmU02**LgZ{ z#=1Qc&l$*eg3T^hp-4`6!cDuTZiPDLe|BhDYGNOmHLTyhREkc!lX)}`CuG&9*S1a? zg2Z-McX8uDEfSp1JT-8g#ij#(lgyJtLbme<1L(tXB0A^S;2P+1u=yUXkqb`#}=VmtgkK%!bL-aJ7oW4r(=?CN`=%G%@|q7 zy_u8K-f%k<3F?L8t|-1pzW_BWhYzfKTILRW+{9BY7y=UvE2R3Mi|thcJUq%((G;qG z2XK|+Hq6~{OASz|VAL+NELl-rn}jgry8S<)*4Y3mEu&p`6|>@8Z{14Z@kyzhSZ*7T z8Ktrr6ZjgZv`Vua=dzoc^aM1Y_^NekMzIrARZu%!0K5%*G?UiiGVir}yZVwQ!;ARY zJfDIHNliK=PB%R~d0P6)?hdDLjL5xfH67yqUcWlV`>;LCY|LFh;kP%a?I#+O z(-DIWgPW)wl(fQ6YaDE(4XMp^TvCohN>kZ=wzHVyL_RYOz0@@c4qWF#&(&ibCgllZqK)(ib9mYvpQ7IV2QBS`X*N z+wJYGg5QgQ(Q_L`f_XtDXa*QpRB8bE8-gMrW&=smlTq_ggK|cak;(6@W4?{CEJ~QX zBVr0q?8&u$C750-(Gd)+=TXlO z>|Ncn(e_~GG}p>8PV%S@_84j7;UVQy;lW6|(hTdl)pC2AZ&VZD+;Gooy*DnkFTH`P zYXogJKka~Xz^K;@I%EO>gXA@!q6W*aYsQ6l61{aVXbVKT;jlX?RI(#X1V}ek1dig! zLMhH7F%xL$LOU+FwJm7BG_#1Qnv=TP175-jC;BSpJkzRsE?uYYg$35sy@?%> zxxG??<7>+yCO3{E5rbJ@<^q0GFxj7+!S; zg>dLqCabVCk_Y>CiSQ~x($9LYAqWMyzPd1Yx>{}!g!Sf_swwPH>CDE{s~~pcd~~r=vF}R)j|OdwT}9-S&OCT7oWoRwD^=| zCQGVXH=cQ$kxgc_70Y~P8<8Vsv=Pf(-^ML;erPubb|COdH(!O@CO&ry0eG9)9b~Q> z+~IKwPgHPF`wNt0dB4I=fju~^VRp)H2fi%r`*JxqvpdnfSp{J$>cakrdcjqId+bv< zGa^#h&hN!49lOOtC-bo3nImNkWXnx%2)(G$TF^%MY{Fod4kzNnn$rpESP;}EWplXH zX;LlE(+|>w$eeer_4}scg8=LIX}TtJ+sS_$(p<*dN*YT`M+YZDx980~*@5#dt+NFO z`7r(clXp!G2eA6d_5oBdX>c*N9bj>rt_Z|rOBB~Lz`mOR)0B(5V*qmNEKMXhDbi~@ z`f#jB9uEF~aCW#!kD{iL_ls0Zh%S`GLGtP-5`#Do#*H&piqb@HL(n1F%!opT0G8rQ%O3M{Xl1QZ$o zxWp}t_Kn6`j1tB=a!T&-%YiDe3B2r$OH?x|ynaHCy>{>#B-*M8r)Ty!JkR@WQ_&eK zJ=b*cm&}^{SR-etxNoP0T)u7@ZRVEj$c7*7*CawRrv(gMot+Nmwaant^9~41T|tvM zRznNJrduy{Qz*!0&y|gWi9+aTj8mdMoL>wMW^I$DQOnyQB1T|_0=8(#f0*GPB$MsU z=UdDDo6S;%d^E?jmtxojCY|Ga5FF!d2#S_USzfUS1iK&t;&=E*^9Qb~ehhKmLT0#c&OLhSK&|wNe9KjfO#e_1qV-~Y=fr(gU2-_^DItM~o>-~0DhR@Qm{@9O>kz5n;0!ZXWvKhs`a zucH3%{lE2e`Lw6k-~an|^Z6fY@Bj4|b6;H^a*7jn1r73$dkT#NJ2fi zM8voJ7Pyc~a~ts}LU|xN5s3(}Gv}^u7u_j($tBvWK^e%)n}ttJpV)v1i>CLYc zV(}QJ;hk8Tdk1hG8fVO7gCLMZOBRm1*=Sx_A92r>x-XaMq$v#vpExIL40mBvL0HhMTAUW4$wM=3Wtr@N@80K@#6i5i+gmS#aNk8OZ%7ih7?Un zhq;DmMC4?+pw>Eud#z^V$&evs6jm-8_x>IC z-R6IQZQ~;o2E;cOHzZX!X6h1gG%RPhk`P-pP#T-t;m0cQgS|bt$@<@&fa)D~$8QjP z5*{vxFSvod?lp!=%O+pPhT)E1jlrDZ}U0s@Y#>3@_^jV!fXohE>%voie{HHVw_H&G~Ehrx7Jp1 z#!zY&W=m8mm-)&(A5L(e%V*9C_6(jlZ}xWf_h2mEe!chh-;r$L<<8!2q()`nQm&U| zEzlP~1ohKkUdv#gh3T~{_SsNpve@TQ{Bk!dM+ZMWNo7XIWv3@#AzUa+= zpT*bCJEO3XSkUDnSn90cMB4;9#&Ofo{3lJeLb-7wt^WsgG#FJxNB-_LyCGq*^`cz{U_`l zsM*3y{%V8Kzw_B&_0Z0Gx=IzewI`h9jmm9|?x7t{NTFC*!)Ns=P ztkf1b<~BQu2q-DPz%V>SSn{FiE}L(56ez6=q4xHd&xY{C=hgEt^dW0;yu1kZEEsPi z45VdL7V)4Z>&7Pfyu=y`&z3>uN9_S{jX?K^sRe)B+}|;4_N)Hj@@o0rpnpXaOnaR6 z9@7Yebt!KQ(MooY4_Z~yDkX1MrdcRa$WWVGc_$f?abl5F1G?r%dt86|O7=RssiFb9 zX%YmJdW;;vD^l5&8KztUaZZ=xfk*6uys-S)Eucrt%Z*>~()K7zT>JrNj7u5yZV`fB zH^gEV_%A`FVXy_F*G~GUm&ob?&9lZ&3kUmDeymu@lS!_++!o{q_vk%{aSs>ILPy{$ z9`c(zZMihc>E7wQoaqs;qYiK@5jG=;cQ$x2BuyoRs?ocJQ8vz)SiV?Vz=Q7xZ=GYT zvw1BC9MLRO9e@Qe?7CG$4s1>i`LTH_1j~d7t8sK9|9t|TxvMOS_5%_u2ND3fl3F>U z;aFgj=g{Qg14bEDvX))pM~Z^v}9Ls-Xq=1P&8=ZZe;G)xT%Zo>N7ukg_Wqdu6k~E7Ho&(sbj| zIXa6&JSL%GMmru+Ay^0Lm-@W?$c9trXd&|^u)P1#~EZ=$-q+({U3BVb*7hC3&w$uF>a;m?@ zdJtkL&DGlkh-I)oR7|W%3LO)&ucV~H*CEf8ddWx#IKtb+<7_@I$YF}6X%q5}Ch{XG zZ>tHBn@yHNBcAxRsTrTpUdkJd!e5C5TdTZS+yjJT#tQgv43GLc%9mj6LIr%i30vf` zF2c-y9jT}#N@}CYw)Cz9qN#z9e1wa0*RF5@=emo=pm&Nz9ol%yZ^pzCGfcG*EM2-Z z;~%P)<{Z6LdJ--FB_(n{VF z@Dwsr((3^_8a#QRF(aJ_*JtW%xx;FHHF@sb>~&#dW3tI`VR&dh!##8(ChmlSnP8RS z(&md00~gD}jlv!}4aFV7FMT{wR9yN>?&dYmLlqNbWq*11lMl&o3ji6Af6~RC32n*M zyU;soeKAH&%0>EGd3}tKMhtj3BL(!y(8qksQ-MvU$RmeUUTL1-3>E3@cROPaOplQ1 znXYG0@(+=A59vSXTLk}UEEE@$(;#G-Kb?$*(Kzo7T6izQpYvA?wSO{P<7JP+>8Ni~VH z0)9+rtPt^Tk?j`dZq=iflRzWF(wgaU0~ei3W=S<-(I){uDOenkkZS;b{vK#(o^_;) zcA_dwInqBN7|cL8zd`Om+bq=Y|HY<33_4mW^}w2G0|A#V_!bey_clhvsrwuv35zEt z6(_vq1a=>Fxz*Ty-?Ka*M4gGaq`+FCHdEJ0Wz9W$N-pjgm8H_CdtL5A+TF|PP*Bpj zpJNrKfA0$3Y?Rh?S({Qv!%mU10BQj*F2wb8BaZCw66t%PWR%twcFyr)gS^ui3rums zBt4pmRrKY@=@I9n1sG5obweBA6hwhd>Kll-(JP1m6m-BT8iEh_>C9ATP58uT z$E2>fWQR^9F(E-s?^5S`a4Td0d|)AMF);Yoa)_OOoU@xrxO_p4J@=mTXJ93E)%~Kx zYi7A9a4xzby@dO8CZP;K6RD^rm^W&Y%6{o-u&pYi@cJ+pfSq5gPhTQNb{{O&hkaM#Vz+4=<3f8sx?vsOA zsckJ`R@-b8Cbeyj4qokt>v4~J$atbl(>ce47KIKBMa1^Je+Z%k8@4TX7Foqf5c8@b zehRtpC`B|u3r%X~!|sF2cr%tGUR_KhdRYgw)E3y(=rzJRLg>H?qWsOyCTKT|Zu)o==uW$0tHY#!aeMffnpHgHGv2vQ*}s z_RHOO&ylc(8dJ;9d2Lc*hv9ys?e@!8JI_=qQ@Q-b)uRV(BtAiXTtb>Z?yuu{`C)f_ zQGM1OADs!n{Cv_nfF-SOzInqmJB-~WmU%M`t#@w%^ch^ccC1e~0{UgUMBC=G{VjIt z7Omf;pL^i+U#BHVoT31cnardxOugVqE!V@s|(pTD|e91>CVRZ zP6qde$vl5t;QQT{>8f|<(I7bSG4y{~*}-Aq!c#XLK?F>)m%PfVB!%0NO);W5R*^?5 zc>R1kyfE+VZ0z66!M+x!*t*yZ>q(Lgbz|cmPa3MkI{92;t*>R9&vt4^6Va%&M9UT*?)WT#N@lk&%_vxXe7c%(@Yd zMb3|$hsEqQ*t|cPz;^%j`n~n$4o!scbkskF&AQz?Un%wEVQo*$VXu)&2~dJ;03nwe z!lqiUW0hhf*MEQNpzlM0a1y(lWO+bBN`9!QJGCqS= zSDz=LZqwrb6d4tz6C{;bObcvrqtX6QO3+x z!^_>_WVCqE=Sk*r*s35q4x3m;xYObC(YtQWa;edSC1YDpXweEgp?&Ys*$Uv^2uYIiw7xU z9zQUSq-CPbnB`)7AA9u$e`h&%*!KG1@TSrn0fN8E+ z9!{30lVg%+{l?^3aqsLdytw}V_O7let{aKI`&Zo9RjC;~UK@-* zV`q!PIPt~=7dTGxbZrlVnau#RGY~_i^56HIZgopnqxk}o-3L=4X6EWj>Q+nYKI(2k ztJ#DL!UrZS5%DnZ5rAe6B;sHMK$GF!yx|72g#R?EQ_{i<+6LQJPXA3>#)zf8zF9FT z8edP~N(zby=|sV=H|0SJmr0msm`chX$g<pg5dX0gt=WJMVQXq6|kkdjv8`F;TRBd?SX;pPr29A19tFL0JK& z>&FQ2Bcbn;oW=%D1U^HQaCQfoBGqHuX5|P9S2o^L6O!IUm=Y1O0+iDkY=rAEAms1W z+klNaDfqQY!O>e*`e(ABCo&bmHj{x)N zal0TpnluPNKX5DFodBe>+aGn$jx?r8<`O|6zZxEW{&4a1#vQZjfTRV)3+D?O#>{TY z(kA!yuy=&4oNs)D4E!)^P!PA`?YzZsfoVH?zi{Ar`=9?PS-i7{w2&?Yx*J7|y8?U) z0aQ+5V9y3T*}&%nh5ZLQ8}NlfXPX@zhSAg*aO>ln0H3n2_0G#ZjPjl81q9{f_~qc@ zDeY*^E^V1W8HZ9b&-Z$Wy@pQ_@PZ>m>qGwsg9-K14#Z`IJz{9L?yuc%|CQ0n6+@CI z);hz#Z4aAR3j|!ofnB=eW7ISxx88ZTwY&RD5^OgBj?~N(O9$g=m~S%XKE(RR<0tAb z2!@S=9MP*08$do8Do!zbahpk`NtJafsEI)b4?>71LN!40iT~lwb zyu{Ay7hdS`6CxJq7RUElL3tT{?)AHe13;qVvyV8p#ByR=EaA_)A=>(GkVYg8=^kP) zmoUCe*NwoLHp$JC;H+l6mwl2av)@#oPQZ-Ma>R<^!mWYej+#7tKE}cG+I`7VjzdGH zP-x*|3_THxp4O`m=MZ)R81LhFU*Zcz3&YK@BnVoA>RCpaPBZFGzk_(uAs(%M3lg%? z&SxHkrS;G-HaLE?tJ~GOeHO@s->eB_MA^x><#QI0rt<4nIJO7E79tg?J8+G*c`SJz zy7W!Ng6|bn7jQ)Oal2;0jE?5Ds zcl@;f@t^IY5P4Uyl-zB6C~!XT`~2*#{>6V%?yo<1j4=L;TL>uK-FZd$SLxh?IJ5C`(~3=Ibha{3_O31r*4c@xMhMvqxVnS&2t3vRc9`U6drTNY1sx$hKta?W90)_~ z8FQ>-Gk#v#7yQTrFyUAND!Wjs1cBq&@dgLaL!e)vgdA5ZUNmE;Fd5C2c1zCPaMj34 zTN;-A8a+_MQh_r^eUcTvn&Z_-sUz44;st201~o zFUhvV4&e6R)}2+Hg#0u1FLD;=BPnC-J#gI)M_Z*v6b?@~>s?Y|upvdjLL9f8?P!~& zRT{;}<#J(Gm^!&nv0y`nPi!_#a}}1wB~>_Kcc#Q~?le>>uJN3q=@@)P{03$ATM*Q#ky@!C^SJxk|-h1HrKku)te~JIS+=wps)-{7+)8c=tZA(xBH#xnn zqf@>30C?kdumA7fv14B}(ShO|oDy#RMjT`qeFp;`4l1KQYH^Cuy1M1??Z$b@UOYk3%rUP82A+Bvy9~tO+<0f;x z|G2kx({6VioxnPgieagEf1rEzuV_TIZq^L+eBpC&S#SiXc2i)R?W z*}RK4znffJ?+t+A?VM^C9jn zb-;}_yBrX|cjq$o1bzRE7ZiNEf=_5$`cUy3WFiIKZ%?XEbRYwD5H_?r?teODK5!u= zMCl#S#)q$#5+EVQ0ujWBJDUIS8P>2{y(JxHyawI|FH_j?YSS>8sA2JqH`u=zs4U&f zhw7R?H({x|?hXfMWB!Ui+D~9*AI+WoH8Q`{Gv{J`b@=~FHI>~xrv zhoYiix5znvCn;awy2VGa3B01*s)fJyqP&tm@E4&I`4xO&F1_2>gQdksz=#GZn&{@@Xeb)y#+Vpbz=NUN%ITK~v$G_Ty`yV2Zd7B=PT zeyiTz+pK{Q`e?|^*lbLe&DB*C%*ZRd`ZgPm(_t(!odg@xDP!bcJEM~q(t)rM$_CC~ zvxHD0W+@deW*A$Q5&`X!W=gW7-+Apx>0+m3s;VgYI}1q6-rE;4Bzy2FtZNmU)kmxM zg4nD+Y6#7v`w!*`!-6t1OJv04=VJCQxVS6r>aYs5Uso^X0>VD9x$<0!ORt?^8$0AKn27Fmu0ygqOU@wS#)<5a}v^^V&wpKJx~71qf;pq#jq2X^4W<#@h!a zL>W297OXdVI(yx?fDGP-66dmTHFLYC^<7g330~D7x)K9`oJ`4jD1SO7Eh(5X1&azZt; z8&Z0%+z_iNHsm5%CMr_o1usvOSAl^f6Eg-b-BzfkNSDpoWU$b2PFoo=Z%gJ+oZKuh zb)ZTQrZUz$5Q)8X2aM2(4&VVpYo>A_OyoGWu?tNOq$|kv@*s4f#DyihumBedi#PCc z%0PJ@rHk|d+yo983_O3@P91cdy)Dxii_e`-QyXJfBU`hj=rWWUgB$68gCfDMF45S0 z%4RhNn`oKFSbR1cXEk;*n$=dai>rX3_@ZqUq!G&8sK+ELQB2Y;B+iJY*d`%D*=@;U zgfR?lv1*$FI>Kcr4sxU0eOh9SBEiIAHKtM{Piz52Et(`N?mLhx;Qe>#+S zV&W4lM=(gM2_E5W9#BZA3pK)lfOnw8i?;ykBR4z_D5V0#oCXX7y7hDjgDAx3-e6Fe zDx%Sm`4AFra;?*0XNLNy8laUOmew$@(e{HyYP7PbF%ALQZm19>18inQ93Y~@-arGQ z2gp=$ic?m=HSmOhDaA8M`T^+WDUAc{#PTk6TXjit!uE0Yd#XwZYoMv5f^jQtUW^`$ zz$o{Pnq`Mvu;#FvPOq8T4|`0_s@d(Rfh1d$YhhkiOrnl7K%K47`9>4AkVyaMG+|{I zZz5BpvPL35*`=)P{6<_Wo;kv?5if7jFjO`bN7xI8iA4U&L~4jnq4LNiA7nu&<_M8o z&%B@zNm|G)BrbNo;s4q_A?q6mILnG9KtiZ6gpOl(9Kz}c2Yn0iI)KW!)M*2zR(x*b-5b_xVR5=hRZncu|3L!m;Qm@;9sWxpDB`epk7<&w(!bnD0*4*kf0OGh{_AR24OXr`o!w>}n> zF?4L4e8C_8H;80Bw4!dOPX3AVjhq5OrCK=gL_9RYB*kTcdX2^bs;QXG0$GtnOUK98 zJ3oGhKxeRU+-16YuAj)lVJ+go;^BJhpj{o@x`ns&q$Pb`+K;u!E!KFt*oJ)^_Hd1;t?)|6kj!!i?SK1V8tmanW zC!vW{PA=oVka=-21pQNSJ%?=Q(yJzC3m>_Rn#Y&F+}2^M6Cv9QX9648Y8Z?kLa)=2 zlWhdKyrLYmA^C-^!`qplke0M9CUYr7;fWpVZ=mo_t4Sjb<)w&BaiF=Z2Q8H>v03X}Tk>01>g9r~;s#O13N1QrPa z(0aNi;7bHsP)G8Kis;JtVNIrOtQ^-Q?$Zn0zbQ=MO(o0b@e(}qt~cerwPJLt-zdNX z%daP~l4q^SW}yp*uJ2wD8o6g9ui^BL0q~z|)s<9dzEviR$-18Mj;!pD$HV z!Hu6C_!5}3h;%?2CKYfW>|_;nGiFhu(WajDmSiv!K@qxT_KGEB%(_vaGcz=T5A;C~ zQG#^Y&E`$1&jy(~$J#Iyo>%uMRB_&07vcu=H5Ok^PVSPq=y_d94FcTF;5>sR#!Rlc z7_(Eq<$Ak*^~>Xj%`{Hi^)C-4-X{#o3gRMyFH5rWkW@YiPR=KYcgomiI+F6v&8pOn z%Gbo^%qlJTv?<9zZeU2!J*`Q!IcaV+;yunulz2!A57PBrVBrFsa1u)|?g}1qpu*HVA(hMQ8KHz?` zC`6%O6f1mBxe8`@ON%8+W47nO5>UEP5Oy|lt_CCkPFS(FB-CfQp{Ff2lQ%}rB}V>y z_5{p_KH45*GIFT)SfoMA>5}Be}4yk|~Bo>`-xVV2?M30eV;aC+f^jr45 z!9_xfin?(&;3%@#1UZ3)#gE8R`3L?%`mm6A+7=~THUeAjxqlCr(|wVuKTWPuGo&a{ zr~uiXv|bS_`saa0YKuU?n4+RqR(>mtO&s@(gRVcBiu=BSbAg~ z4Epa}uHnUw=%(ncZilJDs&%@=%+OUKuCvwDFtg!@jV{7NIh;ZQgp#W}5^v`S&P4Y5 z0ifZCgwIoGiSr2QK5$-^y<{(xHb34OT0*hBH5<-_TeBCIX-zljnP*6#Es~|>1Lo42 z)>3+w52xM|nT>`8YLr8X1Z^Z!3k^%zD>O_Dn)Ehs=6WNToEUVualw(pgjBzxGccZ}##bx6TbzAXzbzS;sXx41tY2m~ zJ7^;zjt8;-{@fHq5^xD$*U&^fs<=!Oc1mHYzj$nHh>H|_yDz8!!94{rEyn=&HP>5E zV>DG5WA7y^x;)EsIbp}45T%xbsBg&*FV9UQ)WRsD`=1&3R!y?Spp46AQPiLaBp4K{ z6s-Vf8VPm4OL^rmLddR@MAW*7N0X=xvq|hzpSeR+S2}M;4#vK?2q&Ax3BU**dvM?1 zm8%;tQoK4&f}0S~Oot`SK-53}omrF+w3gxinYP3#TN6#Jphjdz3hIvrEe9Q4_HmnE zEG4S&J&#sa9F3bCV`VVSdFu*NUqcgenjC_Hh9mGuV3kXG>3ocB!Pdvj3aDoy1B5Nn zTF9@&d>=TWTBWME5MMu?eHiTft3Sx6|#6fTMcu|g)eVq7B9O2MrQr?Z6>PO56j z|230!B$@%*+LF;A`10Mf-0%k-Ss*<&0-&*Ygj*O80`&6d+moXpdk zouTc;>Y6H%)|9aP9<%s3MWM4Y`0a{EkCf40>37(~0n#wCc>Je4{x%cU%%(`Z7-fD* zbQiOXg|uZ)pK1x2P}#|6$c=C3g$tih&NOoJ4hgw$^okpdXQ?0c-rm+4vvow;dq+oD z1jFg)Qtj18N4O*p=d@{4NnUiz>E6i6-W}jt5cEJYj{C6d$t|MFYR}Pp*;MYMquv1Z zH(y8Q|E<^ITWd6ivLy*co3F`*f5YxXb;H7UZ{9GCd)Droou9XM8&F3N6Wh z#dZXLo{*85GwO2vvR%k|AEU%%OJ-3d1?(QeTPX%;UL1E1 z>Cv$i1Zw0@2o0u5m*n6Z4!~U{-y@OtF*kTe^ h&UFpG41Z8Tsq4uI{^jyGd@22f17A4sg#*iS;J?}c-R1xQ From 7e87d30f1f30d39c3005e03195f3d7648b38a1e2 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 23 Apr 2024 13:38:23 -0700 Subject: [PATCH 106/127] gh-118074: Immortal executors are not GC-able (#118182) Better version of gh-118117. Just check for immortality instead of an address range check. --- Python/optimizer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Python/optimizer.c b/Python/optimizer.c index 5863336c0d9ecfe..0017965c32f290b 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -397,10 +397,7 @@ executor_traverse(PyObject *o, visitproc visit, void *arg) static int executor_is_gc(PyObject *o) { - if ((PyObject *)&COLD_EXITS[0] <= o && o < (PyObject *)&COLD_EXITS[COLD_EXIT_COUNT]) { - return 0; - } - return 1; + return !_Py_IsImmortal(o); } PyTypeObject _PyUOpExecutor_Type = { From 692e902c742f577f9fc8ed81e60ed9dd6c994e1e Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Wed, 24 Apr 2024 11:02:38 +0300 Subject: [PATCH 107/127] gh-116023: Add `show_empty=False` to `ast.dump` (#116037) Co-authored-by: Carl Meyer --- Doc/library/ast.rst | 251 +++++++----------- Lib/ast.py | 21 +- Lib/test/test_ast.py | 141 ++++++++-- ...-02-28-11-51-51.gh-issue-116023.CGYhFh.rst | 3 + 4 files changed, 249 insertions(+), 167 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-02-28-11-51-51.gh-issue-116023.CGYhFh.rst diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 8d407321092eef1..09f2a404786fb6b 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -173,8 +173,7 @@ Root nodes Assign( targets=[ Name(id='x', ctx=Store())], - value=Constant(value=1))], - type_ignores=[]) + value=Constant(value=1))]) .. class:: Expression(body) @@ -302,8 +301,7 @@ Literals value=Call( func=Name(id='sin', ctx=Load()), args=[ - Name(id='a', ctx=Load())], - keywords=[]), + Name(id='a', ctx=Load())]), conversion=-1, format_spec=JoinedStr( values=[ @@ -398,8 +396,7 @@ Variables Module( body=[ Expr( - value=Name(id='a', ctx=Load()))], - type_ignores=[]) + value=Name(id='a', ctx=Load()))]) >>> print(ast.dump(ast.parse('a = 1'), indent=4)) Module( @@ -407,16 +404,14 @@ Variables Assign( targets=[ Name(id='a', ctx=Store())], - value=Constant(value=1))], - type_ignores=[]) + value=Constant(value=1))]) >>> print(ast.dump(ast.parse('del a'), indent=4)) Module( body=[ Delete( targets=[ - Name(id='a', ctx=Del())])], - type_ignores=[]) + Name(id='a', ctx=Del())])]) .. class:: Starred(value, ctx) @@ -439,8 +434,7 @@ Variables value=Name(id='b', ctx=Store()), ctx=Store())], ctx=Store())], - value=Name(id='it', ctx=Load()))], - type_ignores=[]) + value=Name(id='it', ctx=Load()))]) .. _ast-expressions: @@ -463,8 +457,7 @@ Expressions Expr( value=UnaryOp( op=USub(), - operand=Name(id='a', ctx=Load())))], - type_ignores=[]) + operand=Name(id='a', ctx=Load())))]) .. class:: UnaryOp(op, operand) @@ -729,7 +722,10 @@ Comprehensions .. doctest:: - >>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4)) + >>> print(ast.dump( + ... ast.parse('[x for x in numbers]', mode='eval'), + ... indent=4, + ... )) Expression( body=ListComp( elt=Name(id='x', ctx=Load()), @@ -737,9 +733,11 @@ Comprehensions comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), - ifs=[], is_async=0)])) - >>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4)) + >>> print(ast.dump( + ... ast.parse('{x: x**2 for x in numbers}', mode='eval'), + ... indent=4, + ... )) Expression( body=DictComp( key=Name(id='x', ctx=Load()), @@ -751,9 +749,11 @@ Comprehensions comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), - ifs=[], is_async=0)])) - >>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4)) + >>> print(ast.dump( + ... ast.parse('{x for x in numbers}', mode='eval'), + ... indent=4, + ... )) Expression( body=SetComp( elt=Name(id='x', ctx=Load()), @@ -761,7 +761,6 @@ Comprehensions comprehension( target=Name(id='x', ctx=Store()), iter=Name(id='numbers', ctx=Load()), - ifs=[], is_async=0)])) @@ -784,18 +783,15 @@ Comprehensions elt=Call( func=Name(id='ord', ctx=Load()), args=[ - Name(id='c', ctx=Load())], - keywords=[]), + Name(id='c', ctx=Load())]), generators=[ comprehension( target=Name(id='line', ctx=Store()), iter=Name(id='file', ctx=Load()), - ifs=[], is_async=0), comprehension( target=Name(id='c', ctx=Store()), iter=Name(id='line', ctx=Load()), - ifs=[], is_async=0)])) >>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'), @@ -834,7 +830,6 @@ Comprehensions comprehension( target=Name(id='i', ctx=Store()), iter=Name(id='soc', ctx=Load()), - ifs=[], is_async=1)])) @@ -864,8 +859,7 @@ Statements targets=[ Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], - value=Constant(value=1))], - type_ignores=[]) + value=Constant(value=1))]) >>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking Module( @@ -877,8 +871,7 @@ Statements Name(id='a', ctx=Store()), Name(id='b', ctx=Store())], ctx=Store())], - value=Name(id='c', ctx=Load()))], - type_ignores=[]) + value=Name(id='c', ctx=Load()))]) .. class:: AnnAssign(target, annotation, value, simple) @@ -898,8 +891,7 @@ Statements AnnAssign( target=Name(id='c', ctx=Store()), annotation=Name(id='int', ctx=Load()), - simple=1)], - type_ignores=[]) + simple=1)]) >>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis Module( @@ -908,8 +900,7 @@ Statements target=Name(id='a', ctx=Store()), annotation=Name(id='int', ctx=Load()), value=Constant(value=1), - simple=0)], - type_ignores=[]) + simple=0)]) >>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation Module( @@ -920,8 +911,7 @@ Statements attr='b', ctx=Store()), annotation=Name(id='int', ctx=Load()), - simple=0)], - type_ignores=[]) + simple=0)]) >>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation Module( @@ -932,8 +922,7 @@ Statements slice=Constant(value=1), ctx=Store()), annotation=Name(id='int', ctx=Load()), - simple=0)], - type_ignores=[]) + simple=0)]) .. class:: AugAssign(target, op, value) @@ -954,8 +943,7 @@ Statements AugAssign( target=Name(id='x', ctx=Store()), op=Add(), - value=Constant(value=2))], - type_ignores=[]) + value=Constant(value=2))]) .. class:: Raise(exc, cause) @@ -971,8 +959,7 @@ Statements body=[ Raise( exc=Name(id='x', ctx=Load()), - cause=Name(id='y', ctx=Load()))], - type_ignores=[]) + cause=Name(id='y', ctx=Load()))]) .. class:: Assert(test, msg) @@ -987,8 +974,7 @@ Statements body=[ Assert( test=Name(id='x', ctx=Load()), - msg=Name(id='y', ctx=Load()))], - type_ignores=[]) + msg=Name(id='y', ctx=Load()))]) .. class:: Delete(targets) @@ -1005,8 +991,7 @@ Statements targets=[ Name(id='x', ctx=Del()), Name(id='y', ctx=Del()), - Name(id='z', ctx=Del())])], - type_ignores=[]) + Name(id='z', ctx=Del())])]) .. class:: Pass() @@ -1018,8 +1003,7 @@ Statements >>> print(ast.dump(ast.parse('pass'), indent=4)) Module( body=[ - Pass()], - type_ignores=[]) + Pass()]) .. class:: TypeAlias(name, type_params, value) @@ -1036,9 +1020,7 @@ Statements body=[ TypeAlias( name=Name(id='Alias', ctx=Store()), - type_params=[], - value=Name(id='int', ctx=Load()))], - type_ignores=[]) + value=Name(id='int', ctx=Load()))]) .. versionadded:: 3.12 @@ -1061,8 +1043,7 @@ Imports names=[ alias(name='x'), alias(name='y'), - alias(name='z')])], - type_ignores=[]) + alias(name='z')])]) .. class:: ImportFrom(module, names, level) @@ -1083,8 +1064,7 @@ Imports alias(name='x'), alias(name='y'), alias(name='z')], - level=0)], - type_ignores=[]) + level=0)]) .. class:: alias(name, asname) @@ -1102,8 +1082,7 @@ Imports names=[ alias(name='a', asname='b'), alias(name='c')], - level=2)], - type_ignores=[]) + level=2)]) Control flow ^^^^^^^^^^^^ @@ -1146,8 +1125,7 @@ Control flow value=Constant(value=Ellipsis))], orelse=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. class:: For(target, iter, body, orelse, type_comment) @@ -1181,8 +1159,7 @@ Control flow value=Constant(value=Ellipsis))], orelse=[ Expr( - value=Constant(value=Ellipsis))])], - type_ignores=[]) + value=Constant(value=Ellipsis))])]) .. class:: While(test, body, orelse) @@ -1207,8 +1184,7 @@ Control flow value=Constant(value=Ellipsis))], orelse=[ Expr( - value=Constant(value=Ellipsis))])], - type_ignores=[]) + value=Constant(value=Ellipsis))])]) .. class:: Break @@ -1242,9 +1218,7 @@ Control flow body=[ Break()], orelse=[ - Continue()])], - orelse=[])], - type_ignores=[]) + Continue()])])]) .. class:: Try(body, handlers, orelse, finalbody) @@ -1289,8 +1263,7 @@ Control flow value=Constant(value=Ellipsis))], finalbody=[ Expr( - value=Constant(value=Ellipsis))])], - type_ignores=[]) + value=Constant(value=Ellipsis))])]) .. class:: TryStar(body, handlers, orelse, finalbody) @@ -1318,10 +1291,7 @@ Control flow type=Name(id='Exception', ctx=Load()), body=[ Expr( - value=Constant(value=Ellipsis))])], - orelse=[], - finalbody=[])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.11 @@ -1353,10 +1323,7 @@ Control flow ExceptHandler( type=Name(id='TypeError', ctx=Load()), body=[ - Pass()])], - orelse=[], - finalbody=[])], - type_ignores=[]) + Pass()])])]) .. class:: With(items, body, type_comment) @@ -1398,9 +1365,7 @@ Control flow func=Name(id='something', ctx=Load()), args=[ Name(id='b', ctx=Load()), - Name(id='d', ctx=Load())], - keywords=[]))])], - type_ignores=[]) + Name(id='d', ctx=Load())]))])]) Pattern matching @@ -1457,14 +1422,10 @@ Pattern matching value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( - cls=Name(id='tuple', ctx=Load()), - patterns=[], - kwd_attrs=[], - kwd_patterns=[]), + cls=Name(id='tuple', ctx=Load())), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1492,8 +1453,7 @@ Pattern matching value=Constant(value='Relevant')), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1519,8 +1479,7 @@ Pattern matching pattern=MatchSingleton(value=None), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1552,8 +1511,7 @@ Pattern matching value=Constant(value=2))]), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1594,8 +1552,7 @@ Pattern matching MatchStar()]), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1639,11 +1596,10 @@ Pattern matching Expr( value=Constant(value=Ellipsis))]), match_case( - pattern=MatchMapping(keys=[], patterns=[], rest='rest'), + pattern=MatchMapping(rest='rest'), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1685,16 +1641,13 @@ Pattern matching MatchValue( value=Constant(value=0)), MatchValue( - value=Constant(value=0))], - kwd_attrs=[], - kwd_patterns=[]), + value=Constant(value=0))]), body=[ Expr( value=Constant(value=Ellipsis))]), match_case( pattern=MatchClass( cls=Name(id='Point3D', ctx=Load()), - patterns=[], kwd_attrs=[ 'x', 'y', @@ -1708,8 +1661,7 @@ Pattern matching value=Constant(value=0))]), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1751,8 +1703,7 @@ Pattern matching pattern=MatchAs(), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1785,8 +1736,7 @@ Pattern matching MatchAs(name='y')]), body=[ Expr( - value=Constant(value=Ellipsis))])])], - type_ignores=[]) + value=Constant(value=Ellipsis))])])]) .. versionadded:: 3.10 @@ -1818,8 +1768,7 @@ aliases. value=Subscript( value=Name(id='list', ctx=Load()), slice=Name(id='T', ctx=Load()), - ctx=Load()))], - type_ignores=[]) + ctx=Load()))]) .. versionadded:: 3.12 @@ -1843,8 +1792,7 @@ aliases. Name(id='P', ctx=Load()), Name(id='int', ctx=Load())], ctx=Load()), - ctx=Load()))], - type_ignores=[]) + ctx=Load()))]) .. versionadded:: 3.12 @@ -1869,8 +1817,7 @@ aliases. value=Name(id='Ts', ctx=Load()), ctx=Load())], ctx=Load()), - ctx=Load()))], - type_ignores=[]) + ctx=Load()))]) .. versionadded:: 3.12 @@ -1910,15 +1857,10 @@ Function and class definitions Expr( value=Lambda( args=arguments( - posonlyargs=[], args=[ arg(arg='x'), - arg(arg='y')], - kwonlyargs=[], - kw_defaults=[], - defaults=[]), - body=Constant(value=Ellipsis)))], - type_ignores=[]) + arg(arg='y')]), + body=Constant(value=Ellipsis)))]) .. class:: arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults) @@ -1957,7 +1899,6 @@ Function and class definitions FunctionDef( name='f', args=arguments( - posonlyargs=[], args=[ arg( arg='a', @@ -1980,9 +1921,7 @@ Function and class definitions decorator_list=[ Name(id='decorator1', ctx=Load()), Name(id='decorator2', ctx=Load())], - returns=Constant(value='return annotation'), - type_params=[])], - type_ignores=[]) + returns=Constant(value='return annotation'))]) .. class:: Return(value) @@ -1995,8 +1934,7 @@ Function and class definitions Module( body=[ Return( - value=Constant(value=4))], - type_ignores=[]) + value=Constant(value=4))]) .. class:: Yield(value) @@ -2012,16 +1950,14 @@ Function and class definitions body=[ Expr( value=Yield( - value=Name(id='x', ctx=Load())))], - type_ignores=[]) + value=Name(id='x', ctx=Load())))]) >>> print(ast.dump(ast.parse('yield from x'), indent=4)) Module( body=[ Expr( value=YieldFrom( - value=Name(id='x', ctx=Load())))], - type_ignores=[]) + value=Name(id='x', ctx=Load())))]) .. class:: Global(names) @@ -2038,8 +1974,7 @@ Function and class definitions names=[ 'x', 'y', - 'z'])], - type_ignores=[]) + 'z'])]) >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( @@ -2048,8 +1983,7 @@ Function and class definitions names=[ 'x', 'y', - 'z'])], - type_ignores=[]) + 'z'])]) .. class:: ClassDef(name, bases, keywords, body, decorator_list, type_params) @@ -2089,9 +2023,7 @@ Function and class definitions Pass()], decorator_list=[ Name(id='decorator1', ctx=Load()), - Name(id='decorator2', ctx=Load())], - type_params=[])], - type_ignores=[]) + Name(id='decorator2', ctx=Load())])]) .. versionchanged:: 3.12 Added ``type_params``. @@ -2123,22 +2055,12 @@ Async and await body=[ AsyncFunctionDef( name='f', - args=arguments( - posonlyargs=[], - args=[], - kwonlyargs=[], - kw_defaults=[], - defaults=[]), + args=arguments(), body=[ Expr( value=Await( value=Call( - func=Name(id='other_func', ctx=Load()), - args=[], - keywords=[])))], - decorator_list=[], - type_params=[])], - type_ignores=[]) + func=Name(id='other_func', ctx=Load()))))])]) .. class:: AsyncFor(target, iter, body, orelse, type_comment) @@ -2425,7 +2347,7 @@ and classes for traversing abstract syntax trees: node = YourTransformer().visit(node) -.. function:: dump(node, annotate_fields=True, include_attributes=False, *, indent=None) +.. function:: dump(node, annotate_fields=True, include_attributes=False, *, indent=None, show_empty=False) Return a formatted dump of the tree in *node*. This is mainly useful for debugging purposes. If *annotate_fields* is true (by default), @@ -2442,9 +2364,42 @@ and classes for traversing abstract syntax trees: indents that many spaces per level. If *indent* is a string (such as ``"\t"``), that string is used to indent each level. + If *show_empty* is ``False`` (the default), empty lists and fields that are ``None`` + will be omitted from the output. + .. versionchanged:: 3.9 Added the *indent* option. + .. versionchanged:: 3.13 + Added the *show_empty* option. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... async def f(): + ... await other_func() + ... """), indent=4, show_empty=True)) + Module( + body=[ + AsyncFunctionDef( + name='f', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Await( + value=Call( + func=Name(id='other_func', ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + type_params=[])], + type_ignores=[]) + .. _ast-compiler-flags: diff --git a/Lib/ast.py b/Lib/ast.py index b8c4ce6f919e6b4..9f386051659e76c 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -114,7 +114,11 @@ def _convert(node): return _convert(node_or_string) -def dump(node, annotate_fields=True, include_attributes=False, *, indent=None): +def dump( + node, annotate_fields=True, include_attributes=False, + *, + indent=None, show_empty=False, +): """ Return a formatted dump of the tree in node. This is mainly useful for debugging purposes. If annotate_fields is true (by default), @@ -125,6 +129,8 @@ def dump(node, annotate_fields=True, include_attributes=False, *, indent=None): include_attributes can be set to true. If indent is a non-negative integer or string, then the tree will be pretty-printed with that indent level. None (the default) selects the single line representation. + If show_empty is False, then empty lists and fields that are None + will be omitted from the output for better readability. """ def _format(node, level=0): if indent is not None: @@ -137,6 +143,7 @@ def _format(node, level=0): if isinstance(node, AST): cls = type(node) args = [] + args_buffer = [] allsimple = True keywords = annotate_fields for name in node._fields: @@ -148,6 +155,18 @@ def _format(node, level=0): if value is None and getattr(cls, name, ...) is None: keywords = True continue + if ( + not show_empty + and (value is None or value == []) + # Special cases: + # `Constant(value=None)` and `MatchSingleton(value=None)` + and not isinstance(node, (Constant, MatchSingleton)) + ): + args_buffer.append(repr(value)) + continue + elif not keywords: + args.extend(args_buffer) + args_buffer = [] value, simple = _format(value, level) allsimple = allsimple and simple if keywords: diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 5b47cdaafb092e4..44bcb9bae1cfde9 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -1227,21 +1227,20 @@ def test_dump(self): node = ast.parse('spam(eggs, "and cheese")') self.assertEqual(ast.dump(node), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " - "args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')], " - "keywords=[]))], type_ignores=[])" + "args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')]))])" ) self.assertEqual(ast.dump(node, annotate_fields=False), "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " - "Constant('and cheese')], []))], [])" + "Constant('and cheese')]))])" ) self.assertEqual(ast.dump(node, include_attributes=True), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=4), " "args=[Name(id='eggs', ctx=Load(), lineno=1, col_offset=5, " "end_lineno=1, end_col_offset=9), Constant(value='and cheese', " - "lineno=1, col_offset=11, end_lineno=1, end_col_offset=23)], keywords=[], " + "lineno=1, col_offset=11, end_lineno=1, end_col_offset=23)], " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24), " - "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)], type_ignores=[])" + "lineno=1, col_offset=0, end_lineno=1, end_col_offset=24)])" ) def test_dump_indent(self): @@ -1254,9 +1253,7 @@ def test_dump_indent(self): func=Name(id='spam', ctx=Load()), args=[ Name(id='eggs', ctx=Load()), - Constant(value='and cheese')], - keywords=[]))], - type_ignores=[])""") + Constant(value='and cheese')]))])""") self.assertEqual(ast.dump(node, annotate_fields=False, indent='\t'), """\ Module( \t[ @@ -1265,9 +1262,7 @@ def test_dump_indent(self): \t\t\t\tName('spam', Load()), \t\t\t\t[ \t\t\t\t\tName('eggs', Load()), -\t\t\t\t\tConstant('and cheese')], -\t\t\t\t[]))], -\t[])""") +\t\t\t\t\tConstant('and cheese')]))])""") self.assertEqual(ast.dump(node, include_attributes=True, indent=3), """\ Module( body=[ @@ -1294,7 +1289,6 @@ def test_dump_indent(self): col_offset=11, end_lineno=1, end_col_offset=23)], - keywords=[], lineno=1, col_offset=0, end_lineno=1, @@ -1302,8 +1296,7 @@ def test_dump_indent(self): lineno=1, col_offset=0, end_lineno=1, - end_col_offset=24)], - type_ignores=[])""") + end_col_offset=24)])""") def test_dump_incomplete(self): node = ast.Raise(lineno=3, col_offset=4) @@ -1333,6 +1326,119 @@ def test_dump_incomplete(self): self.assertEqual(ast.dump(node, annotate_fields=False), "Raise(cause=Name('e', Load()))" ) + # Arguments: + node = ast.arguments(args=[ast.arg("x")]) + self.assertEqual(ast.dump(node, annotate_fields=False), + "arguments([], [arg('x')])", + ) + node = ast.arguments(posonlyargs=[ast.arg("x")]) + self.assertEqual(ast.dump(node, annotate_fields=False), + "arguments([arg('x')])", + ) + node = ast.arguments(posonlyargs=[ast.arg("x")], kwonlyargs=[ast.arg('y')]) + self.assertEqual(ast.dump(node, annotate_fields=False), + "arguments([arg('x')], kwonlyargs=[arg('y')])", + ) + node = ast.arguments(args=[ast.arg("x")], kwonlyargs=[ast.arg('y')]) + self.assertEqual(ast.dump(node, annotate_fields=False), + "arguments([], [arg('x')], kwonlyargs=[arg('y')])", + ) + node = ast.arguments() + self.assertEqual(ast.dump(node, annotate_fields=False), + "arguments()", + ) + # Classes: + node = ast.ClassDef( + 'T', + [], + [ast.keyword('a', ast.Constant(None))], + [], + [ast.Name('dataclass')], + ) + self.assertEqual(ast.dump(node), + "ClassDef(name='T', keywords=[keyword(arg='a', value=Constant(value=None))], decorator_list=[Name(id='dataclass')])", + ) + self.assertEqual(ast.dump(node, annotate_fields=False), + "ClassDef('T', [], [keyword('a', Constant(None))], [], [Name('dataclass')])", + ) + + def test_dump_show_empty(self): + def check_node(node, empty, full, **kwargs): + with self.subTest(show_empty=False): + self.assertEqual( + ast.dump(node, show_empty=False, **kwargs), + empty, + ) + with self.subTest(show_empty=True): + self.assertEqual( + ast.dump(node, show_empty=True, **kwargs), + full, + ) + + def check_text(code, empty, full, **kwargs): + check_node(ast.parse(code), empty, full, **kwargs) + + check_node( + ast.arguments(), + empty="arguments()", + full="arguments(posonlyargs=[], args=[], kwonlyargs=[], kw_defaults=[], defaults=[])", + ) + + check_node( + # Corner case: there are no real `Name` instances with `id=''`: + ast.Name(id='', ctx=ast.Load()), + empty="Name(id='', ctx=Load())", + full="Name(id='', ctx=Load())", + ) + + check_node( + ast.MatchSingleton(value=None), + empty="MatchSingleton(value=None)", + full="MatchSingleton(value=None)", + ) + + check_node( + ast.Constant(value=None), + empty="Constant(value=None)", + full="Constant(value=None)", + ) + + check_node( + ast.Constant(value=''), + empty="Constant(value='')", + full="Constant(value='')", + ) + + check_text( + "def a(b: int = 0, *, c): ...", + empty="Module(body=[FunctionDef(name='a', args=arguments(args=[arg(arg='b', annotation=Name(id='int', ctx=Load()))], kwonlyargs=[arg(arg='c')], kw_defaults=[None], defaults=[Constant(value=0)]), body=[Expr(value=Constant(value=Ellipsis))])])", + full="Module(body=[FunctionDef(name='a', args=arguments(posonlyargs=[], args=[arg(arg='b', annotation=Name(id='int', ctx=Load()))], kwonlyargs=[arg(arg='c')], kw_defaults=[None], defaults=[Constant(value=0)]), body=[Expr(value=Constant(value=Ellipsis))], decorator_list=[], type_params=[])], type_ignores=[])", + ) + + check_text( + "def a(b: int = 0, *, c): ...", + empty="Module(body=[FunctionDef(name='a', args=arguments(args=[arg(arg='b', annotation=Name(id='int', ctx=Load(), lineno=1, col_offset=9, end_lineno=1, end_col_offset=12), lineno=1, col_offset=6, end_lineno=1, end_col_offset=12)], kwonlyargs=[arg(arg='c', lineno=1, col_offset=21, end_lineno=1, end_col_offset=22)], kw_defaults=[None], defaults=[Constant(value=0, lineno=1, col_offset=15, end_lineno=1, end_col_offset=16)]), body=[Expr(value=Constant(value=Ellipsis, lineno=1, col_offset=25, end_lineno=1, end_col_offset=28), lineno=1, col_offset=25, end_lineno=1, end_col_offset=28)], lineno=1, col_offset=0, end_lineno=1, end_col_offset=28)])", + full="Module(body=[FunctionDef(name='a', args=arguments(posonlyargs=[], args=[arg(arg='b', annotation=Name(id='int', ctx=Load(), lineno=1, col_offset=9, end_lineno=1, end_col_offset=12), lineno=1, col_offset=6, end_lineno=1, end_col_offset=12)], kwonlyargs=[arg(arg='c', lineno=1, col_offset=21, end_lineno=1, end_col_offset=22)], kw_defaults=[None], defaults=[Constant(value=0, lineno=1, col_offset=15, end_lineno=1, end_col_offset=16)]), body=[Expr(value=Constant(value=Ellipsis, lineno=1, col_offset=25, end_lineno=1, end_col_offset=28), lineno=1, col_offset=25, end_lineno=1, end_col_offset=28)], decorator_list=[], type_params=[], lineno=1, col_offset=0, end_lineno=1, end_col_offset=28)], type_ignores=[])", + include_attributes=True, + ) + + check_text( + 'spam(eggs, "and cheese")', + empty="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')]))])", + full="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load()), Constant(value='and cheese')], keywords=[]))], type_ignores=[])", + ) + + check_text( + 'spam(eggs, text="and cheese")', + empty="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load())], keywords=[keyword(arg='text', value=Constant(value='and cheese'))]))])", + full="Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), args=[Name(id='eggs', ctx=Load())], keywords=[keyword(arg='text', value=Constant(value='and cheese'))]))], type_ignores=[])", + ) + + check_text( + "import _ast as ast; from module import sub", + empty="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)])", + full="Module(body=[Import(names=[alias(name='_ast', asname='ast')]), ImportFrom(module='module', names=[alias(name='sub')], level=0)], type_ignores=[])", + ) def test_copy_location(self): src = ast.parse('1 + 1', mode='eval') @@ -1361,14 +1467,13 @@ def test_fix_missing_locations(self): "Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=5), " "args=[Constant(value='spam', lineno=1, col_offset=6, end_lineno=1, " - "end_col_offset=12)], keywords=[], lineno=1, col_offset=0, end_lineno=1, " + "end_col_offset=12)], lineno=1, col_offset=0, end_lineno=1, " "end_col_offset=13), lineno=1, col_offset=0, end_lineno=1, " "end_col_offset=13), Expr(value=Call(func=Name(id='spam', ctx=Load(), " "lineno=1, col_offset=0, end_lineno=1, end_col_offset=0), " "args=[Constant(value='eggs', lineno=1, col_offset=0, end_lineno=1, " - "end_col_offset=0)], keywords=[], lineno=1, col_offset=0, end_lineno=1, " - "end_col_offset=0), lineno=1, col_offset=0, end_lineno=1, end_col_offset=0)], " - "type_ignores=[])" + "end_col_offset=0)], lineno=1, col_offset=0, end_lineno=1, " + "end_col_offset=0), lineno=1, col_offset=0, end_lineno=1, end_col_offset=0)])" ) def test_increment_lineno(self): diff --git a/Misc/NEWS.d/next/Library/2024-02-28-11-51-51.gh-issue-116023.CGYhFh.rst b/Misc/NEWS.d/next/Library/2024-02-28-11-51-51.gh-issue-116023.CGYhFh.rst new file mode 100644 index 000000000000000..bebb67e585eea6e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-02-28-11-51-51.gh-issue-116023.CGYhFh.rst @@ -0,0 +1,3 @@ +Don't show empty fields (value ``None`` or ``[]``) +in :func:`ast.dump` by default. Add ``show_empty=False`` +parameter to optionally show them. From 0aa0fc3d3ca144f979c684552a56a18ed8f558e4 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:46:17 +0100 Subject: [PATCH 108/127] gh-117901: Add option for compiler's codegen to save nested instruction sequences for introspection (#118007) --- .../internal/pycore_instruction_sequence.h | 1 + Lib/test/test_compiler_codegen.py | 96 ++++++++++++++++++- ...-04-17-22-53-52.gh-issue-117901.SsEcVJ.rst | 1 + Python/compile.c | 18 ++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-17-22-53-52.gh-issue-117901.SsEcVJ.rst diff --git a/Include/internal/pycore_instruction_sequence.h b/Include/internal/pycore_instruction_sequence.h index ecba0d9d8e996ea..d6a79616db71fa0 100644 --- a/Include/internal/pycore_instruction_sequence.h +++ b/Include/internal/pycore_instruction_sequence.h @@ -61,6 +61,7 @@ _PyJumpTargetLabel _PyInstructionSequence_NewLabel(_PyInstructionSequence *seq); int _PyInstructionSequence_ApplyLabelMap(_PyInstructionSequence *seq); int _PyInstructionSequence_InsertInstruction(_PyInstructionSequence *seq, int pos, int opcode, int oparg, _Py_SourceLocation loc); +int _PyInstructionSequence_AddNested(_PyInstructionSequence *seq, _PyInstructionSequence *nested); void PyInstructionSequence_Fini(_PyInstructionSequence *seq); extern PyTypeObject _PyInstructionSequence_Type; diff --git a/Lib/test/test_compiler_codegen.py b/Lib/test/test_compiler_codegen.py index 166294a40c1cb7b..1088b4aa9e624d4 100644 --- a/Lib/test/test_compiler_codegen.py +++ b/Lib/test/test_compiler_codegen.py @@ -1,4 +1,5 @@ +import textwrap from test.support.bytecode_helper import CodegenTestCase # Tests for the code-generation stage of the compiler. @@ -6,11 +7,19 @@ class IsolatedCodeGenTests(CodegenTestCase): + def assertInstructionsMatch_recursive(self, insts, expected_insts): + expected_nested = [i for i in expected_insts if isinstance(i, list)] + expected_insts = [i for i in expected_insts if not isinstance(i, list)] + self.assertInstructionsMatch(insts, expected_insts) + self.assertEqual(len(insts.get_nested()), len(expected_nested)) + for n_insts, n_expected in zip(insts.get_nested(), expected_nested): + self.assertInstructionsMatch_recursive(n_insts, n_expected) + def codegen_test(self, snippet, expected_insts): import ast a = ast.parse(snippet, "my_file.py", "exec") insts = self.generate_code(a) - self.assertInstructionsMatch(insts, expected_insts) + self.assertInstructionsMatch_recursive(insts, expected_insts) def test_if_expression(self): snippet = "42 if True else 24" @@ -55,6 +64,91 @@ def test_for_loop(self): ] self.codegen_test(snippet, expected) + def test_function(self): + snippet = textwrap.dedent(""" + def f(x): + return x + 42 + """) + expected = [ + # Function definition + ('RESUME', 0), + ('LOAD_CONST', 0), + ('MAKE_FUNCTION', None), + ('STORE_NAME', 0), + ('LOAD_CONST', 1), + ('RETURN_VALUE', None), + [ + # Function body + ('RESUME', 0), + ('LOAD_FAST', 0), + ('LOAD_CONST', 1), + ('BINARY_OP', 0), + ('RETURN_VALUE', None), + ('LOAD_CONST', 0), + ('RETURN_VALUE', None), + ] + ] + self.codegen_test(snippet, expected) + + def test_nested_functions(self): + snippet = textwrap.dedent(""" + def f(): + def h(): + return 12 + def g(): + x = 1 + y = 2 + z = 3 + u = 4 + return 42 + """) + expected = [ + # Function definition + ('RESUME', 0), + ('LOAD_CONST', 0), + ('MAKE_FUNCTION', None), + ('STORE_NAME', 0), + ('LOAD_CONST', 1), + ('RETURN_VALUE', None), + [ + # Function body + ('RESUME', 0), + ('LOAD_CONST', 1), + ('MAKE_FUNCTION', None), + ('STORE_FAST', 0), + ('LOAD_CONST', 2), + ('MAKE_FUNCTION', None), + ('STORE_FAST', 1), + ('LOAD_CONST', 0), + ('RETURN_VALUE', None), + [ + ('RESUME', 0), + ('NOP', None), + ('LOAD_CONST', 1), + ('RETURN_VALUE', None), + ('LOAD_CONST', 0), + ('RETURN_VALUE', None), + ], + [ + ('RESUME', 0), + ('LOAD_CONST', 1), + ('STORE_FAST', 0), + ('LOAD_CONST', 2), + ('STORE_FAST', 1), + ('LOAD_CONST', 3), + ('STORE_FAST', 2), + ('LOAD_CONST', 4), + ('STORE_FAST', 3), + ('NOP', None), + ('LOAD_CONST', 5), + ('RETURN_VALUE', None), + ('LOAD_CONST', 0), + ('RETURN_VALUE', None), + ], + ], + ] + self.codegen_test(snippet, expected) + def test_syntax_error__return_not_in_function(self): snippet = "return 42" with self.assertRaisesRegex(SyntaxError, "'return' outside function"): diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-17-22-53-52.gh-issue-117901.SsEcVJ.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-17-22-53-52.gh-issue-117901.SsEcVJ.rst new file mode 100644 index 000000000000000..1e412690deecd75 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-17-22-53-52.gh-issue-117901.SsEcVJ.rst @@ -0,0 +1 @@ +Add option for compiler's codegen to save nested instruction sequences for introspection. diff --git a/Python/compile.c b/Python/compile.c index 3d856b7e4ddd973..ca5551a8e64ab03 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -285,6 +285,10 @@ struct compiler { struct compiler_unit *u; /* compiler state for current block */ PyObject *c_stack; /* Python list holding compiler_unit ptrs */ PyArena *c_arena; /* pointer to memory allocation arena */ + + bool c_save_nested_seqs; /* if true, construct recursive instruction sequences + * (including instructions for nested code objects) + */ }; #define INSTR_SEQUENCE(C) ((C)->u->u_instr_sequence) @@ -402,6 +406,7 @@ compiler_setup(struct compiler *c, mod_ty mod, PyObject *filename, c->c_flags = *flags; c->c_optimize = (optimize == -1) ? _Py_GetConfig()->optimization_level : optimize; c->c_nestlevel = 0; + c->c_save_nested_seqs = false; if (!_PyAST_Optimize(mod, arena, c->c_optimize, merged)) { return ERROR; @@ -1290,6 +1295,11 @@ compiler_exit_scope(struct compiler *c) // Don't call PySequence_DelItem() with an exception raised PyObject *exc = PyErr_GetRaisedException(); + instr_sequence *nested_seq = NULL; + if (c->c_save_nested_seqs) { + nested_seq = c->u->u_instr_sequence; + Py_INCREF(nested_seq); + } c->c_nestlevel--; compiler_unit_free(c->u); /* Restore c->u to the parent unit. */ @@ -1303,10 +1313,17 @@ compiler_exit_scope(struct compiler *c) PyErr_FormatUnraisable("Exception ignored on removing " "the last compiler stack item"); } + if (nested_seq != NULL) { + if (_PyInstructionSequence_AddNested(c->u->u_instr_sequence, nested_seq) < 0) { + PyErr_FormatUnraisable("Exception ignored on appending " + "nested instruction sequence"); + } + } } else { c->u = NULL; } + Py_XDECREF(nested_seq); PyErr_SetRaisedException(exc); } @@ -7734,6 +7751,7 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, _PyArena_Free(arena); return NULL; } + c->c_save_nested_seqs = true; metadata = PyDict_New(); if (metadata == NULL) { From f6e5cc66bef74346b4a6490f9d0c623e7a736e03 Mon Sep 17 00:00:00 2001 From: rindeal Date: Wed, 24 Apr 2024 11:13:35 +0000 Subject: [PATCH 109/127] no-issue: devcontainer: update to Fedora 40 (gh-118161) --- .devcontainer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index fa30aee478cf33a..6f8fe005621c88e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/library/fedora:37 +FROM docker.io/library/fedora:40 ENV CC=clang From 975081b11e052c9f8deb42c5876104651736302e Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:27:40 +0300 Subject: [PATCH 110/127] gh-117225: Add color to doctest output (#117583) Co-authored-by: Alex Waygood --- Lib/doctest.py | 49 ++++++++++++++---- Lib/test/support/__init__.py | 2 +- Lib/test/test_doctest/test_doctest.py | 51 +++++++++++++++++-- Lib/traceback.py | 4 ++ ...-04-06-18-41-36.gh-issue-117225.tJh1Hw.rst | 1 + 5 files changed, 92 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-06-18-41-36.gh-issue-117225.tJh1Hw.rst diff --git a/Lib/doctest.py b/Lib/doctest.py index 4e362cbb9c9d6b4..a3b42fdfb12254d 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -104,6 +104,7 @@ def _test(): import unittest from io import StringIO, IncrementalNewlineDecoder from collections import namedtuple +from traceback import _ANSIColors, _can_colorize class TestResults(namedtuple('TestResults', 'failed attempted')): @@ -1179,6 +1180,9 @@ class DocTestRunner: The `run` method is used to process a single DocTest case. It returns a TestResults instance. + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> tests = DocTestFinder().find(_TestClass) >>> runner = DocTestRunner(verbose=False) >>> tests.sort(key = lambda test: test.name) @@ -1229,6 +1233,8 @@ class DocTestRunner: can be also customized by subclassing DocTestRunner, and overriding the methods `report_start`, `report_success`, `report_unexpected_exception`, and `report_failure`. + + >>> traceback._COLORIZE = save_colorize """ # This divider string is used to separate failure messages, and to # separate sections of the summary. @@ -1307,7 +1313,10 @@ def report_unexpected_exception(self, out, test, example, exc_info): 'Exception raised:\n' + _indent(_exception_traceback(exc_info))) def _failure_header(self, test, example): - out = [self.DIVIDER] + red, reset = ( + (_ANSIColors.RED, _ANSIColors.RESET) if _can_colorize() else ("", "") + ) + out = [f"{red}{self.DIVIDER}{reset}"] if test.filename: if test.lineno is not None and example.lineno is not None: lineno = test.lineno + example.lineno + 1 @@ -1592,6 +1601,21 @@ def summarize(self, verbose=None): else: failed.append((name, (failures, tries, skips))) + if _can_colorize(): + bold_green = _ANSIColors.BOLD_GREEN + bold_red = _ANSIColors.BOLD_RED + green = _ANSIColors.GREEN + red = _ANSIColors.RED + reset = _ANSIColors.RESET + yellow = _ANSIColors.YELLOW + else: + bold_green = "" + bold_red = "" + green = "" + red = "" + reset = "" + yellow = "" + if verbose: if notests: print(f"{_n_items(notests)} had no tests:") @@ -1600,13 +1624,13 @@ def summarize(self, verbose=None): print(f" {name}") if passed: - print(f"{_n_items(passed)} passed all tests:") + print(f"{green}{_n_items(passed)} passed all tests:{reset}") for name, count in sorted(passed): s = "" if count == 1 else "s" - print(f" {count:3d} test{s} in {name}") + print(f" {green}{count:3d} test{s} in {name}{reset}") if failed: - print(self.DIVIDER) + print(f"{red}{self.DIVIDER}{reset}") print(f"{_n_items(failed)} had failures:") for name, (failures, tries, skips) in sorted(failed): print(f" {failures:3d} of {tries:3d} in {name}") @@ -1615,18 +1639,21 @@ def summarize(self, verbose=None): s = "" if total_tries == 1 else "s" print(f"{total_tries} test{s} in {_n_items(self._stats)}.") - and_f = f" and {total_failures} failed" if total_failures else "" - print(f"{total_tries - total_failures} passed{and_f}.") + and_f = ( + f" and {red}{total_failures} failed{reset}" + if total_failures else "" + ) + print(f"{green}{total_tries - total_failures} passed{reset}{and_f}.") if total_failures: s = "" if total_failures == 1 else "s" - msg = f"***Test Failed*** {total_failures} failure{s}" + msg = f"{bold_red}***Test Failed*** {total_failures} failure{s}{reset}" if total_skips: s = "" if total_skips == 1 else "s" - msg = f"{msg} and {total_skips} skipped test{s}" + msg = f"{msg} and {yellow}{total_skips} skipped test{s}{reset}" print(f"{msg}.") elif verbose: - print("Test passed.") + print(f"{bold_green}Test passed.{reset}") return TestResults(total_failures, total_tries, skipped=total_skips) @@ -1644,7 +1671,7 @@ def merge(self, other): d[name] = (failures, tries, skips) -def _n_items(items: list) -> str: +def _n_items(items: list | dict) -> str: """ Helper to pluralise the number of items in a list. """ @@ -1655,7 +1682,7 @@ def _n_items(items: list) -> str: class OutputChecker: """ - A class used to check the whether the actual output from a doctest + A class used to check whether the actual output from a doctest example matches the expected output. `OutputChecker` defines two methods: `check_output`, which compares a given pair of outputs, and returns true if they match; and `output_difference`, which diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index be3f93ab2e5fd1a..6eb0f84b02ea22a 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -26,7 +26,7 @@ "Error", "TestFailed", "TestDidNotRun", "ResourceDenied", # io "record_original_stdout", "get_original_stdout", "captured_stdout", - "captured_stdin", "captured_stderr", + "captured_stdin", "captured_stderr", "captured_output", # unittest "is_resource_enabled", "requires", "requires_freebsd_version", "requires_gil_enabled", "requires_linux_version", "requires_mac_ver", diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py index cba4b16d544a204..0f1e584e22a888f 100644 --- a/Lib/test/test_doctest/test_doctest.py +++ b/Lib/test/test_doctest/test_doctest.py @@ -16,6 +16,7 @@ import tempfile import types import contextlib +import traceback def doctest_skip_if(condition): @@ -470,7 +471,7 @@ def basics(): r""" >>> tests = finder.find(sample_func) >>> print(tests) # doctest: +ELLIPSIS - [] + [] The exact name depends on how test_doctest was invoked, so allow for leading path components. @@ -892,6 +893,9 @@ def basics(): r""" DocTestRunner is used to run DocTest test cases, and to accumulate statistics. Here's a simple DocTest case we can use: + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> def f(x): ... ''' ... >>> x = 12 @@ -946,6 +950,8 @@ def basics(): r""" 6 ok TestResults(failed=1, attempted=3) + + >>> traceback._COLORIZE = save_colorize """ def verbose_flag(): r""" The `verbose` flag makes the test runner generate more detailed @@ -1021,6 +1027,9 @@ def exceptions(): r""" lines between the first line and the type/value may be omitted or replaced with any other string: + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> def f(x): ... ''' ... >>> x = 12 @@ -1251,6 +1260,8 @@ def exceptions(): r""" ... ZeroDivisionError: integer division or modulo by zero TestResults(failed=1, attempted=1) + + >>> traceback._COLORIZE = save_colorize """ def displayhook(): r""" Test that changing sys.displayhook doesn't matter for doctest. @@ -1292,6 +1303,9 @@ def optionflags(): r""" The DONT_ACCEPT_TRUE_FOR_1 flag disables matches between True/False and 1/0: + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> def f(x): ... '>>> True\n1\n' @@ -1711,6 +1725,7 @@ def optionflags(): r""" Clean up. >>> del doctest.OPTIONFLAGS_BY_NAME[unlikely] + >>> traceback._COLORIZE = save_colorize """ @@ -1721,6 +1736,9 @@ def option_directives(): r""" single example. To turn an option on for an example, follow that example with a comment of the form ``# doctest: +OPTION``: + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> def f(x): r''' ... >>> print(list(range(10))) # should fail: no ellipsis ... [0, 1, ..., 9] @@ -1928,6 +1946,8 @@ def option_directives(): r""" >>> test = doctest.DocTestParser().get_doctest(s, {}, 's', 's.py', 0) Traceback (most recent call last): ValueError: line 0 of the doctest for s has an option directive on a line with no example: '# doctest: +ELLIPSIS' + + >>> traceback._COLORIZE = save_colorize """ def test_testsource(): r""" @@ -2011,6 +2031,9 @@ def test_pdb_set_trace(): with a version that restores stdout. This is necessary for you to see debugger output. + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> doc = ''' ... >>> x = 42 ... >>> raise Exception('clé') @@ -2065,7 +2088,7 @@ def test_pdb_set_trace(): ... finally: ... sys.stdin = real_stdin --Return-- - > (3)calls_set_trace()->None + > (3)calls_set_trace()->None -> import pdb; pdb.set_trace() (Pdb) print(y) 2 @@ -2133,6 +2156,8 @@ def test_pdb_set_trace(): Got: 9 TestResults(failed=1, attempted=3) + + >>> traceback._COLORIZE = save_colorize """ def test_pdb_set_trace_nested(): @@ -2667,7 +2692,10 @@ def test_testfile(): r""" called with the name of a file, which is taken to be relative to the calling module. The return value is (#failures, #tests). -We don't want `-v` in sys.argv for these tests. +We don't want color or `-v` in sys.argv for these tests. + + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False >>> save_argv = sys.argv >>> if '-v' in sys.argv: @@ -2835,6 +2863,7 @@ def test_testfile(): r""" TestResults(failed=0, attempted=2) >>> doctest.master = None # Reset master. >>> sys.argv = save_argv + >>> traceback._COLORIZE = save_colorize """ class TestImporter(importlib.abc.MetaPathFinder, importlib.abc.ResourceLoader): @@ -2972,6 +3001,9 @@ def test_testmod(): r""" def test_unicode(): """ Check doctest with a non-ascii filename: + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> doc = ''' ... >>> raise Exception('clé') ... ''' @@ -2997,8 +3029,11 @@ def test_unicode(): """ raise Exception('clé') Exception: clé TestResults(failed=1, attempted=1) + + >>> traceback._COLORIZE = save_colorize """ + @doctest_skip_if(not support.has_subprocess_support) def test_CLI(): r""" The doctest module can be used to run doctests against an arbitrary file. @@ -3290,6 +3325,9 @@ def test_run_doctestsuite_multiple_times(): def test_exception_with_note(note): """ + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> test_exception_with_note('Note') Traceback (most recent call last): ... @@ -3339,6 +3377,8 @@ def test_exception_with_note(note): ValueError: message note TestResults(failed=1, attempted=...) + + >>> traceback._COLORIZE = save_colorize """ exc = ValueError('Text') exc.add_note(note) @@ -3419,6 +3459,9 @@ def test_syntax_error_subclass_from_stdlib(): def test_syntax_error_with_incorrect_expected_note(): """ + >>> save_colorize = traceback._COLORIZE + >>> traceback._COLORIZE = False + >>> def f(x): ... r''' ... >>> exc = SyntaxError("error", ("x.py", 23, None, "bad syntax")) @@ -3447,6 +3490,8 @@ def test_syntax_error_with_incorrect_expected_note(): note1 note2 TestResults(failed=1, attempted=...) + + >>> traceback._COLORIZE = save_colorize """ diff --git a/Lib/traceback.py b/Lib/traceback.py index d27c7a726d2bb6c..054def57c214827 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -448,8 +448,12 @@ class _ANSIColors: BOLD_RED = '\x1b[1;31m' MAGENTA = '\x1b[35m' BOLD_MAGENTA = '\x1b[1;35m' + GREEN = "\x1b[32m" + BOLD_GREEN = "\x1b[1;32m" GREY = '\x1b[90m' RESET = '\x1b[0m' + YELLOW = "\x1b[33m" + class StackSummary(list): """A list of FrameSummary objects, representing a stack of frames.""" diff --git a/Misc/NEWS.d/next/Library/2024-04-06-18-41-36.gh-issue-117225.tJh1Hw.rst b/Misc/NEWS.d/next/Library/2024-04-06-18-41-36.gh-issue-117225.tJh1Hw.rst new file mode 100644 index 000000000000000..6a0da1c3bc9388e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-06-18-41-36.gh-issue-117225.tJh1Hw.rst @@ -0,0 +1 @@ +Add colour to doctest output. Patch by Hugo van Kemenade. From 7d369d471cf2b067c4d795d70b75201c48b46f5b Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 24 Apr 2024 13:20:19 +0100 Subject: [PATCH 111/127] GH-117536: GH-117894: fix athrow().throw(...) unawaited warning (GH-117851) --- Lib/test/test_asyncgen.py | 83 ++++++++++++++++--- ...-04-13-16-55-53.gh-issue-117536.xkVbfv.rst | 1 + ...-04-15-13-53-59.gh-issue-117894.8LpZ6m.rst | 1 + Objects/genobject.c | 9 +- 4 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-13-16-55-53.gh-issue-117536.xkVbfv.rst create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-04-15-13-53-59.gh-issue-117894.8LpZ6m.rst diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py index 39605dca3886c8f..a1e9e1b89c6a2cf 100644 --- a/Lib/test/test_asyncgen.py +++ b/Lib/test/test_asyncgen.py @@ -399,9 +399,8 @@ async def gen(): with self.assertWarns(DeprecationWarning): x = gen().athrow(GeneratorExit, GeneratorExit(), None) - with self.assertWarnsRegex(RuntimeWarning, - f"coroutine method 'athrow' of '{gen.__qualname__}' " - f"was never awaited"): + with self.assertRaises(GeneratorExit): + x.send(None) del x gc_collect() @@ -1572,11 +1571,6 @@ async def main(): self.assertIsInstance(message['exception'], ZeroDivisionError) self.assertIn('unhandled exception during asyncio.run() shutdown', message['message']) - with self.assertWarnsRegex(RuntimeWarning, - f"coroutine method 'aclose' of '{async_iterate.__qualname__}' " - f"was never awaited"): - del message, messages - gc_collect() def test_async_gen_expression_01(self): async def arange(n): @@ -1630,10 +1624,6 @@ async def main(): asyncio.run(main()) self.assertEqual([], messages) - with self.assertWarnsRegex(RuntimeWarning, - f"coroutine method 'aclose' of '{async_iterate.__qualname__}' " - f"was never awaited"): - gc_collect() def test_async_gen_await_same_anext_coro_twice(self): async def async_iterate(): @@ -1671,6 +1661,62 @@ async def run(): self.loop.run_until_complete(run()) + def test_async_gen_throw_same_aclose_coro_twice(self): + async def async_iterate(): + yield 1 + yield 2 + + it = async_iterate() + nxt = it.aclose() + with self.assertRaises(StopIteration): + nxt.throw(GeneratorExit) + + with self.assertRaisesRegex( + RuntimeError, + r"cannot reuse already awaited aclose\(\)/athrow\(\)" + ): + nxt.throw(GeneratorExit) + + def test_async_gen_throw_custom_same_aclose_coro_twice(self): + async def async_iterate(): + yield 1 + yield 2 + + it = async_iterate() + + class MyException(Exception): + pass + + nxt = it.aclose() + with self.assertRaises(MyException): + nxt.throw(MyException) + + with self.assertRaisesRegex( + RuntimeError, + r"cannot reuse already awaited aclose\(\)/athrow\(\)" + ): + nxt.throw(MyException) + + def test_async_gen_throw_custom_same_athrow_coro_twice(self): + async def async_iterate(): + yield 1 + yield 2 + + it = async_iterate() + + class MyException(Exception): + pass + + nxt = it.athrow(MyException) + with self.assertRaises(MyException): + nxt.throw(MyException) + + with self.assertRaisesRegex( + RuntimeError, + r"cannot reuse already awaited aclose\(\)/athrow\(\)" + ): + nxt.throw(MyException) + def test_async_gen_aclose_twice_with_different_coros(self): # Regression test for https://bugs.python.org/issue39606 async def async_iterate(): @@ -1752,6 +1798,19 @@ async def gen(): g.aclose() gc_collect() + def test_aclose_throw(self): + async def gen(): + return + yield + + class MyException(Exception): + pass + + g = gen() + with self.assertRaises(MyException): + g.aclose().throw(MyException) + del g + gc_collect() if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-13-16-55-53.gh-issue-117536.xkVbfv.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-13-16-55-53.gh-issue-117536.xkVbfv.rst new file mode 100644 index 000000000000000..2492fd163cb549f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-13-16-55-53.gh-issue-117536.xkVbfv.rst @@ -0,0 +1 @@ +Fix a :exc:`RuntimeWarning` when calling ``agen.aclose().throw(Exception)``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-04-15-13-53-59.gh-issue-117894.8LpZ6m.rst b/Misc/NEWS.d/next/Core and Builtins/2024-04-15-13-53-59.gh-issue-117894.8LpZ6m.rst new file mode 100644 index 000000000000000..bd32500a54ee211 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-04-15-13-53-59.gh-issue-117894.8LpZ6m.rst @@ -0,0 +1 @@ +Prevent ``agen.aclose()`` objects being re-used after ``.throw()``. diff --git a/Objects/genobject.c b/Objects/genobject.c index 8d1dbb72ba9ec21..5d7da49cfca1668 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -2208,7 +2208,11 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs); if (o->agt_args) { - return async_gen_unwrap_value(o->agt_gen, retval); + retval = async_gen_unwrap_value(o->agt_gen, retval); + if (retval == NULL) { + o->agt_state = AWAITABLE_STATE_CLOSED; + } + return retval; } else { /* aclose() mode */ if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) { @@ -2218,6 +2222,9 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG); return NULL; } + if (retval == NULL) { + o->agt_state = AWAITABLE_STATE_CLOSED; + } if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) || PyErr_ExceptionMatches(PyExc_GeneratorExit)) { From 77cd0428b698a743844179f7babead43b2794d77 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 24 Apr 2024 14:37:55 +0100 Subject: [PATCH 112/127] GH-118095: Convert DEOPT_IFs on likely side exits to EXIT_IFs (GH-118106) Covert DEOPT_IFs on likely side exits to EXIT_IFs --- Include/internal/pycore_opcode_metadata.h | 10 +++++----- Include/internal/pycore_uop_metadata.h | 14 +++++++------- Python/bytecodes.c | 22 +++++++++++----------- Python/optimizer.c | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index e75de9d12e0c557..5636debbf4a7f2c 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -984,7 +984,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [CACHE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_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 }, - [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_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 }, @@ -1000,7 +1000,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CALL_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [CALL_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_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_ESCAPES_FLAG }, @@ -1036,9 +1036,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = { [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 }, [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, - [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, - [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG }, - [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG }, + [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG }, + [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG }, + [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG }, [GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 4d15be6317d615f..2da4c4d4e21e939 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -171,14 +171,14 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GET_ITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GET_YIELD_FROM_ITER] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_FOR_ITER_TIER_TWO] = HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_ITER_CHECK_LIST] = HAS_DEOPT_FLAG, - [_GUARD_NOT_EXHAUSTED_LIST] = HAS_DEOPT_FLAG, + [_ITER_CHECK_LIST] = HAS_EXIT_FLAG, + [_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG, [_ITER_NEXT_LIST] = 0, - [_ITER_CHECK_TUPLE] = HAS_DEOPT_FLAG, - [_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_DEOPT_FLAG, + [_ITER_CHECK_TUPLE] = HAS_EXIT_FLAG, + [_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_EXIT_FLAG, [_ITER_NEXT_TUPLE] = 0, - [_ITER_CHECK_RANGE] = HAS_DEOPT_FLAG, - [_GUARD_NOT_EXHAUSTED_RANGE] = HAS_DEOPT_FLAG, + [_ITER_CHECK_RANGE] = HAS_EXIT_FLAG, + [_GUARD_NOT_EXHAUSTED_RANGE] = HAS_EXIT_FLAG, [_ITER_NEXT_RANGE] = HAS_ERROR_FLAG, [_WITH_EXCEPT_START] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_PUSH_EXC_INFO] = 0, @@ -194,7 +194,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_INIT_CALL_BOUND_METHOD_EXACT_ARGS] = HAS_ARG_FLAG, [_CHECK_PEP_523] = HAS_DEOPT_FLAG, - [_CHECK_FUNCTION_EXACT_ARGS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_CHECK_FUNCTION_EXACT_ARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CHECK_STACK_SPACE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_INIT_CALL_PY_EXACT_ARGS_0] = HAS_PURE_FLAG, [_INIT_CALL_PY_EXACT_ARGS_1] = HAS_PURE_FLAG, diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 4541eb635da0150..1f908a991072931 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2628,7 +2628,7 @@ dummy_func( } op(_ITER_CHECK_LIST, (iter -- iter)) { - DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type); + EXIT_IF(Py_TYPE(iter) != &PyListIter_Type); } replaced op(_ITER_JUMP_LIST, (iter -- iter)) { @@ -2657,8 +2657,8 @@ dummy_func( _PyListIterObject *it = (_PyListIterObject *)iter; assert(Py_TYPE(iter) == &PyListIter_Type); PyListObject *seq = it->it_seq; - DEOPT_IF(seq == NULL); - DEOPT_IF((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)); + EXIT_IF(seq == NULL); + EXIT_IF((size_t)it->it_index >= (size_t)PyList_GET_SIZE(seq)); } op(_ITER_NEXT_LIST, (iter -- iter, next)) { @@ -2677,7 +2677,7 @@ dummy_func( _ITER_NEXT_LIST; op(_ITER_CHECK_TUPLE, (iter -- iter)) { - DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type); + EXIT_IF(Py_TYPE(iter) != &PyTupleIter_Type); } replaced op(_ITER_JUMP_TUPLE, (iter -- iter)) { @@ -2703,8 +2703,8 @@ dummy_func( _PyTupleIterObject *it = (_PyTupleIterObject *)iter; assert(Py_TYPE(iter) == &PyTupleIter_Type); PyTupleObject *seq = it->it_seq; - DEOPT_IF(seq == NULL); - DEOPT_IF(it->it_index >= PyTuple_GET_SIZE(seq)); + EXIT_IF(seq == NULL); + EXIT_IF(it->it_index >= PyTuple_GET_SIZE(seq)); } op(_ITER_NEXT_TUPLE, (iter -- iter, next)) { @@ -2724,7 +2724,7 @@ dummy_func( op(_ITER_CHECK_RANGE, (iter -- iter)) { _PyRangeIterObject *r = (_PyRangeIterObject *)iter; - DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type); + EXIT_IF(Py_TYPE(r) != &PyRangeIter_Type); } replaced op(_ITER_JUMP_RANGE, (iter -- iter)) { @@ -2744,7 +2744,7 @@ dummy_func( op(_GUARD_NOT_EXHAUSTED_RANGE, (iter -- iter)) { _PyRangeIterObject *r = (_PyRangeIterObject *)iter; assert(Py_TYPE(r) == &PyRangeIter_Type); - DEOPT_IF(r->len <= 0); + EXIT_IF(r->len <= 0); } op(_ITER_NEXT_RANGE, (iter -- iter, next)) { @@ -3145,11 +3145,11 @@ dummy_func( } op(_CHECK_FUNCTION_EXACT_ARGS, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) { - DEOPT_IF(!PyFunction_Check(callable)); + EXIT_IF(!PyFunction_Check(callable)); PyFunctionObject *func = (PyFunctionObject *)callable; - DEOPT_IF(func->func_version != func_version); + EXIT_IF(func->func_version != func_version); PyCodeObject *code = (PyCodeObject *)func->func_code; - DEOPT_IF(code->co_argcount != oparg + (self_or_null != NULL)); + EXIT_IF(code->co_argcount != oparg + (self_or_null != NULL)); } op(_CHECK_STACK_SPACE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { diff --git a/Python/optimizer.c b/Python/optimizer.c index 0017965c32f290b..6a8b4f3c9504ade 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -696,7 +696,7 @@ translate_bytecode_to_trace( if (expansion->nuops > 0) { // Reserve space for nuops (+ _SET_IP + _EXIT_TRACE) int nuops = expansion->nuops; - RESERVE(nuops); + RESERVE(nuops + 1); /* One extra for exit */ if (expansion->uops[nuops-1].uop == _POP_FRAME) { // Check for trace stack underflow now: // We can't bail e.g. in the middle of From 83235f7791fbe6ee2618192f2341de9cd22d0511 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 24 Apr 2024 14:41:30 +0100 Subject: [PATCH 113/127] GH-115419: Move setting the instruction pointer to error exit stubs (GH-118088) --- Lib/test/test_capi/test_opt.py | 2 +- Python/bytecodes.c | 3 ++- Python/executor_cases.c.h | 2 ++ Python/optimizer.c | 1 + Python/optimizer_analysis.c | 3 --- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index ae23eadb8aafa07..c004f4637700190 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -231,7 +231,7 @@ def testfunc(x): ex = get_first_executor(testfunc) self.assertIsNotNone(ex) uops = get_opnames(ex) - self.assertIn("_SET_IP", uops) + self.assertIn("_JUMP_TO_TOP", uops) self.assertIn("_LOAD_FAST_0", uops) def test_extended_arg(self): diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 1f908a991072931..c31617d35b02f5c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4226,7 +4226,8 @@ dummy_func( EXIT_TO_TRACE(); } - tier2 op(_ERROR_POP_N, (unused[oparg] --)) { + tier2 op(_ERROR_POP_N, (target/2, unused[oparg] --)) { + frame->instr_ptr = ((_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive) + target; SYNC_SP(); GOTO_UNWIND(); } diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 43b022107a9ae6f..7403d6fdaf0e2b2 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4210,6 +4210,8 @@ case _ERROR_POP_N: { oparg = CURRENT_OPARG(); + uint32_t target = (uint32_t)CURRENT_OPERAND(); + frame->instr_ptr = ((_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive) + target; stack_pointer += -oparg; GOTO_UNWIND(); break; diff --git a/Python/optimizer.c b/Python/optimizer.c index 6a8b4f3c9504ade..b17c2998e2504bf 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -978,6 +978,7 @@ prepare_for_execution(_PyUOpInstruction *buffer, int length) current_error_target = target; make_exit(&buffer[next_spare], _ERROR_POP_N, 0); buffer[next_spare].oparg = popped; + buffer[next_spare].operand = target; next_spare++; } buffer[i].error_target = current_error; diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 76de6e50f1f786c..a76edd62c94c131 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -554,9 +554,6 @@ remove_unneeded_uops(_PyUOpInstruction *buffer, int buffer_size) needs_ip = true; may_have_escaped = true; } - if (_PyUop_Flags[opcode] & HAS_ERROR_FLAG) { - needs_ip = true; - } if (needs_ip && last_set_ip >= 0) { if (buffer[last_set_ip].opcode == _CHECK_VALIDITY) { buffer[last_set_ip].opcode = _CHECK_VALIDITY_AND_SET_IP; From 8227883d1f1bbb6560e5f175d7ee49f013c094bd Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Wed, 24 Apr 2024 15:55:02 +0100 Subject: [PATCH 114/127] gh-118013: Use weakrefs for the cache key in `inspect._shadowed_dict` (#118202) --- Doc/whatsnew/3.12.rst | 7 +++--- Lib/inspect.py | 25 ++++++++++++++++--- Lib/test/libregrtest/utils.py | 2 +- Lib/test/test_inspect/test_inspect.py | 24 ++++++++++++++++++ ...-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst | 9 +++++++ 5 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index ce3d9ec6a29de8e..8757311a484257d 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -734,8 +734,7 @@ inspect * The performance of :func:`inspect.getattr_static` has been considerably improved. Most calls to the function should be at least 2x faster than they - were in Python 3.11, and some may be 6x faster or more. (Contributed by Alex - Waygood in :gh:`103193`.) + were in Python 3.11. (Contributed by Alex Waygood in :gh:`103193`.) itertools --------- @@ -1006,8 +1005,8 @@ typing :func:`runtime-checkable protocols ` has changed significantly. Most ``isinstance()`` checks against protocols with only a few members should be at least 2x faster than in 3.11, and some may be 20x - faster or more. However, ``isinstance()`` checks against protocols with fourteen - or more members may be slower than in Python 3.11. (Contributed by Alex + faster or more. However, ``isinstance()`` checks against protocols with many + members may be slower than in Python 3.11. (Contributed by Alex Waygood in :gh:`74690` and :gh:`103193`.) * All :data:`typing.TypedDict` and :data:`typing.NamedTuple` classes now have the diff --git a/Lib/inspect.py b/Lib/inspect.py index 422c09a92ad1417..3c346b27b1f06dd 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -160,6 +160,7 @@ from keyword import iskeyword from operator import attrgetter from collections import namedtuple, OrderedDict +from weakref import ref as make_weakref # Create constants for the compiler flags in Include/code.h # We try to get them from dis to avoid duplication @@ -1832,9 +1833,16 @@ def _check_class(klass, attr): return entry.__dict__[attr] return _sentinel + @functools.lru_cache() -def _shadowed_dict_from_mro_tuple(mro): - for entry in mro: +def _shadowed_dict_from_weakref_mro_tuple(*weakref_mro): + for weakref_entry in weakref_mro: + # Normally we'd have to check whether the result of weakref_entry() + # is None here, in case the object the weakref is pointing to has died. + # In this specific case, however, we know that the only caller of this + # function is `_shadowed_dict()`, and that therefore this weakref is + # guaranteed to point to an object that is still alive. + entry = weakref_entry() dunder_dict = _get_dunder_dict_of_class(entry) if '__dict__' in dunder_dict: class_dict = dunder_dict['__dict__'] @@ -1844,8 +1852,19 @@ def _shadowed_dict_from_mro_tuple(mro): return class_dict return _sentinel + def _shadowed_dict(klass): - return _shadowed_dict_from_mro_tuple(_static_getmro(klass)) + # gh-118013: the inner function here is decorated with lru_cache for + # performance reasons, *but* make sure not to pass strong references + # to the items in the mro. Doing so can lead to unexpected memory + # consumption in cases where classes are dynamically created and + # destroyed, and the dynamically created classes happen to be the only + # objects that hold strong references to other objects that take up a + # significant amount of memory. + return _shadowed_dict_from_weakref_mro_tuple( + *[make_weakref(entry) for entry in _static_getmro(klass)] + ) + def getattr_static(obj, attr, default=_sentinel): """Retrieve attributes without triggering dynamic lookup via the diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py index 791f996127ea58a..8253d330b95b811 100644 --- a/Lib/test/libregrtest/utils.py +++ b/Lib/test/libregrtest/utils.py @@ -275,7 +275,7 @@ def clear_caches(): except KeyError: pass else: - inspect._shadowed_dict_from_mro_tuple.cache_clear() + inspect._shadowed_dict_from_weakref_mro_tuple.cache_clear() inspect._filesbymodname.clear() inspect.modulesbyfile.clear() diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index b2265e44e0c79b8..169d1edb706fc3a 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -4,6 +4,7 @@ import copy import datetime import functools +import gc import importlib import inspect import io @@ -25,6 +26,7 @@ import unittest import unittest.mock import warnings +import weakref try: @@ -2302,6 +2304,13 @@ def __dict__(self): self.assertEqual(inspect.getattr_static(foo, 'a'), 3) self.assertFalse(test.called) + class Bar(Foo): pass + + bar = Bar() + bar.a = 5 + self.assertEqual(inspect.getattr_static(bar, 'a'), 3) + self.assertFalse(test.called) + def test_mutated_mro(self): test = self test.called = False @@ -2406,6 +2415,21 @@ def __getattribute__(self, attr): self.assertFalse(test.called) + def test_cache_does_not_cause_classes_to_persist(self): + # regression test for gh-118013: + # check that the internal _shadowed_dict cache does not cause + # dynamically created classes to have extended lifetimes even + # when no other strong references to those classes remain. + # Since these classes can themselves hold strong references to + # other objects, this can cause unexpected memory consumption. + class Foo: pass + Foo.instance = Foo() + weakref_to_class = weakref.ref(Foo) + inspect.getattr_static(Foo.instance, 'whatever', 'irrelevant') + del Foo + gc.collect() + self.assertIsNone(weakref_to_class()) + class TestGetGeneratorState(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst b/Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst new file mode 100644 index 000000000000000..8eb68ebe99ba155 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-24-12-20-48.gh-issue-118013.TKn_kZ.rst @@ -0,0 +1,9 @@ +Fix regression introduced in gh-103193 that meant that calling +:func:`inspect.getattr_static` on an instance would cause a strong reference +to that instance's class to persist in an internal cache in the +:mod:`inspect` module. This caused unexpected memory consumption if the +class was dynamically created, the class held strong references to other +objects which took up a significant amount of memory, and the cache +contained the sole strong reference to the class. The fix for the regression +leads to a slowdown in :func:`getattr_static`, but the function should still +be signficantly faster than it was in Python 3.11. Patch by Alex Waygood. From af3c1d817d3f8369f8003965d967332a3a721a25 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 Apr 2024 09:55:48 -0600 Subject: [PATCH 115/127] gh-117953: Cleanups For fix_up_extension() in import.c (gh-118192) These are cleanups I've pulled out of gh-118116. Mostly, this change moves code around to align with some future changes and to improve clarity a little. There is one very small change in behavior: we now add the module to the per-interpreter caches after updating the global state, rather than before. --- Include/internal/pycore_import.h | 2 + Python/import.c | 249 +++++++++++++++++++------------ Python/importdl.c | 5 + Python/pylifecycle.c | 2 +- Python/sysmodule.c | 2 +- 5 files changed, 163 insertions(+), 97 deletions(-) diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h index 08af53258cde977..8d7f0543f8d3153 100644 --- a/Include/internal/pycore_import.h +++ b/Include/internal/pycore_import.h @@ -24,10 +24,12 @@ extern int _PyImport_ReleaseLock(PyInterpreterState *interp); // This is used exclusively for the sys and builtins modules: extern int _PyImport_FixupBuiltin( + PyThreadState *tstate, PyObject *mod, const char *name, /* UTF-8 encoded string */ PyObject *modules ); +// We could probably drop this: extern int _PyImport_FixupExtensionObject(PyObject*, PyObject *, PyObject *, PyObject *); diff --git a/Python/import.c b/Python/import.c index 8cdc04f03dd201b..30d8082607ab375 100644 --- a/Python/import.c +++ b/Python/import.c @@ -200,39 +200,54 @@ _PyImport_ClearModules(PyInterpreterState *interp) Py_SETREF(MODULES(interp), NULL); } +static inline PyObject * +get_modules_dict(PyThreadState *tstate, bool fatal) +{ + /* Technically, it would make sense to incref the dict, + * since sys.modules could be swapped out and decref'ed to 0 + * before the caller is done using it. However, that is highly + * unlikely, especially since we can rely on a global lock + * (i.e. the GIL) for thread-safety. */ + PyObject *modules = MODULES(tstate->interp); + if (modules == NULL) { + if (fatal) { + Py_FatalError("interpreter has no modules dictionary"); + } + _PyErr_SetString(tstate, PyExc_RuntimeError, + "unable to get sys.modules"); + return NULL; + } + return modules; +} + PyObject * PyImport_GetModuleDict(void) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - if (MODULES(interp) == NULL) { - Py_FatalError("interpreter has no modules dictionary"); - } - return MODULES(interp); + PyThreadState *tstate = _PyThreadState_GET(); + return get_modules_dict(tstate, true); } int _PyImport_SetModule(PyObject *name, PyObject *m) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - PyObject *modules = MODULES(interp); + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *modules = get_modules_dict(tstate, true); return PyObject_SetItem(modules, name, m); } int _PyImport_SetModuleString(const char *name, PyObject *m) { - PyInterpreterState *interp = _PyInterpreterState_GET(); - PyObject *modules = MODULES(interp); + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *modules = get_modules_dict(tstate, true); return PyMapping_SetItemString(modules, name, m); } static PyObject * import_get_module(PyThreadState *tstate, PyObject *name) { - PyObject *modules = MODULES(tstate->interp); + PyObject *modules = get_modules_dict(tstate, false); if (modules == NULL) { - _PyErr_SetString(tstate, PyExc_RuntimeError, - "unable to get sys.modules"); return NULL; } @@ -297,10 +312,8 @@ PyImport_GetModule(PyObject *name) static PyObject * import_add_module(PyThreadState *tstate, PyObject *name) { - PyObject *modules = MODULES(tstate->interp); + PyObject *modules = get_modules_dict(tstate, false); if (modules == NULL) { - _PyErr_SetString(tstate, PyExc_RuntimeError, - "no import module dictionary"); return NULL; } @@ -397,7 +410,7 @@ remove_module(PyThreadState *tstate, PyObject *name) { PyObject *exc = _PyErr_GetRaisedException(tstate); - PyObject *modules = MODULES(tstate->interp); + PyObject *modules = get_modules_dict(tstate, true); if (PyDict_CheckExact(modules)) { // Error is reported to the caller (void)PyDict_Pop(modules, name, NULL); @@ -618,77 +631,91 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp) ...for single-phase init modules, where m_size == -1: (6). first time (not found in _PyRuntime.imports.extensions): - 1. _imp_create_dynamic_impl() -> import_find_extension() - 2. _imp_create_dynamic_impl() -> _PyImport_LoadDynamicModuleWithSpec() - 3. _PyImport_LoadDynamicModuleWithSpec(): load - 4. _PyImport_LoadDynamicModuleWithSpec(): call - 5. -> PyModule_Create() -> PyModule_Create2() -> PyModule_CreateInitialized() - 6. PyModule_CreateInitialized() -> PyModule_New() - 7. PyModule_CreateInitialized(): allocate mod->md_state - 8. PyModule_CreateInitialized() -> PyModule_AddFunctions() - 9. PyModule_CreateInitialized() -> PyModule_SetDocString() - 10. PyModule_CreateInitialized(): set mod->md_def - 11. : initialize the module - 12. _PyImport_LoadDynamicModuleWithSpec() -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed() - 13. _PyImport_LoadDynamicModuleWithSpec(): set def->m_base.m_init - 14. _PyImport_LoadDynamicModuleWithSpec(): set __file__ - 15. _PyImport_LoadDynamicModuleWithSpec() -> _PyImport_FixupExtensionObject() - 16. _PyImport_FixupExtensionObject(): add it to interp->imports.modules_by_index - 17. _PyImport_FixupExtensionObject(): copy __dict__ into def->m_base.m_copy - 18. _PyImport_FixupExtensionObject(): add it to _PyRuntime.imports.extensions + A. _imp_create_dynamic_impl() -> import_find_extension() + B. _imp_create_dynamic_impl() -> _PyImport_LoadDynamicModuleWithSpec() + C. _PyImport_LoadDynamicModuleWithSpec(): load + D. _PyImport_LoadDynamicModuleWithSpec(): call + E. -> PyModule_Create() -> PyModule_Create2() + -> PyModule_CreateInitialized() + F. PyModule_CreateInitialized() -> PyModule_New() + G. PyModule_CreateInitialized(): allocate mod->md_state + H. PyModule_CreateInitialized() -> PyModule_AddFunctions() + I. PyModule_CreateInitialized() -> PyModule_SetDocString() + J. PyModule_CreateInitialized(): set mod->md_def + K. : initialize the module, etc. + L. _PyImport_LoadDynamicModuleWithSpec() + -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed() + M. _PyImport_LoadDynamicModuleWithSpec(): set def->m_base.m_init + N. _PyImport_LoadDynamicModuleWithSpec() -> _PyImport_FixupExtensionObject() + O. _PyImport_FixupExtensionObject() -> update_global_state_for_extension() + P. update_global_state_for_extension(): + copy __dict__ into def->m_base.m_copy + Q. update_global_state_for_extension(): + add it to _PyRuntime.imports.extensions + R. _PyImport_FixupExtensionObject() -> finish_singlephase_extension() + S. finish_singlephase_extension(): + add it to interp->imports.modules_by_index + T. finish_singlephase_extension(): add it to sys.modules + U. _imp_create_dynamic_impl(): set __file__ + + Step (P) is skipped for core modules (sys/builtins). (6). subsequent times (found in _PyRuntime.imports.extensions): - 1. _imp_create_dynamic_impl() -> import_find_extension() - 2. import_find_extension() -> import_add_module() - 3. if name in sys.modules: use that module - 4. else: + A. _imp_create_dynamic_impl() -> import_find_extension() + B. import_find_extension() -> import_add_module() + C. if name in sys.modules: use that module + D. else: 1. import_add_module() -> PyModule_NewObject() 2. import_add_module(): set it on sys.modules - 5. import_find_extension(): copy the "m_copy" dict into __dict__ - 6. _imp_create_dynamic_impl() -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed() + E. import_find_extension(): copy the "m_copy" dict into __dict__ + F. _imp_create_dynamic_impl() + -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed() (10). (every time): - 1. noop + A. noop ...for single-phase init modules, where m_size >= 0: (6). not main interpreter and never loaded there - every time (not found in _PyRuntime.imports.extensions): - 1-16. (same as for m_size == -1) + A-N. (same as for m_size == -1) + O-Q. (skipped) + R-U. (same as for m_size == -1) (6). main interpreter - first time (not found in _PyRuntime.imports.extensions): - 1-16. (same as for m_size == -1) - 17. _PyImport_FixupExtensionObject(): add it to _PyRuntime.imports.extensions + A-O. (same as for m_size == -1) + P. (skipped) + Q-U. (same as for m_size == -1) (6). previously loaded in main interpreter (found in _PyRuntime.imports.extensions): - 1. _imp_create_dynamic_impl() -> import_find_extension() - 2. import_find_extension(): call def->m_base.m_init - 3. import_find_extension(): add the module to sys.modules + A. _imp_create_dynamic_impl() -> import_find_extension() + B. import_find_extension(): call def->m_base.m_init + C. import_find_extension(): add the module to sys.modules (10). every time: - 1. noop + A. noop ...for multi-phase init modules: (6). every time: - 1. _imp_create_dynamic_impl() -> import_find_extension() (not found) - 2. _imp_create_dynamic_impl() -> _PyImport_LoadDynamicModuleWithSpec() - 3. _PyImport_LoadDynamicModuleWithSpec(): load module init func - 4. _PyImport_LoadDynamicModuleWithSpec(): call module init func - 5. _PyImport_LoadDynamicModuleWithSpec() -> PyModule_FromDefAndSpec() - 6. PyModule_FromDefAndSpec(): gather/check moduledef slots - 7. if there's a Py_mod_create slot: + A. _imp_create_dynamic_impl() -> import_find_extension() (not found) + B. _imp_create_dynamic_impl() -> _PyImport_LoadDynamicModuleWithSpec() + C. _PyImport_LoadDynamicModuleWithSpec(): load module init func + D. _PyImport_LoadDynamicModuleWithSpec(): call module init func + E. _PyImport_LoadDynamicModuleWithSpec() -> PyModule_FromDefAndSpec() + F. PyModule_FromDefAndSpec(): gather/check moduledef slots + G. if there's a Py_mod_create slot: 1. PyModule_FromDefAndSpec(): call its function - 8. else: + H. else: 1. PyModule_FromDefAndSpec() -> PyModule_NewObject() - 9: PyModule_FromDefAndSpec(): set mod->md_def - 10. PyModule_FromDefAndSpec() -> _add_methods_to_object() - 11. PyModule_FromDefAndSpec() -> PyModule_SetDocString() + I: PyModule_FromDefAndSpec(): set mod->md_def + J. PyModule_FromDefAndSpec() -> _add_methods_to_object() + K. PyModule_FromDefAndSpec() -> PyModule_SetDocString() (10). every time: - 1. _imp_exec_dynamic_impl() -> exec_builtin_or_dynamic() - 2. if mod->md_state == NULL (including if m_size == 0): + A. _imp_exec_dynamic_impl() -> exec_builtin_or_dynamic() + B. if mod->md_state == NULL (including if m_size == 0): 1. exec_builtin_or_dynamic() -> PyModule_ExecDef() 2. PyModule_ExecDef(): allocate mod->md_state 3. if there's a Py_mod_exec slot: @@ -894,7 +921,7 @@ extensions_lock_release(void) (module name, module name) (for built-in modules) or by (filename, module name) (for dynamically loaded modules), containing these modules. A copy of the module's dictionary is stored by calling - _PyImport_FixupExtensionObject() immediately after the module initialization + fix_up_extension() immediately after the module initialization function succeeds. A copy can be retrieved from there by calling import_find_extension(). @@ -1158,24 +1185,14 @@ is_core_module(PyInterpreterState *interp, PyObject *name, PyObject *path) return 0; } + static int -fix_up_extension(PyObject *mod, PyObject *name, PyObject *path) +update_global_state_for_extension(PyThreadState *tstate, + PyObject *mod, PyModuleDef *def, + PyObject *name, PyObject *path) { - if (mod == NULL || !PyModule_Check(mod)) { - PyErr_BadInternalCall(); - return -1; - } - - struct PyModuleDef *def = PyModule_GetDef(mod); - if (!def) { - PyErr_BadInternalCall(); - return -1; - } - - PyThreadState *tstate = _PyThreadState_GET(); - if (_modules_by_index_set(tstate->interp, def, mod) < 0) { - return -1; - } + assert(mod != NULL && PyModule_Check(mod)); + assert(def == _PyModule_GetDef(mod)); // bpo-44050: Extensions and def->m_base.m_copy can be updated // when the extension module doesn't support sub-interpreters. @@ -1202,6 +1219,10 @@ fix_up_extension(PyObject *mod, PyObject *name, PyObject *path) // XXX Why special-case the main interpreter? if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) { +#ifndef NDEBUG + PyModuleDef *cached = _extensions_cache_get(path, name); + assert(cached == NULL || cached == def); +#endif if (_extensions_cache_set(path, name, def) < 0) { return -1; } @@ -1210,15 +1231,50 @@ fix_up_extension(PyObject *mod, PyObject *name, PyObject *path) return 0; } +/* For multi-phase init modules, the module is finished + * by PyModule_FromDefAndSpec(). */ +static int +finish_singlephase_extension(PyThreadState *tstate, + PyObject *mod, PyModuleDef *def, + PyObject *name, PyObject *modules) +{ + assert(mod != NULL && PyModule_Check(mod)); + assert(def == PyModule_GetDef(mod)); + + if (_modules_by_index_set(tstate->interp, def, mod) < 0) { + return -1; + } + + if (modules != NULL) { + if (PyObject_SetItem(modules, name, mod) < 0) { + return -1; + } + } + + return 0; +} + int _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, PyObject *filename, PyObject *modules) { - if (PyObject_SetItem(modules, name, mod) < 0) { + if (mod == NULL || !PyModule_Check(mod)) { + PyErr_BadInternalCall(); return -1; } - if (fix_up_extension(mod, name, filename) < 0) { - PyMapping_DelItem(modules, name); + PyModuleDef *def = PyModule_GetDef(mod); + if (def == NULL) { + PyErr_BadInternalCall(); + return -1; + } + + PyThreadState *tstate = _PyThreadState_GET(); + if (update_global_state_for_extension( + tstate, mod, def, name, filename) < 0) + { + return -1; + } + if (finish_singlephase_extension(tstate, mod, def, name, modules) < 0) { return -1; } return 0; @@ -1245,7 +1301,7 @@ import_find_extension(PyThreadState *tstate, PyObject *name, } PyObject *mod, *mdict; - PyObject *modules = MODULES(tstate->interp); + PyObject *modules = get_modules_dict(tstate, true); if (def->m_size == -1) { PyObject *m_copy = def->m_base.m_copy; @@ -1333,7 +1389,8 @@ clear_singlephase_extension(PyInterpreterState *interp, /*******************/ int -_PyImport_FixupBuiltin(PyObject *mod, const char *name, PyObject *modules) +_PyImport_FixupBuiltin(PyThreadState *tstate, PyObject *mod, const char *name, + PyObject *modules) { int res = -1; assert(mod != NULL && PyModule_Check(mod)); @@ -1350,11 +1407,12 @@ _PyImport_FixupBuiltin(PyObject *mod, const char *name, PyObject *modules) goto finally; } - if (PyObject_SetItem(modules, nameobj, mod) < 0) { + if (update_global_state_for_extension( + tstate, mod, def, nameobj, nameobj) < 0) + { goto finally; } - if (fix_up_extension(mod, nameobj, nameobj) < 0) { - PyMapping_DelItem(modules, nameobj); + if (finish_singlephase_extension(tstate, mod, def, nameobj, modules) < 0) { goto finally; } @@ -1391,7 +1449,6 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) return mod; } - PyObject *modules = MODULES(tstate->interp); struct _inittab *found = NULL; for (struct _inittab *p = INITTAB; p->name != NULL; p++) { if (_PyUnicode_EqualToASCIIString(name, p->name)) { @@ -1419,14 +1476,22 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec); } else { - /* Remember pointer to module init function. */ + assert(PyModule_Check(mod)); PyModuleDef *def = PyModule_GetDef(mod); if (def == NULL) { return NULL; } + /* Remember pointer to module init function. */ def->m_base.m_init = p0; - if (_PyImport_FixupExtensionObject(mod, name, name, modules) < 0) { + + if (update_global_state_for_extension( + tstate, mod, def, name, name) < 0) + { + return NULL; + } + PyObject *modules = get_modules_dict(tstate, true); + if (finish_singlephase_extension(tstate, mod, def, name, modules) < 0) { return NULL; } return mod; @@ -3783,12 +3848,6 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) } mod = _PyImport_LoadDynamicModuleWithSpec(spec, fp); - if (mod != NULL) { - /* Remember the filename as the __file__ attribute */ - if (PyModule_AddObjectRef(mod, "__file__", filename) < 0) { - PyErr_Clear(); /* Not important enough to report */ - } - } // XXX Shouldn't this happen in the error cases too. if (fp) { diff --git a/Python/importdl.c b/Python/importdl.c index 7cf30bea3a861ab..e512161d3071f2d 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -226,6 +226,11 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) } def->m_base.m_init = p0; + /* Remember the filename as the __file__ attribute */ + if (PyModule_AddObjectRef(m, "__file__", filename) < 0) { + PyErr_Clear(); /* Not important enough to report */ + } + PyObject *modules = PyImport_GetModuleDict(); if (_PyImport_FixupExtensionObject(m, name_unicode, filename, modules) < 0) goto error; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index cc1824634e7a7f5..0f3ca4a66875144 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -777,7 +777,7 @@ pycore_init_builtins(PyThreadState *tstate) } PyObject *modules = _PyImport_GetModules(interp); - if (_PyImport_FixupBuiltin(bimod, "builtins", modules) < 0) { + if (_PyImport_FixupBuiltin(tstate, bimod, "builtins", modules) < 0) { goto error; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 05ee4051a20e18d..7af363678e8e867 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -3764,7 +3764,7 @@ _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p) return status; } - if (_PyImport_FixupBuiltin(sysmod, "sys", modules) < 0) { + if (_PyImport_FixupBuiltin(tstate, sysmod, "sys", modules) < 0) { goto error; } From 03e3e317231d67557191ee067cb7f192f3d4d092 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 Apr 2024 10:18:24 -0600 Subject: [PATCH 116/127] gh-76785: Rename _xxsubinterpreters to _interpreters (gh-117791) See https://discuss.python.org/t/pep-734-multiple-interpreters-in-the-stdlib/41147/26. --- Include/internal/pycore_atexit.h | 2 +- Include/internal/pycore_pybuffer.h | 2 +- Include/internal/pycore_pystate.h | 4 +- Include/internal/pycore_pythread.h | 4 +- Lib/test/support/import_helper.py | 2 +- Lib/test/support/interpreters/__init__.py | 4 +- Lib/test/support/interpreters/channels.py | 4 +- Lib/test/support/interpreters/queues.py | 4 +- ...erpchannels.py => test__interpchannels.py} | 844 +++++++++--------- ...binterpreters.py => test__interpreters.py} | 22 +- Lib/test/test_capi/test_misc.py | 2 +- Lib/test/test_import/__init__.py | 2 +- Lib/test/test_importlib/test_util.py | 2 +- Lib/test/test_interpreters/test_api.py | 16 +- Lib/test/test_interpreters/test_channels.py | 4 +- Lib/test/test_interpreters/test_lifecycle.py | 2 +- Lib/test/test_interpreters/test_queues.py | 2 +- Lib/test/test_interpreters/test_stress.py | 2 +- Lib/test/test_interpreters/utils.py | 2 +- Makefile.pre.in | 6 +- ...4-04-11-18-11-37.gh-issue-76785.BWNkhC.rst | 6 + Modules/Setup | 6 +- Modules/Setup.stdlib.in | 7 +- ...annelsmodule.c => _interpchannelsmodule.c} | 2 +- ...rpqueuesmodule.c => _interpqueuesmodule.c} | 2 +- ...rpretersmodule.c => _interpretersmodule.c} | 2 +- PC/config.c | 12 +- PCbuild/pythoncore.vcxproj | 6 +- PCbuild/pythoncore.vcxproj.filters | 6 +- Python/stdlib_module_names.h | 3 + Tools/build/generate_stdlib_module_names.py | 3 - Tools/c-analyzer/cpython/ignored.tsv | 10 +- configure | 84 +- configure.ac | 12 +- 34 files changed, 550 insertions(+), 543 deletions(-) rename Lib/test/{test__xxinterpchannels.py => test__interpchannels.py} (68%) rename Lib/test/{test__xxsubinterpreters.py => test__interpreters.py} (98%) create mode 100644 Misc/NEWS.d/next/Library/2024-04-11-18-11-37.gh-issue-76785.BWNkhC.rst rename Modules/{_xxinterpchannelsmodule.c => _interpchannelsmodule.c} (99%) rename Modules/{_xxinterpqueuesmodule.c => _interpqueuesmodule.c} (99%) rename Modules/{_xxsubinterpretersmodule.c => _interpretersmodule.c} (99%) diff --git a/Include/internal/pycore_atexit.h b/Include/internal/pycore_atexit.h index 4dcda8f517c7873..507a5c03cbc7929 100644 --- a/Include/internal/pycore_atexit.h +++ b/Include/internal/pycore_atexit.h @@ -54,7 +54,7 @@ struct atexit_state { int callback_len; }; -// Export for '_xxinterpchannels' shared extension +// Export for '_interpchannels' shared extension PyAPI_FUNC(int) _Py_AtExit( PyInterpreterState *interp, atexit_datacallbackfunc func, diff --git a/Include/internal/pycore_pybuffer.h b/Include/internal/pycore_pybuffer.h index 3cbc290b2ea3ee5..9439d2bd770587d 100644 --- a/Include/internal/pycore_pybuffer.h +++ b/Include/internal/pycore_pybuffer.h @@ -9,7 +9,7 @@ extern "C" { #endif -// Exported for the _xxinterpchannels module. +// Exported for the _interpchannels module. PyAPI_FUNC(int) _PyBuffer_ReleaseInInterpreter( PyInterpreterState *interp, Py_buffer *view); PyAPI_FUNC(int) _PyBuffer_ReleaseInInterpreterAndRawFree( diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index eb5b5fee59009cf..a668d78b969bd93 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -77,10 +77,10 @@ _Py_IsMainInterpreterFinalizing(PyInterpreterState *interp) interp == &_PyRuntime._main_interpreter); } -// Export for _xxsubinterpreters module. +// Export for _interpreters module. PyAPI_FUNC(PyObject *) _PyInterpreterState_GetIDObject(PyInterpreterState *); -// Export for _xxsubinterpreters module. +// Export for _interpreters module. PyAPI_FUNC(int) _PyInterpreterState_SetRunningMain(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_SetNotRunningMain(PyInterpreterState *); PyAPI_FUNC(int) _PyInterpreterState_IsRunningMain(PyInterpreterState *); diff --git a/Include/internal/pycore_pythread.h b/Include/internal/pycore_pythread.h index f032cb973886572..3610c6254db6af3 100644 --- a/Include/internal/pycore_pythread.h +++ b/Include/internal/pycore_pythread.h @@ -99,7 +99,7 @@ extern void _PyThread_AfterFork(struct _pythread_runtime_state *state); // unset: -1 seconds, in nanoseconds #define PyThread_UNSET_TIMEOUT ((PyTime_t)(-1 * 1000 * 1000 * 1000)) -// Exported for the _xxinterpchannels module. +// Exported for the _interpchannels module. PyAPI_FUNC(int) PyThread_ParseTimeoutArg( PyObject *arg, int blocking, @@ -111,7 +111,7 @@ PyAPI_FUNC(int) PyThread_ParseTimeoutArg( * are returned, depending on whether the lock can be acquired within the * timeout. */ -// Exported for the _xxinterpchannels module. +// Exported for the _interpchannels module. PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed_with_retries( PyThread_type_lock, PY_TIMEOUT_T microseconds); diff --git a/Lib/test/support/import_helper.py b/Lib/test/support/import_helper.py index 29c6f535b403425..edcd2b9a35bbd9d 100644 --- a/Lib/test/support/import_helper.py +++ b/Lib/test/support/import_helper.py @@ -114,7 +114,7 @@ def multi_interp_extensions_check(enabled=True): This only applies to modules that haven't been imported yet. It overrides the PyInterpreterConfig.check_multi_interp_extensions setting (see support.run_in_subinterp_with_config() and - _xxsubinterpreters.create()). + _interpreters.create()). Also see importlib.utils.allowing_all_extensions(). """ diff --git a/Lib/test/support/interpreters/__init__.py b/Lib/test/support/interpreters/__init__.py index 0a5a9259479be47..e067f259364d2aa 100644 --- a/Lib/test/support/interpreters/__init__.py +++ b/Lib/test/support/interpreters/__init__.py @@ -2,10 +2,10 @@ import threading import weakref -import _xxsubinterpreters as _interpreters +import _interpreters # aliases: -from _xxsubinterpreters import ( +from _interpreters import ( InterpreterError, InterpreterNotFoundError, NotShareableError, is_shareable, ) diff --git a/Lib/test/support/interpreters/channels.py b/Lib/test/support/interpreters/channels.py index f7f523b1fc5a778..fbae7e634cf34d1 100644 --- a/Lib/test/support/interpreters/channels.py +++ b/Lib/test/support/interpreters/channels.py @@ -1,10 +1,10 @@ """Cross-interpreter Channels High Level Module.""" import time -import _xxinterpchannels as _channels +import _interpchannels as _channels # aliases: -from _xxinterpchannels import ( +from _interpchannels import ( ChannelError, ChannelNotFoundError, ChannelClosedError, ChannelEmptyError, ChannelNotEmptyError, ) diff --git a/Lib/test/support/interpreters/queues.py b/Lib/test/support/interpreters/queues.py index 5849a1cc15e4475..1b9e7481f2e313d 100644 --- a/Lib/test/support/interpreters/queues.py +++ b/Lib/test/support/interpreters/queues.py @@ -4,10 +4,10 @@ import queue import time import weakref -import _xxinterpqueues as _queues +import _interpqueues as _queues # aliases: -from _xxinterpqueues import ( +from _interpqueues import ( QueueError, QueueNotFoundError, ) diff --git a/Lib/test/test__xxinterpchannels.py b/Lib/test/test__interpchannels.py similarity index 68% rename from Lib/test/test__xxinterpchannels.py rename to Lib/test/test__interpchannels.py index 3db0cb7e6e1d49d..b76c58917c0b9c3 100644 --- a/Lib/test/test__xxinterpchannels.py +++ b/Lib/test/test__interpchannels.py @@ -8,14 +8,14 @@ from test.support import import_helper -from test.test__xxsubinterpreters import ( +from test.test__interpreters import ( _interpreters, _run_output, clean_up_interpreters, ) -channels = import_helper.import_module('_xxinterpchannels') +_channels = import_helper.import_module('_interpchannels') # Additional tests are found in Lib/test/test_interpreters/test_channels.py. @@ -29,8 +29,8 @@ def recv_wait(cid): while True: try: - return channels.recv(cid) - except channels.ChannelEmptyError: + return _channels.recv(cid) + except _channels.ChannelEmptyError: time.sleep(0.1) #@contextmanager @@ -101,7 +101,7 @@ def __new__(cls, name=None, id=None): def expect_channel_closed(): try: yield - except channels.ChannelClosedError: + except _channels.ChannelClosedError: pass else: assert False, 'channel not closed' @@ -188,7 +188,7 @@ def run_action(cid, action, end, state, *, hideclosed=True): try: result = _run_action(cid, action, end, state) - except channels.ChannelClosedError: + except _channels.ChannelClosedError: if not hideclosed and not expectfail: raise result = state.close() @@ -201,18 +201,18 @@ def run_action(cid, action, end, state, *, hideclosed=True): def _run_action(cid, action, end, state): if action == 'use': if end == 'send': - channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'spam', blocking=False) return state.incr() elif end == 'recv': if not state.pending: try: - channels.recv(cid) - except channels.ChannelEmptyError: + _channels.recv(cid) + except _channels.ChannelEmptyError: return state else: raise Exception('expected ChannelEmptyError') else: - channels.recv(cid) + _channels.recv(cid) return state.decr() else: raise ValueError(end) @@ -220,7 +220,7 @@ def _run_action(cid, action, end, state): kwargs = {} if end in ('recv', 'send'): kwargs[end] = True - channels.close(cid, **kwargs) + _channels.close(cid, **kwargs) return state.close() elif action == 'force-close': kwargs = { @@ -228,17 +228,17 @@ def _run_action(cid, action, end, state): } if end in ('recv', 'send'): kwargs[end] = True - channels.close(cid, **kwargs) + _channels.close(cid, **kwargs) return state.close(force=True) else: raise ValueError(action) def clean_up_channels(): - for cid in channels.list_all(): + for cid in _channels.list_all(): try: - channels.destroy(cid) - except channels.ChannelNotFoundError: + _channels.destroy(cid) + except _channels.ChannelNotFoundError: pass # already destroyed @@ -255,25 +255,25 @@ def tearDown(self): class ChannelIDTests(TestBase): def test_default_kwargs(self): - cid = channels._channel_id(10, force=True) + cid = _channels._channel_id(10, force=True) self.assertEqual(int(cid), 10) self.assertEqual(cid.end, 'both') def test_with_kwargs(self): - cid = channels._channel_id(10, send=True, force=True) + cid = _channels._channel_id(10, send=True, force=True) self.assertEqual(cid.end, 'send') - cid = channels._channel_id(10, send=True, recv=False, force=True) + cid = _channels._channel_id(10, send=True, recv=False, force=True) self.assertEqual(cid.end, 'send') - cid = channels._channel_id(10, recv=True, force=True) + cid = _channels._channel_id(10, recv=True, force=True) self.assertEqual(cid.end, 'recv') - cid = channels._channel_id(10, recv=True, send=False, force=True) + cid = _channels._channel_id(10, recv=True, send=False, force=True) self.assertEqual(cid.end, 'recv') - cid = channels._channel_id(10, send=True, recv=True, force=True) + cid = _channels._channel_id(10, send=True, recv=True, force=True) self.assertEqual(cid.end, 'both') def test_coerce_id(self): @@ -281,47 +281,47 @@ class Int(str): def __index__(self): return 10 - cid = channels._channel_id(Int(), force=True) + cid = _channels._channel_id(Int(), force=True) self.assertEqual(int(cid), 10) def test_bad_id(self): - self.assertRaises(TypeError, channels._channel_id, object()) - self.assertRaises(TypeError, channels._channel_id, 10.0) - self.assertRaises(TypeError, channels._channel_id, '10') - self.assertRaises(TypeError, channels._channel_id, b'10') - self.assertRaises(ValueError, channels._channel_id, -1) - self.assertRaises(OverflowError, channels._channel_id, 2**64) + self.assertRaises(TypeError, _channels._channel_id, object()) + self.assertRaises(TypeError, _channels._channel_id, 10.0) + self.assertRaises(TypeError, _channels._channel_id, '10') + self.assertRaises(TypeError, _channels._channel_id, b'10') + self.assertRaises(ValueError, _channels._channel_id, -1) + self.assertRaises(OverflowError, _channels._channel_id, 2**64) def test_bad_kwargs(self): with self.assertRaises(ValueError): - channels._channel_id(10, send=False, recv=False) + _channels._channel_id(10, send=False, recv=False) def test_does_not_exist(self): - cid = channels.create() - with self.assertRaises(channels.ChannelNotFoundError): - channels._channel_id(int(cid) + 1) # unforced + cid = _channels.create() + with self.assertRaises(_channels.ChannelNotFoundError): + _channels._channel_id(int(cid) + 1) # unforced def test_str(self): - cid = channels._channel_id(10, force=True) + cid = _channels._channel_id(10, force=True) self.assertEqual(str(cid), '10') def test_repr(self): - cid = channels._channel_id(10, force=True) + cid = _channels._channel_id(10, force=True) self.assertEqual(repr(cid), 'ChannelID(10)') - cid = channels._channel_id(10, send=True, force=True) + cid = _channels._channel_id(10, send=True, force=True) self.assertEqual(repr(cid), 'ChannelID(10, send=True)') - cid = channels._channel_id(10, recv=True, force=True) + cid = _channels._channel_id(10, recv=True, force=True) self.assertEqual(repr(cid), 'ChannelID(10, recv=True)') - cid = channels._channel_id(10, send=True, recv=True, force=True) + cid = _channels._channel_id(10, send=True, recv=True, force=True) self.assertEqual(repr(cid), 'ChannelID(10)') def test_equality(self): - cid1 = channels.create() - cid2 = channels._channel_id(int(cid1)) - cid3 = channels.create() + cid1 = _channels.create() + cid2 = _channels._channel_id(int(cid1)) + cid3 = _channels.create() self.assertTrue(cid1 == cid1) self.assertTrue(cid1 == cid2) @@ -341,11 +341,11 @@ def test_equality(self): self.assertTrue(cid1 != cid3) def test_shareable(self): - chan = channels.create() + chan = _channels.create() - obj = channels.create() - channels.send(chan, obj, blocking=False) - got = channels.recv(chan) + obj = _channels.create() + _channels.send(chan, obj, blocking=False) + got = _channels.recv(chan) self.assertEqual(got, obj) self.assertIs(type(got), type(obj)) @@ -356,15 +356,15 @@ def test_shareable(self): class ChannelTests(TestBase): def test_create_cid(self): - cid = channels.create() - self.assertIsInstance(cid, channels.ChannelID) + cid = _channels.create() + self.assertIsInstance(cid, _channels.ChannelID) def test_sequential_ids(self): - before = channels.list_all() - id1 = channels.create() - id2 = channels.create() - id3 = channels.create() - after = channels.list_all() + before = _channels.list_all() + id1 = _channels.create() + id2 = _channels.create() + id3 = _channels.create() + after = _channels.list_all() self.assertEqual(id2, int(id1) + 1) self.assertEqual(id3, int(id2) + 1) @@ -373,7 +373,7 @@ def test_sequential_ids(self): def test_ids_global(self): id1 = _interpreters.create() out = _run_output(id1, dedent(""" - import _xxinterpchannels as _channels + import _interpchannels as _channels cid = _channels.create() print(cid) """)) @@ -381,7 +381,7 @@ def test_ids_global(self): id2 = _interpreters.create() out = _run_output(id2, dedent(""" - import _xxinterpchannels as _channels + import _interpchannels as _channels cid = _channels.create() print(cid) """)) @@ -392,31 +392,31 @@ def test_ids_global(self): def test_channel_list_interpreters_none(self): """Test listing interpreters for a channel with no associations.""" # Test for channel with no associated _interpreters. - cid = channels.create() - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + cid = _channels.create() + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(send_interps, []) self.assertEqual(recv_interps, []) def test_channel_list_interpreters_basic(self): """Test basic listing channel _interpreters.""" interp0, *_ = _interpreters.get_main() - cid = channels.create() - channels.send(cid, "send", blocking=False) + cid = _channels.create() + _channels.send(cid, "send", blocking=False) # Test for a channel that has one end associated to an interpreter. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(send_interps, [interp0]) self.assertEqual(recv_interps, []) interp1 = _interpreters.create() _run_output(interp1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.recv({cid}) """)) # Test for channel that has both ends associated to an interpreter. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(send_interps, [interp0]) self.assertEqual(recv_interps, [interp1]) @@ -426,23 +426,23 @@ def test_channel_list_interpreters_multiple(self): interp1 = _interpreters.create() interp2 = _interpreters.create() interp3 = _interpreters.create() - cid = channels.create() + cid = _channels.create() - channels.send(cid, "send", blocking=False) + _channels.send(cid, "send", blocking=False) _run_output(interp1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.send({cid}, "send", blocking=False) """)) _run_output(interp2, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.recv({cid}) """)) _run_output(interp3, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.recv({cid}) """)) - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(set(send_interps), {interp0, interp1}) self.assertEqual(set(recv_interps), {interp2, interp3}) @@ -450,22 +450,22 @@ def test_channel_list_interpreters_destroyed(self): """Test listing channel interpreters with a destroyed interpreter.""" interp0, *_ = _interpreters.get_main() interp1 = _interpreters.create() - cid = channels.create() - channels.send(cid, "send", blocking=False) + cid = _channels.create() + _channels.send(cid, "send", blocking=False) _run_output(interp1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.recv({cid}) """)) # Should be one interpreter associated with each end. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(send_interps, [interp0]) self.assertEqual(recv_interps, [interp1]) _interpreters.destroy(interp1) # Destroyed interpreter should not be listed. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(send_interps, [interp0]) self.assertEqual(recv_interps, []) @@ -476,39 +476,39 @@ def test_channel_list_interpreters_released(self): interp0, *_ = _interpreters.get_main() interp1 = _interpreters.create() interp2 = _interpreters.create() - cid = channels.create() - channels.send(cid, "data", blocking=False) + cid = _channels.create() + _channels.send(cid, "data", blocking=False) _run_output(interp1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.recv({cid}) """)) - channels.send(cid, "data", blocking=False) + _channels.send(cid, "data", blocking=False) _run_output(interp2, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.recv({cid}) """)) # Check the setup. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(len(send_interps), 1) self.assertEqual(len(recv_interps), 2) # Release the main interpreter from the send end. - channels.release(cid, send=True) + _channels.release(cid, send=True) # Send end should have no associated _interpreters. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(len(send_interps), 0) self.assertEqual(len(recv_interps), 2) # Release one of the subinterpreters from the receive end. _run_output(interp2, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.release({cid}) """)) # Receive end should have the released interpreter removed. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(len(send_interps), 0) self.assertEqual(recv_interps, [interp1]) @@ -516,61 +516,61 @@ def test_channel_list_interpreters_closed(self): """Test listing channel interpreters with a closed channel.""" interp0, *_ = _interpreters.get_main() interp1 = _interpreters.create() - cid = channels.create() + cid = _channels.create() # Put something in the channel so that it's not empty. - channels.send(cid, "send", blocking=False) + _channels.send(cid, "send", blocking=False) # Check initial state. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(len(send_interps), 1) self.assertEqual(len(recv_interps), 0) # Force close the channel. - channels.close(cid, force=True) + _channels.close(cid, force=True) # Both ends should raise an error. - with self.assertRaises(channels.ChannelClosedError): - channels.list_interpreters(cid, send=True) - with self.assertRaises(channels.ChannelClosedError): - channels.list_interpreters(cid, send=False) + with self.assertRaises(_channels.ChannelClosedError): + _channels.list_interpreters(cid, send=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.list_interpreters(cid, send=False) def test_channel_list_interpreters_closed_send_end(self): """Test listing channel interpreters with a channel's send end closed.""" interp0, *_ = _interpreters.get_main() interp1 = _interpreters.create() - cid = channels.create() + cid = _channels.create() # Put something in the channel so that it's not empty. - channels.send(cid, "send", blocking=False) + _channels.send(cid, "send", blocking=False) # Check initial state. - send_interps = channels.list_interpreters(cid, send=True) - recv_interps = channels.list_interpreters(cid, send=False) + send_interps = _channels.list_interpreters(cid, send=True) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(len(send_interps), 1) self.assertEqual(len(recv_interps), 0) # Close the send end of the channel. - channels.close(cid, send=True) + _channels.close(cid, send=True) # Send end should raise an error. - with self.assertRaises(channels.ChannelClosedError): - channels.list_interpreters(cid, send=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.list_interpreters(cid, send=True) # Receive end should not be closed (since channel is not empty). - recv_interps = channels.list_interpreters(cid, send=False) + recv_interps = _channels.list_interpreters(cid, send=False) self.assertEqual(len(recv_interps), 0) # Close the receive end of the channel from a subinterpreter. _run_output(interp1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.close({cid}, force=True) """)) return # Both ends should raise an error. - with self.assertRaises(channels.ChannelClosedError): - channels.list_interpreters(cid, send=True) - with self.assertRaises(channels.ChannelClosedError): - channels.list_interpreters(cid, send=False) + with self.assertRaises(_channels.ChannelClosedError): + _channels.list_interpreters(cid, send=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.list_interpreters(cid, send=False) def test_allowed_types(self): - cid = channels.create() + cid = _channels.create() objects = [ None, 'spam', @@ -579,8 +579,8 @@ def test_allowed_types(self): ] for obj in objects: with self.subTest(obj): - channels.send(cid, obj, blocking=False) - got = channels.recv(cid) + _channels.send(cid, obj, blocking=False) + got = _channels.recv(cid) self.assertEqual(got, obj) self.assertIs(type(got), type(obj)) @@ -589,16 +589,16 @@ def test_allowed_types(self): # XXX What about between interpreters? def test_run_string_arg_unresolved(self): - cid = channels.create() + cid = _channels.create() interp = _interpreters.create() _interpreters.set___main___attrs(interp, dict(cid=cid.send)) out = _run_output(interp, dedent(""" - import _xxinterpchannels as _channels + import _interpchannels as _channels print(cid.end) _channels.send(cid, b'spam', blocking=False) """)) - obj = channels.recv(cid) + obj = _channels.recv(cid) self.assertEqual(obj, b'spam') self.assertEqual(out.strip(), 'send') @@ -608,17 +608,17 @@ def test_run_string_arg_unresolved(self): # Note: this test caused crashes on some buildbots (bpo-33615). @unittest.skip('disabled until high-level channels exist') def test_run_string_arg_resolved(self): - cid = channels.create() - cid = channels._channel_id(cid, _resolve=True) + cid = _channels.create() + cid = _channels._channel_id(cid, _resolve=True) interp = _interpreters.create() out = _run_output(interp, dedent(""" - import _xxinterpchannels as _channels + import _interpchannels as _channels print(chan.id.end) _channels.send(chan.id, b'spam', blocking=False) """), dict(chan=cid.send)) - obj = channels.recv(cid) + obj = _channels.recv(cid) self.assertEqual(obj, b'spam') self.assertEqual(out.strip(), 'send') @@ -627,10 +627,10 @@ def test_run_string_arg_resolved(self): # send/recv def test_send_recv_main(self): - cid = channels.create() + cid = _channels.create() orig = b'spam' - channels.send(cid, orig, blocking=False) - obj = channels.recv(cid) + _channels.send(cid, orig, blocking=False) + obj = _channels.recv(cid) self.assertEqual(obj, orig) self.assertIsNot(obj, orig) @@ -638,7 +638,7 @@ def test_send_recv_main(self): def test_send_recv_same_interpreter(self): id1 = _interpreters.create() out = _run_output(id1, dedent(""" - import _xxinterpchannels as _channels + import _interpchannels as _channels cid = _channels.create() orig = b'spam' _channels.send(cid, orig, blocking=False) @@ -648,33 +648,33 @@ def test_send_recv_same_interpreter(self): """)) def test_send_recv_different_interpreters(self): - cid = channels.create() + cid = _channels.create() id1 = _interpreters.create() out = _run_output(id1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.send({cid}, b'spam', blocking=False) """)) - obj = channels.recv(cid) + obj = _channels.recv(cid) self.assertEqual(obj, b'spam') def test_send_recv_different_threads(self): - cid = channels.create() + cid = _channels.create() def f(): obj = recv_wait(cid) - channels.send(cid, obj) + _channels.send(cid, obj) t = threading.Thread(target=f) t.start() - channels.send(cid, b'spam') + _channels.send(cid, b'spam') obj = recv_wait(cid) t.join() self.assertEqual(obj, b'spam') def test_send_recv_different_interpreters_and_threads(self): - cid = channels.create() + cid = _channels.create() id1 = _interpreters.create() out = None @@ -682,7 +682,7 @@ def f(): nonlocal out out = _run_output(id1, dedent(f""" import time - import _xxinterpchannels as _channels + import _interpchannels as _channels while True: try: obj = _channels.recv({cid}) @@ -695,38 +695,38 @@ def f(): t = threading.Thread(target=f) t.start() - channels.send(cid, b'spam') + _channels.send(cid, b'spam') obj = recv_wait(cid) t.join() self.assertEqual(obj, b'eggs') def test_send_not_found(self): - with self.assertRaises(channels.ChannelNotFoundError): - channels.send(10, b'spam') + with self.assertRaises(_channels.ChannelNotFoundError): + _channels.send(10, b'spam') def test_recv_not_found(self): - with self.assertRaises(channels.ChannelNotFoundError): - channels.recv(10) + with self.assertRaises(_channels.ChannelNotFoundError): + _channels.recv(10) def test_recv_empty(self): - cid = channels.create() - with self.assertRaises(channels.ChannelEmptyError): - channels.recv(cid) + cid = _channels.create() + with self.assertRaises(_channels.ChannelEmptyError): + _channels.recv(cid) def test_recv_default(self): default = object() - cid = channels.create() - obj1 = channels.recv(cid, default) - channels.send(cid, None, blocking=False) - channels.send(cid, 1, blocking=False) - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'eggs', blocking=False) - obj2 = channels.recv(cid, default) - obj3 = channels.recv(cid, default) - obj4 = channels.recv(cid) - obj5 = channels.recv(cid, default) - obj6 = channels.recv(cid, default) + cid = _channels.create() + obj1 = _channels.recv(cid, default) + _channels.send(cid, None, blocking=False) + _channels.send(cid, 1, blocking=False) + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'eggs', blocking=False) + obj2 = _channels.recv(cid, default) + obj3 = _channels.recv(cid, default) + obj4 = _channels.recv(cid) + obj5 = _channels.recv(cid, default) + obj6 = _channels.recv(cid, default) self.assertIs(obj1, default) self.assertIs(obj2, None) @@ -737,32 +737,32 @@ def test_recv_default(self): def test_recv_sending_interp_destroyed(self): with self.subTest('closed'): - cid1 = channels.create() + cid1 = _channels.create() interp = _interpreters.create() _interpreters.run_string(interp, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.send({cid1}, b'spam', blocking=False) """)) _interpreters.destroy(interp) with self.assertRaisesRegex(RuntimeError, f'channel {cid1} is closed'): - channels.recv(cid1) + _channels.recv(cid1) del cid1 with self.subTest('still open'): - cid2 = channels.create() + cid2 = _channels.create() interp = _interpreters.create() _interpreters.run_string(interp, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.send({cid2}, b'spam', blocking=False) """)) - channels.send(cid2, b'eggs', blocking=False) + _channels.send(cid2, b'eggs', blocking=False) _interpreters.destroy(interp) - channels.recv(cid2) + _channels.recv(cid2) with self.assertRaisesRegex(RuntimeError, f'channel {cid2} is empty'): - channels.recv(cid2) + _channels.recv(cid2) del cid2 #------------------- @@ -770,9 +770,9 @@ def test_recv_sending_interp_destroyed(self): def test_send_buffer(self): buf = bytearray(b'spamspamspam') - cid = channels.create() - channels.send_buffer(cid, buf, blocking=False) - obj = channels.recv(cid) + cid = _channels.create() + _channels.send_buffer(cid, buf, blocking=False) + obj = _channels.recv(cid) self.assertIsNot(obj, buf) self.assertIsInstance(obj, memoryview) @@ -790,18 +790,18 @@ def build_send_waiter(self, obj, *, buffer=False): # We want a long enough sleep that send() actually has to wait. if buffer: - send = channels.send_buffer + send = _channels.send_buffer else: - send = channels.send + send = _channels.send - cid = channels.create() + cid = _channels.create() try: started = time.monotonic() send(cid, obj, blocking=False) stopped = time.monotonic() - channels.recv(cid) + _channels.recv(cid) finally: - channels.destroy(cid) + _channels.destroy(cid) delay = stopped - started # seconds delay *= 3 @@ -813,14 +813,14 @@ def test_send_blocking_waiting(self): received = None obj = b'spam' wait = self.build_send_waiter(obj) - cid = channels.create() + cid = _channels.create() def f(): nonlocal received wait() received = recv_wait(cid) t = threading.Thread(target=f) t.start() - channels.send(cid, obj, blocking=True) + _channels.send(cid, obj, blocking=True) t.join() self.assertEqual(received, obj) @@ -829,14 +829,14 @@ def test_send_buffer_blocking_waiting(self): received = None obj = bytearray(b'spam') wait = self.build_send_waiter(obj, buffer=True) - cid = channels.create() + cid = _channels.create() def f(): nonlocal received wait() received = recv_wait(cid) t = threading.Thread(target=f) t.start() - channels.send_buffer(cid, obj, blocking=True) + _channels.send_buffer(cid, obj, blocking=True) t.join() self.assertEqual(received, obj) @@ -844,13 +844,13 @@ def f(): def test_send_blocking_no_wait(self): received = None obj = b'spam' - cid = channels.create() + cid = _channels.create() def f(): nonlocal received received = recv_wait(cid) t = threading.Thread(target=f) t.start() - channels.send(cid, obj, blocking=True) + _channels.send(cid, obj, blocking=True) t.join() self.assertEqual(received, obj) @@ -858,13 +858,13 @@ def f(): def test_send_buffer_blocking_no_wait(self): received = None obj = bytearray(b'spam') - cid = channels.create() + cid = _channels.create() def f(): nonlocal received received = recv_wait(cid) t = threading.Thread(target=f) t.start() - channels.send_buffer(cid, obj, blocking=True) + _channels.send_buffer(cid, obj, blocking=True) t.join() self.assertEqual(received, obj) @@ -873,25 +873,25 @@ def test_send_timeout(self): obj = b'spam' with self.subTest('non-blocking with timeout'): - cid = channels.create() + cid = _channels.create() with self.assertRaises(ValueError): - channels.send(cid, obj, blocking=False, timeout=0.1) + _channels.send(cid, obj, blocking=False, timeout=0.1) with self.subTest('timeout hit'): - cid = channels.create() + cid = _channels.create() with self.assertRaises(TimeoutError): - channels.send(cid, obj, blocking=True, timeout=0.1) - with self.assertRaises(channels.ChannelEmptyError): - received = channels.recv(cid) + _channels.send(cid, obj, blocking=True, timeout=0.1) + with self.assertRaises(_channels.ChannelEmptyError): + received = _channels.recv(cid) print(repr(received)) with self.subTest('timeout not hit'): - cid = channels.create() + cid = _channels.create() def f(): recv_wait(cid) t = threading.Thread(target=f) t.start() - channels.send(cid, obj, blocking=True, timeout=10) + _channels.send(cid, obj, blocking=True, timeout=10) t.join() def test_send_buffer_timeout(self): @@ -910,25 +910,25 @@ def test_send_buffer_timeout(self): obj = bytearray(b'spam') with self.subTest('non-blocking with timeout'): - cid = channels.create() + cid = _channels.create() with self.assertRaises(ValueError): - channels.send_buffer(cid, obj, blocking=False, timeout=0.1) + _channels.send_buffer(cid, obj, blocking=False, timeout=0.1) with self.subTest('timeout hit'): - cid = channels.create() + cid = _channels.create() with self.assertRaises(TimeoutError): - channels.send_buffer(cid, obj, blocking=True, timeout=0.1) - with self.assertRaises(channels.ChannelEmptyError): - received = channels.recv(cid) + _channels.send_buffer(cid, obj, blocking=True, timeout=0.1) + with self.assertRaises(_channels.ChannelEmptyError): + received = _channels.recv(cid) print(repr(received)) with self.subTest('timeout not hit'): - cid = channels.create() + cid = _channels.create() def f(): recv_wait(cid) t = threading.Thread(target=f) t.start() - channels.send_buffer(cid, obj, blocking=True, timeout=10) + _channels.send_buffer(cid, obj, blocking=True, timeout=10) t.join() def test_send_closed_while_waiting(self): @@ -936,25 +936,25 @@ def test_send_closed_while_waiting(self): wait = self.build_send_waiter(obj) with self.subTest('without timeout'): - cid = channels.create() + cid = _channels.create() def f(): wait() - channels.close(cid, force=True) + _channels.close(cid, force=True) t = threading.Thread(target=f) t.start() - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, obj, blocking=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, obj, blocking=True) t.join() with self.subTest('with timeout'): - cid = channels.create() + cid = _channels.create() def f(): wait() - channels.close(cid, force=True) + _channels.close(cid, force=True) t = threading.Thread(target=f) t.start() - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, obj, blocking=True, timeout=30) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, obj, blocking=True, timeout=30) t.join() def test_send_buffer_closed_while_waiting(self): @@ -974,54 +974,54 @@ def test_send_buffer_closed_while_waiting(self): wait = self.build_send_waiter(obj, buffer=True) with self.subTest('without timeout'): - cid = channels.create() + cid = _channels.create() def f(): wait() - channels.close(cid, force=True) + _channels.close(cid, force=True) t = threading.Thread(target=f) t.start() - with self.assertRaises(channels.ChannelClosedError): - channels.send_buffer(cid, obj, blocking=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send_buffer(cid, obj, blocking=True) t.join() with self.subTest('with timeout'): - cid = channels.create() + cid = _channels.create() def f(): wait() - channels.close(cid, force=True) + _channels.close(cid, force=True) t = threading.Thread(target=f) t.start() - with self.assertRaises(channels.ChannelClosedError): - channels.send_buffer(cid, obj, blocking=True, timeout=30) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send_buffer(cid, obj, blocking=True, timeout=30) t.join() #------------------- # close def test_close_single_user(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.close(cid) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.close(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_close_multiple_users(self): - cid = channels.create() + cid = _channels.create() id1 = _interpreters.create() id2 = _interpreters.create() _interpreters.run_string(id1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.send({cid}, b'spam', blocking=False) """)) _interpreters.run_string(id2, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.recv({cid}) """)) - channels.close(cid) + _channels.close(cid) excsnap = _interpreters.run_string(id1, dedent(f""" _channels.send({cid}, b'spam') @@ -1034,13 +1034,13 @@ def test_close_multiple_users(self): self.assertEqual(excsnap.type.__name__, 'ChannelClosedError') def test_close_multiple_times(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.close(cid) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.close(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.close(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.close(cid) def test_close_empty(self): tests = [ @@ -1051,149 +1051,149 @@ def test_close_empty(self): ] for send, recv in tests: with self.subTest((send, recv)): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.close(cid, send=send, recv=recv) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.close(cid, send=send, recv=recv) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_close_defaults_with_unused_items(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) - with self.assertRaises(channels.ChannelNotEmptyError): - channels.close(cid) - channels.recv(cid) - channels.send(cid, b'eggs', blocking=False) + with self.assertRaises(_channels.ChannelNotEmptyError): + _channels.close(cid) + _channels.recv(cid) + _channels.send(cid, b'eggs', blocking=False) def test_close_recv_with_unused_items_unforced(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) - - with self.assertRaises(channels.ChannelNotEmptyError): - channels.close(cid, recv=True) - channels.recv(cid) - channels.send(cid, b'eggs', blocking=False) - channels.recv(cid) - channels.recv(cid) - channels.close(cid, recv=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) + + with self.assertRaises(_channels.ChannelNotEmptyError): + _channels.close(cid, recv=True) + _channels.recv(cid) + _channels.send(cid, b'eggs', blocking=False) + _channels.recv(cid) + _channels.recv(cid) + _channels.close(cid, recv=True) def test_close_send_with_unused_items_unforced(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) - channels.close(cid, send=True) - - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - channels.recv(cid) - channels.recv(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) + _channels.close(cid, send=True) + + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + _channels.recv(cid) + _channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_close_both_with_unused_items_unforced(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) - - with self.assertRaises(channels.ChannelNotEmptyError): - channels.close(cid, recv=True, send=True) - channels.recv(cid) - channels.send(cid, b'eggs', blocking=False) - channels.recv(cid) - channels.recv(cid) - channels.close(cid, recv=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) + + with self.assertRaises(_channels.ChannelNotEmptyError): + _channels.close(cid, recv=True, send=True) + _channels.recv(cid) + _channels.send(cid, b'eggs', blocking=False) + _channels.recv(cid) + _channels.recv(cid) + _channels.close(cid, recv=True) def test_close_recv_with_unused_items_forced(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) - channels.close(cid, recv=True, force=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) + _channels.close(cid, recv=True, force=True) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_close_send_with_unused_items_forced(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) - channels.close(cid, send=True, force=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) + _channels.close(cid, send=True, force=True) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_close_both_with_unused_items_forced(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) - channels.close(cid, send=True, recv=True, force=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) + _channels.close(cid, send=True, recv=True, force=True) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_close_never_used(self): - cid = channels.create() - channels.close(cid) + cid = _channels.create() + _channels.close(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'spam') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'spam') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_close_by_unassociated_interp(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) interp = _interpreters.create() _interpreters.run_string(interp, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.close({cid}, force=True) """)) - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.close(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.close(cid) def test_close_used_multiple_times_by_single_user(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.close(cid, force=True) - - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.close(cid, force=True) + + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_channel_list_interpreters_invalid_channel(self): - cid = channels.create() + cid = _channels.create() # Test for invalid channel ID. - with self.assertRaises(channels.ChannelNotFoundError): - channels.list_interpreters(1000, send=True) + with self.assertRaises(_channels.ChannelNotFoundError): + _channels.list_interpreters(1000, send=True) - channels.close(cid) + _channels.close(cid) # Test for a channel that has been closed. - with self.assertRaises(channels.ChannelClosedError): - channels.list_interpreters(cid, send=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.list_interpreters(cid, send=True) def test_channel_list_interpreters_invalid_args(self): # Tests for invalid arguments passed to the API. - cid = channels.create() + cid = _channels.create() with self.assertRaises(TypeError): - channels.list_interpreters(cid) + _channels.list_interpreters(cid) class ChannelReleaseTests(TestBase): @@ -1240,26 +1240,26 @@ class ChannelReleaseTests(TestBase): """ def test_single_user(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.release(cid, send=True, recv=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.release(cid, send=True, recv=True) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_multiple_users(self): - cid = channels.create() + cid = _channels.create() id1 = _interpreters.create() id2 = _interpreters.create() _interpreters.run_string(id1, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.send({cid}, b'spam', blocking=False) """)) out = _run_output(id2, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.recv({cid}) _channels.release({cid}) print(repr(obj)) @@ -1271,94 +1271,94 @@ def test_multiple_users(self): self.assertEqual(out.strip(), "b'spam'") def test_no_kwargs(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.release(cid) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.release(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_multiple_times(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.release(cid, send=True, recv=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.release(cid, send=True, recv=True) - with self.assertRaises(channels.ChannelClosedError): - channels.release(cid, send=True, recv=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.release(cid, send=True, recv=True) def test_with_unused_items(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'ham', blocking=False) - channels.release(cid, send=True, recv=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'ham', blocking=False) + _channels.release(cid, send=True, recv=True) - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_never_used(self): - cid = channels.create() - channels.release(cid) + cid = _channels.create() + _channels.release(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'spam') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'spam') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_by_unassociated_interp(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) interp = _interpreters.create() _interpreters.run_string(interp, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels _channels.release({cid}) """)) - obj = channels.recv(cid) - channels.release(cid) + obj = _channels.recv(cid) + _channels.release(cid) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') self.assertEqual(obj, b'spam') def test_close_if_unassociated(self): # XXX Something's not right with this test... - cid = channels.create() + cid = _channels.create() interp = _interpreters.create() _interpreters.run_string(interp, dedent(f""" - import _xxinterpchannels as _channels + import _interpchannels as _channels obj = _channels.send({cid}, b'spam', blocking=False) _channels.release({cid}) """)) - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) def test_partially(self): # XXX Is partial close too weird/confusing? - cid = channels.create() - channels.send(cid, None, blocking=False) - channels.recv(cid) - channels.send(cid, b'spam', blocking=False) - channels.release(cid, send=True) - obj = channels.recv(cid) + cid = _channels.create() + _channels.send(cid, None, blocking=False) + _channels.recv(cid) + _channels.send(cid, b'spam', blocking=False) + _channels.release(cid, send=True) + obj = _channels.recv(cid) self.assertEqual(obj, b'spam') def test_used_multiple_times_by_single_user(self): - cid = channels.create() - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'spam', blocking=False) - channels.send(cid, b'spam', blocking=False) - channels.recv(cid) - channels.release(cid, send=True, recv=True) + cid = _channels.create() + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'spam', blocking=False) + _channels.recv(cid) + _channels.release(cid, send=True, recv=True) - with self.assertRaises(channels.ChannelClosedError): - channels.send(cid, b'eggs') - with self.assertRaises(channels.ChannelClosedError): - channels.recv(cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(cid, b'eggs') + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(cid) class ChannelCloseFixture(namedtuple('ChannelCloseFixture', @@ -1428,18 +1428,18 @@ def clean_up(self): def _new_channel(self, creator): if creator.name == 'main': - return channels.create() + return _channels.create() else: - ch = channels.create() + ch = _channels.create() run_interp(creator.id, f""" - import _xxsubinterpreters + import _interpreters cid = _xxsubchannels.create() # We purposefully send back an int to avoid tying the # channel to the other interpreter. _xxsubchannels.send({ch}, int(cid), blocking=False) - del _xxsubinterpreters + del _interpreters """) - self._cid = channels.recv(ch) + self._cid = _channels.recv(ch) return self._cid def _get_interpreter(self, interp): @@ -1464,13 +1464,13 @@ def _prep_interpreter(self, interp): if interp.name == 'main': return run_interp(interp.id, f""" - import _xxinterpchannels as channels - import test.test__xxinterpchannels as helpers + import _interpchannels as channels + import test.test__interpchannels as helpers ChannelState = helpers.ChannelState try: cid except NameError: - cid = channels._channel_id({self.cid}) + cid = _channels._channel_id({self.cid}) """) @@ -1657,7 +1657,7 @@ def run_action(self, fix, action, *, hideclosed=True): ) fix.record_action(action, result) else: - _cid = channels.create() + _cid = _channels.create() run_interp(interp.id, f""" result = helpers.run_action( {fix.cid}, @@ -1666,12 +1666,12 @@ def run_action(self, fix, action, *, hideclosed=True): {repr(fix.state)}, hideclosed={hideclosed}, ) - channels.send({_cid}, result.pending.to_bytes(1, 'little'), blocking=False) - channels.send({_cid}, b'X' if result.closed else b'', blocking=False) + _channels.send({_cid}, result.pending.to_bytes(1, 'little'), blocking=False) + _channels.send({_cid}, b'X' if result.closed else b'', blocking=False) """) result = ChannelState( - pending=int.from_bytes(channels.recv(_cid), 'little'), - closed=bool(channels.recv(_cid)), + pending=int.from_bytes(_channels.recv(_cid), 'little'), + closed=bool(_channels.recv(_cid)), ) fix.record_action(action, result) @@ -1694,42 +1694,42 @@ def _close(self, fix, *, force): if not fix.expect_closed_error(): self.run_action(fix, close, hideclosed=False) else: - with self.assertRaises(channels.ChannelClosedError): + with self.assertRaises(_channels.ChannelClosedError): self.run_action(fix, close, hideclosed=False) def _assert_closed_in_interp(self, fix, interp=None): if interp is None or interp.name == 'main': - with self.assertRaises(channels.ChannelClosedError): - channels.recv(fix.cid) - with self.assertRaises(channels.ChannelClosedError): - channels.send(fix.cid, b'spam') - with self.assertRaises(channels.ChannelClosedError): - channels.close(fix.cid) - with self.assertRaises(channels.ChannelClosedError): - channels.close(fix.cid, force=True) + with self.assertRaises(_channels.ChannelClosedError): + _channels.recv(fix.cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.send(fix.cid, b'spam') + with self.assertRaises(_channels.ChannelClosedError): + _channels.close(fix.cid) + with self.assertRaises(_channels.ChannelClosedError): + _channels.close(fix.cid, force=True) else: run_interp(interp.id, """ with helpers.expect_channel_closed(): - channels.recv(cid) + _channels.recv(cid) """) run_interp(interp.id, """ with helpers.expect_channel_closed(): - channels.send(cid, b'spam', blocking=False) + _channels.send(cid, b'spam', blocking=False) """) run_interp(interp.id, """ with helpers.expect_channel_closed(): - channels.close(cid) + _channels.close(cid) """) run_interp(interp.id, """ with helpers.expect_channel_closed(): - channels.close(cid, force=True) + _channels.close(cid, force=True) """) def _assert_closed(self, fix): self.assertTrue(fix.state.closed) for _ in range(fix.state.pending): - channels.recv(fix.cid) + _channels.recv(fix.cid) self._assert_closed_in_interp(fix) for interp in ('same', 'other'): diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__interpreters.py similarity index 98% rename from Lib/test/test__xxsubinterpreters.py rename to Lib/test/test__interpreters.py index c8c964f642f1cfb..beeb280894ea99c 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__interpreters.py @@ -13,9 +13,9 @@ from test.support import script_helper -_interpreters = import_helper.import_module('_xxsubinterpreters') +_interpreters = import_helper.import_module('_interpreters') _testinternalcapi = import_helper.import_module('_testinternalcapi') -from _xxsubinterpreters import InterpreterNotFoundError +from _interpreters import InterpreterNotFoundError ################################## @@ -231,7 +231,7 @@ class ModuleTests(TestBase): def test_import_in_interpreter(self): _run_output( _interpreters.create(), - 'import _xxsubinterpreters as _interpreters', + 'import _interpreters', ) @@ -273,7 +273,7 @@ def test_subinterpreter(self): main, *_ = _interpreters.get_main() interp = _interpreters.create() out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters + import _interpreters cur, *_ = _interpreters.get_current() print(cur) assert isinstance(cur, int) @@ -296,7 +296,7 @@ def test_from_subinterpreter(self): [expected] = [id for id, *_ in _interpreters.list_all()] interp = _interpreters.create() out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters + import _interpreters main, *_ = _interpreters.get_main() print(main) assert isinstance(main, int) @@ -323,7 +323,7 @@ def test_subinterpreter(self): def test_from_subinterpreter(self): interp = _interpreters.create() out = _run_output(interp, dedent(f""" - import _xxsubinterpreters as _interpreters + import _interpreters if _interpreters.is_running({interp}): print(True) else: @@ -385,7 +385,7 @@ def test_in_subinterpreter(self): main, = [id for id, *_ in _interpreters.list_all()] id1 = _interpreters.create() out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters + import _interpreters id = _interpreters.create() print(id) assert isinstance(id, int) @@ -402,7 +402,7 @@ def test_in_threaded_subinterpreter(self): def f(): nonlocal id2 out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters + import _interpreters id = _interpreters.create() print(id) """)) @@ -505,7 +505,7 @@ def test_from_current(self): main, = [id for id, *_ in _interpreters.list_all()] id = _interpreters.create() script = dedent(f""" - import _xxsubinterpreters as _interpreters + import _interpreters try: _interpreters.destroy({id}) except _interpreters.InterpreterError: @@ -521,7 +521,7 @@ def test_from_sibling(self): id1 = _interpreters.create() id2 = _interpreters.create() script = dedent(f""" - import _xxsubinterpreters as _interpreters + import _interpreters _interpreters.destroy({id2}) """) _interpreters.run_string(id1, script) @@ -862,7 +862,7 @@ def test_still_running_at_exit(self): script = dedent(""" from textwrap import dedent import threading - import _xxsubinterpreters as _interpreters + import _interpreters id = _interpreters.create() def f(): _interpreters.run_string(id, dedent(''' diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 9c24ec8fd05b12e..0701eafb7c36e0f 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -42,7 +42,7 @@ except ImportError: _testsinglephase = None try: - import _xxsubinterpreters as _interpreters + import _interpreters except ModuleNotFoundError: _interpreters = None diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 947a7b19056bdbf..40c3023a827067b 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -50,7 +50,7 @@ except ImportError: _testmultiphase = None try: - import _xxsubinterpreters as _interpreters + import _interpreters except ModuleNotFoundError: _interpreters = None try: diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index f0583c5fd0196fa..668042782bdc5f9 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -27,7 +27,7 @@ except ImportError: _testmultiphase = None try: - import _xxsubinterpreters as _interpreters + import _interpreters except ModuleNotFoundError: _interpreters = None diff --git a/Lib/test/test_interpreters/test_api.py b/Lib/test/test_interpreters/test_api.py index 2bd8bee40639202..0039fa46496c53f 100644 --- a/Lib/test/test_interpreters/test_api.py +++ b/Lib/test/test_interpreters/test_api.py @@ -9,7 +9,7 @@ from test import support from test.support import import_helper # Raise SkipTest if subinterpreters not supported. -_interpreters = import_helper.import_module('_xxsubinterpreters') +_interpreters = import_helper.import_module('_interpreters') from test.support import Py_GIL_DISABLED from test.support import interpreters from test.support.interpreters import ( @@ -385,7 +385,7 @@ def test_finished(self): def test_from_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(f""" - import _xxsubinterpreters as _interpreters + import _interpreters if _interpreters.is_running({interp.id}): print(True) else: @@ -876,7 +876,7 @@ def test_created_with_capi(self): with self.assertRaisesRegex(InterpreterError, 'unrecognized'): interp.exec('raise Exception("it worked!")') - # test_xxsubinterpreters covers the remaining + # test__interpreters covers the remaining # Interpreter.exec() behavior. @@ -1290,7 +1290,7 @@ def test_get_current(self): self.assertEqual(whence, _interpreters.WHENCE_RUNTIME) script = f""" - import {_interpreters.__name__} as _interpreters + import _interpreters interpid, whence = _interpreters.get_current() print((interpid, whence)) """ @@ -1333,7 +1333,7 @@ def test_list_all(self): with self.subTest('via interp from _interpreters'): text = self.run_and_capture(interpid2, f""" - import {_interpreters.__name__} as _interpreters + import _interpreters print( _interpreters.list_all()) """) @@ -1352,7 +1352,7 @@ def test_list_all(self): (interpid5, _interpreters.WHENCE_STDLIB), ] text = self.run_temp_from_capi(f""" - import {_interpreters.__name__} as _interpreters + import _interpreters _interpreters.create() print( _interpreters.list_all()) @@ -1507,7 +1507,7 @@ def test_whence(self): with self.subTest('from C-API, running'): text = self.run_temp_from_capi(dedent(f""" - import {_interpreters.__name__} as _interpreters + import _interpreters interpid, *_ = _interpreters.get_current() print(_interpreters.whence(interpid)) """), @@ -1518,7 +1518,7 @@ def test_whence(self): with self.subTest('from legacy C-API, running'): ... text = self.run_temp_from_capi(dedent(f""" - import {_interpreters.__name__} as _interpreters + import _interpreters interpid, *_ = _interpreters.get_current() print(_interpreters.whence(interpid)) """), diff --git a/Lib/test/test_interpreters/test_channels.py b/Lib/test/test_interpreters/test_channels.py index 7e0b82884c33d39..68cc45d1a5e09f8 100644 --- a/Lib/test/test_interpreters/test_channels.py +++ b/Lib/test/test_interpreters/test_channels.py @@ -7,7 +7,7 @@ from test.support import import_helper # Raise SkipTest if subinterpreters not supported. -_channels = import_helper.import_module('_xxinterpchannels') +_channels = import_helper.import_module('_interpchannels') from test.support import interpreters from test.support.interpreters import channels from .utils import _run_output, TestBase @@ -22,7 +22,7 @@ class LowLevelTests(TestBase): # encountered by the high-level module, thus they # mostly shouldn't matter as much. - # Additional tests are found in Lib/test/test__xxinterpchannels.py. + # Additional tests are found in Lib/test/test__interpchannels.py. # XXX Those should be either moved to LowLevelTests or eliminated # in favor of high-level tests in this file. diff --git a/Lib/test/test_interpreters/test_lifecycle.py b/Lib/test/test_interpreters/test_lifecycle.py index becf003e2e5f207..ac24f6568acd952 100644 --- a/Lib/test/test_interpreters/test_lifecycle.py +++ b/Lib/test/test_interpreters/test_lifecycle.py @@ -10,7 +10,7 @@ from test.support import import_helper from test.support import os_helper # Raise SkipTest if subinterpreters not supported. -import_helper.import_module('_xxsubinterpreters') +import_helper.import_module('_interpreters') from .utils import TestBase diff --git a/Lib/test/test_interpreters/test_queues.py b/Lib/test/test_interpreters/test_queues.py index 8ab9ebb354712aa..a3d44c402e0ea26 100644 --- a/Lib/test/test_interpreters/test_queues.py +++ b/Lib/test/test_interpreters/test_queues.py @@ -7,7 +7,7 @@ from test.support import import_helper, Py_DEBUG # Raise SkipTest if subinterpreters not supported. -_queues = import_helper.import_module('_xxinterpqueues') +_queues = import_helper.import_module('_interpqueues') from test.support import interpreters from test.support.interpreters import queues from .utils import _run_output, TestBase as _TestBase diff --git a/Lib/test/test_interpreters/test_stress.py b/Lib/test/test_interpreters/test_stress.py index 3cc570b3bf7128c..e400535b2a0e4ef 100644 --- a/Lib/test/test_interpreters/test_stress.py +++ b/Lib/test/test_interpreters/test_stress.py @@ -5,7 +5,7 @@ from test.support import import_helper from test.support import threading_helper # Raise SkipTest if subinterpreters not supported. -import_helper.import_module('_xxsubinterpreters') +import_helper.import_module('_interpreters') from test.support import interpreters from .utils import TestBase diff --git a/Lib/test/test_interpreters/utils.py b/Lib/test/test_interpreters/utils.py index 8e475816f04de4d..312e6fff0ceb176 100644 --- a/Lib/test/test_interpreters/utils.py +++ b/Lib/test/test_interpreters/utils.py @@ -21,7 +21,7 @@ # We would use test.support.import_helper.import_module(), # but the indirect import of test.support.os_helper causes refleaks. try: - import _xxsubinterpreters as _interpreters + import _interpreters except ImportError as exc: raise unittest.SkipTest(str(exc)) from test.support import interpreters diff --git a/Makefile.pre.in b/Makefile.pre.in index c7cf44de2dbe79a..0e52e10602cf857 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1686,11 +1686,11 @@ Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c $(srcdir)/Modules/posixmodule Modules/signalmodule.o: $(srcdir)/Modules/signalmodule.c $(srcdir)/Modules/posixmodule.h -Modules/_xxsubinterpretersmodule.o: $(srcdir)/Modules/_xxsubinterpretersmodule.c $(srcdir)/Modules/_interpreters_common.h +Modules/_interpretersmodule.o: $(srcdir)/Modules/_interpretersmodule.c $(srcdir)/Modules/_interpreters_common.h -Modules/_xxinterpqueuesmodule.o: $(srcdir)/Modules/_xxinterpqueuesmodule.c $(srcdir)/Modules/_interpreters_common.h +Modules/_interpqueuesmodule.o: $(srcdir)/Modules/_interpqueuesmodule.c $(srcdir)/Modules/_interpreters_common.h -Modules/_xxinterpchannelsmodule.o: $(srcdir)/Modules/_xxinterpchannelsmodule.c $(srcdir)/Modules/_interpreters_common.h +Modules/_interpchannelsmodule.o: $(srcdir)/Modules/_interpchannelsmodule.c $(srcdir)/Modules/_interpreters_common.h Python/crossinterp.o: $(srcdir)/Python/crossinterp.c $(srcdir)/Python/crossinterp_data_lookup.h $(srcdir)/Python/crossinterp_exceptions.h diff --git a/Misc/NEWS.d/next/Library/2024-04-11-18-11-37.gh-issue-76785.BWNkhC.rst b/Misc/NEWS.d/next/Library/2024-04-11-18-11-37.gh-issue-76785.BWNkhC.rst new file mode 100644 index 000000000000000..f3e4c57b8f19cb2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-04-11-18-11-37.gh-issue-76785.BWNkhC.rst @@ -0,0 +1,6 @@ +We've exposed the low-level :mod:`!_interpreters` module for the sake of the +PyPI implementation of :pep:`734`. It was sometimes available as the +:mod:`!_xxsubinterpreters` module and was formerly used only for testing. For +the most part, it should be considered an internal module, like :mod:`!_thread` +and :mod:`!_imp`. See +https://discuss.python.org/t/pep-734-multiple-interpreters-in-the-stdlib/41147/26. diff --git a/Modules/Setup b/Modules/Setup index cd1cf24c25d4064..e4acf6bc7de8ea5 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -137,6 +137,9 @@ PYTHONPATH=$(COREPYTHONPATH) #_datetime _datetimemodule.c #_decimal _decimal/_decimal.c #_heapq _heapqmodule.c +#_interpchannels _interpchannelsmodule.c +#_interpqueues _interpqueuesmodule.c +#_interpreters _interpretersmodule.c #_json _json.c #_lsprof _lsprof.c rotatingtree.c #_multiprocessing -I$(srcdir)/Modules/_multiprocessing _multiprocessing/multiprocessing.c _multiprocessing/semaphore.c @@ -271,9 +274,6 @@ PYTHONPATH=$(COREPYTHONPATH) # Testing -#_xxsubinterpreters _xxsubinterpretersmodule.c -#_xxinterpchannels _xxinterpchannelsmodule.c -#_xxinterpqueues _xxinterpqueuesmodule.c #_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c #_testbuffer _testbuffer.c #_testinternalcapi _testinternalcapi.c diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 0b0c1eef0cd8721..61037f592f82f18 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -43,9 +43,10 @@ @MODULE__STRUCT_TRUE@_struct _struct.c # build supports subinterpreters -@MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c -@MODULE__XXINTERPCHANNELS_TRUE@_xxinterpchannels _xxinterpchannelsmodule.c -@MODULE__XXINTERPQUEUES_TRUE@_xxinterpqueues _xxinterpqueuesmodule.c +@MODULE__INTERPRETERS_TRUE@_interpreters _interpretersmodule.c +@MODULE__INTERPCHANNELS_TRUE@_interpchannels _interpchannelsmodule.c +@MODULE__INTERPQUEUES_TRUE@_interpqueues _interpqueuesmodule.c + @MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c # needs libm diff --git a/Modules/_xxinterpchannelsmodule.c b/Modules/_interpchannelsmodule.c similarity index 99% rename from Modules/_xxinterpchannelsmodule.c rename to Modules/_interpchannelsmodule.c index bea0a6cf93fa02d..43c96584790fa05 100644 --- a/Modules/_xxinterpchannelsmodule.c +++ b/Modules/_interpchannelsmodule.c @@ -84,7 +84,7 @@ channel's queue, which are safely managed via the _PyCrossInterpreterData_*() API.. The module does not create any objects that are shared globally. */ -#define MODULE_NAME _xxinterpchannels +#define MODULE_NAME _interpchannels #define MODULE_NAME_STR Py_STRINGIFY(MODULE_NAME) #define MODINIT_FUNC_NAME RESOLVE_MODINIT_FUNC_NAME(MODULE_NAME) diff --git a/Modules/_xxinterpqueuesmodule.c b/Modules/_interpqueuesmodule.c similarity index 99% rename from Modules/_xxinterpqueuesmodule.c rename to Modules/_interpqueuesmodule.c index 96f6eeeea94b5e4..46801bd416495a6 100644 --- a/Modules/_xxinterpqueuesmodule.c +++ b/Modules/_interpqueuesmodule.c @@ -13,7 +13,7 @@ #undef REGISTERS_HEAP_TYPES -#define MODULE_NAME _xxinterpqueues +#define MODULE_NAME _interpqueues #define MODULE_NAME_STR Py_STRINGIFY(MODULE_NAME) #define MODINIT_FUNC_NAME RESOLVE_MODINIT_FUNC_NAME(MODULE_NAME) diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_interpretersmodule.c similarity index 99% rename from Modules/_xxsubinterpretersmodule.c rename to Modules/_interpretersmodule.c index 8fcd4fc4154882f..8fea56977ef3fe1 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -23,7 +23,7 @@ #include "_interpreters_common.h" -#define MODULE_NAME _xxsubinterpreters +#define MODULE_NAME _interpreters #define MODULE_NAME_STR Py_STRINGIFY(MODULE_NAME) #define MODINIT_FUNC_NAME RESOLVE_MODINIT_FUNC_NAME(MODULE_NAME) diff --git a/PC/config.c b/PC/config.c index 5eff2f5b2310bbb..b744f711b0d6363 100644 --- a/PC/config.c +++ b/PC/config.c @@ -35,9 +35,9 @@ extern PyObject* PyInit__codecs(void); extern PyObject* PyInit__weakref(void); /* XXX: These two should really be extracted to standalone extensions. */ extern PyObject* PyInit_xxsubtype(void); -extern PyObject* PyInit__xxsubinterpreters(void); -extern PyObject* PyInit__xxinterpchannels(void); -extern PyObject* PyInit__xxinterpqueues(void); +extern PyObject* PyInit__interpreters(void); +extern PyObject* PyInit__interpchannels(void); +extern PyObject* PyInit__interpqueues(void); extern PyObject* PyInit__random(void); extern PyObject* PyInit_itertools(void); extern PyObject* PyInit__collections(void); @@ -139,9 +139,9 @@ struct _inittab _PyImport_Inittab[] = { {"_json", PyInit__json}, {"xxsubtype", PyInit_xxsubtype}, - {"_xxsubinterpreters", PyInit__xxsubinterpreters}, - {"_xxinterpchannels", PyInit__xxinterpchannels}, - {"_xxinterpqueues", PyInit__xxinterpqueues}, + {"_interpreters", PyInit__interpreters}, + {"_interpchannels", PyInit__interpchannels}, + {"_interpqueues", PyInit__interpqueues}, #ifdef _Py_HAVE_ZLIB {"zlib", PyInit_zlib}, #endif diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 3a019a5fe550dbd..25d52945c1c3300 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -465,9 +465,9 @@ - - - + + + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index e43970410bd378e..4b1f9aa6538562e 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -1547,13 +1547,13 @@ Parser - + Modules - + Modules - + Modules diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index ac9d91b5e128850..08a66f447e22580 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -37,6 +37,9 @@ static const char* _Py_stdlib_module_names[] = { "_hashlib", "_heapq", "_imp", +"_interpchannels", +"_interpqueues", +"_interpreters", "_io", "_ios_support", "_json", diff --git a/Tools/build/generate_stdlib_module_names.py b/Tools/build/generate_stdlib_module_names.py index 69dc74e7f25ec98..f9fd29509f3225d 100644 --- a/Tools/build/generate_stdlib_module_names.py +++ b/Tools/build/generate_stdlib_module_names.py @@ -36,9 +36,6 @@ '_testmultiphase', '_testsinglephase', '_testexternalinspection', - '_xxsubinterpreters', - '_xxinterpchannels', - '_xxinterpqueues', '_xxtestfuzz', 'idlelib.idle_test', 'test', diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index e0ae39036c128da..87b695de23e25e2 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -164,8 +164,8 @@ Python/pylifecycle.c _Py_FatalErrorFormat reentrant - Python/pylifecycle.c fatal_error reentrant - # explicitly protected, internal-only -Modules/_xxinterpchannelsmodule.c - _globals - -Modules/_xxinterpqueuesmodule.c - _globals - +Modules/_interpchannelsmodule.c - _globals - +Modules/_interpqueuesmodule.c - _globals - # set once during module init Modules/_decimal/_decimal.c - minalloc_is_set - @@ -246,11 +246,11 @@ Modules/_struct.c - bigendian_table - Modules/_struct.c - lilendian_table - Modules/_struct.c - native_table - Modules/_tkinter.c - state_key - -Modules/_xxinterpchannelsmodule.c - _channelid_end_recv - -Modules/_xxinterpchannelsmodule.c - _channelid_end_send - +Modules/_interpchannelsmodule.c - _channelid_end_recv - +Modules/_interpchannelsmodule.c - _channelid_end_send - Modules/_zoneinfo.c - DAYS_BEFORE_MONTH - Modules/_zoneinfo.c - DAYS_IN_MONTH - -Modules/_xxsubinterpretersmodule.c - no_exception - +Modules/_interpretersmodule.c - no_exception - Modules/arraymodule.c - descriptors - Modules/arraymodule.c - emptybuf - Modules/cjkcodecs/_codecs_cn.c - _mapping_list - diff --git a/configure b/configure index 94ee1ca9cd0b8dc..78f86d83077eaac 100755 --- a/configure +++ b/configure @@ -775,12 +775,12 @@ MODULE__MULTIPROCESSING_FALSE MODULE__MULTIPROCESSING_TRUE MODULE__ZONEINFO_FALSE MODULE__ZONEINFO_TRUE -MODULE__XXINTERPQUEUES_FALSE -MODULE__XXINTERPQUEUES_TRUE -MODULE__XXINTERPCHANNELS_FALSE -MODULE__XXINTERPCHANNELS_TRUE -MODULE__XXSUBINTERPRETERS_FALSE -MODULE__XXSUBINTERPRETERS_TRUE +MODULE__INTERPQUEUES_FALSE +MODULE__INTERPQUEUES_TRUE +MODULE__INTERPCHANNELS_FALSE +MODULE__INTERPCHANNELS_TRUE +MODULE__INTERPRETERS_FALSE +MODULE__INTERPRETERS_TRUE MODULE__TYPING_FALSE MODULE__TYPING_TRUE MODULE__STRUCT_FALSE @@ -28659,9 +28659,9 @@ case $ac_sys_system in #( py_cv_module__posixsubprocess=n/a py_cv_module__scproxy=n/a py_cv_module__tkinter=n/a - py_cv_module__xxsubinterpreters=n/a - py_cv_module__xxinterpchannels=n/a - py_cv_module__xxinterpqueues=n/a + py_cv_module__interpreters=n/a + py_cv_module__interpchannels=n/a + py_cv_module__interpqueues=n/a py_cv_module_grp=n/a py_cv_module_pwd=n/a py_cv_module_resource=n/a @@ -29126,20 +29126,20 @@ then : fi - if test "$py_cv_module__xxsubinterpreters" != "n/a" + if test "$py_cv_module__interpreters" != "n/a" then : - py_cv_module__xxsubinterpreters=yes + py_cv_module__interpreters=yes fi - if test "$py_cv_module__xxsubinterpreters" = yes; then - MODULE__XXSUBINTERPRETERS_TRUE= - MODULE__XXSUBINTERPRETERS_FALSE='#' + if test "$py_cv_module__interpreters" = yes; then + MODULE__INTERPRETERS_TRUE= + MODULE__INTERPRETERS_FALSE='#' else - MODULE__XXSUBINTERPRETERS_TRUE='#' - MODULE__XXSUBINTERPRETERS_FALSE= + MODULE__INTERPRETERS_TRUE='#' + MODULE__INTERPRETERS_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__XXSUBINTERPRETERS_STATE=$py_cv_module__xxsubinterpreters$as_nl" - if test "x$py_cv_module__xxsubinterpreters" = xyes + as_fn_append MODULE_BLOCK "MODULE__INTERPRETERS_STATE=$py_cv_module__interpreters$as_nl" + if test "x$py_cv_module__interpreters" = xyes then : @@ -29148,20 +29148,20 @@ then : fi - if test "$py_cv_module__xxinterpchannels" != "n/a" + if test "$py_cv_module__interpchannels" != "n/a" then : - py_cv_module__xxinterpchannels=yes + py_cv_module__interpchannels=yes fi - if test "$py_cv_module__xxinterpchannels" = yes; then - MODULE__XXINTERPCHANNELS_TRUE= - MODULE__XXINTERPCHANNELS_FALSE='#' + if test "$py_cv_module__interpchannels" = yes; then + MODULE__INTERPCHANNELS_TRUE= + MODULE__INTERPCHANNELS_FALSE='#' else - MODULE__XXINTERPCHANNELS_TRUE='#' - MODULE__XXINTERPCHANNELS_FALSE= + MODULE__INTERPCHANNELS_TRUE='#' + MODULE__INTERPCHANNELS_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__XXINTERPCHANNELS_STATE=$py_cv_module__xxinterpchannels$as_nl" - if test "x$py_cv_module__xxinterpchannels" = xyes + as_fn_append MODULE_BLOCK "MODULE__INTERPCHANNELS_STATE=$py_cv_module__interpchannels$as_nl" + if test "x$py_cv_module__interpchannels" = xyes then : @@ -29170,20 +29170,20 @@ then : fi - if test "$py_cv_module__xxinterpqueues" != "n/a" + if test "$py_cv_module__interpqueues" != "n/a" then : - py_cv_module__xxinterpqueues=yes + py_cv_module__interpqueues=yes fi - if test "$py_cv_module__xxinterpqueues" = yes; then - MODULE__XXINTERPQUEUES_TRUE= - MODULE__XXINTERPQUEUES_FALSE='#' + if test "$py_cv_module__interpqueues" = yes; then + MODULE__INTERPQUEUES_TRUE= + MODULE__INTERPQUEUES_FALSE='#' else - MODULE__XXINTERPQUEUES_TRUE='#' - MODULE__XXINTERPQUEUES_FALSE= + MODULE__INTERPQUEUES_TRUE='#' + MODULE__INTERPQUEUES_FALSE= fi - as_fn_append MODULE_BLOCK "MODULE__XXINTERPQUEUES_STATE=$py_cv_module__xxinterpqueues$as_nl" - if test "x$py_cv_module__xxinterpqueues" = xyes + as_fn_append MODULE_BLOCK "MODULE__INTERPQUEUES_STATE=$py_cv_module__interpqueues$as_nl" + if test "x$py_cv_module__interpqueues" = xyes then : @@ -31532,16 +31532,16 @@ if test -z "${MODULE__TYPING_TRUE}" && test -z "${MODULE__TYPING_FALSE}"; then as_fn_error $? "conditional \"MODULE__TYPING\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__XXSUBINTERPRETERS_TRUE}" && test -z "${MODULE__XXSUBINTERPRETERS_FALSE}"; then - as_fn_error $? "conditional \"MODULE__XXSUBINTERPRETERS\" was never defined. +if test -z "${MODULE__INTERPRETERS_TRUE}" && test -z "${MODULE__INTERPRETERS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__INTERPRETERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__XXINTERPCHANNELS_TRUE}" && test -z "${MODULE__XXINTERPCHANNELS_FALSE}"; then - as_fn_error $? "conditional \"MODULE__XXINTERPCHANNELS\" was never defined. +if test -z "${MODULE__INTERPCHANNELS_TRUE}" && test -z "${MODULE__INTERPCHANNELS_FALSE}"; then + as_fn_error $? "conditional \"MODULE__INTERPCHANNELS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${MODULE__XXINTERPQUEUES_TRUE}" && test -z "${MODULE__XXINTERPQUEUES_FALSE}"; then - as_fn_error $? "conditional \"MODULE__XXINTERPQUEUES\" was never defined. +if test -z "${MODULE__INTERPQUEUES_TRUE}" && test -z "${MODULE__INTERPQUEUES_FALSE}"; then + as_fn_error $? "conditional \"MODULE__INTERPQUEUES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MODULE__ZONEINFO_TRUE}" && test -z "${MODULE__ZONEINFO_FALSE}"; then diff --git a/configure.ac b/configure.ac index 7877ef45c2e500c..719b8d3a9573b93 100644 --- a/configure.ac +++ b/configure.ac @@ -7433,9 +7433,9 @@ AS_CASE([$ac_sys_system], [_posixsubprocess], [_scproxy], [_tkinter], - [_xxsubinterpreters], - [_xxinterpchannels], - [_xxinterpqueues], + [_interpreters], + [_interpchannels], + [_interpqueues], [grp], [pwd], [resource], @@ -7558,9 +7558,9 @@ PY_STDLIB_MOD_SIMPLE([_random]) PY_STDLIB_MOD_SIMPLE([select]) PY_STDLIB_MOD_SIMPLE([_struct]) PY_STDLIB_MOD_SIMPLE([_typing]) -PY_STDLIB_MOD_SIMPLE([_xxsubinterpreters]) -PY_STDLIB_MOD_SIMPLE([_xxinterpchannels]) -PY_STDLIB_MOD_SIMPLE([_xxinterpqueues]) +PY_STDLIB_MOD_SIMPLE([_interpreters]) +PY_STDLIB_MOD_SIMPLE([_interpchannels]) +PY_STDLIB_MOD_SIMPLE([_interpqueues]) PY_STDLIB_MOD_SIMPLE([_zoneinfo]) dnl multiprocessing modules From 1acd2497983f1a78dffd6e5b3e0f5dd0920a550f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 Apr 2024 10:28:35 -0600 Subject: [PATCH 117/127] gh-117953: Let update_global_state_for_extension() Caller Decide If Singlephase or Not (gh-118193) This change makes other upcoming changes simpler. --- Python/import.c | 113 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 20 deletions(-) diff --git a/Python/import.c b/Python/import.c index 30d8082607ab375..739f506fe03100a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1185,19 +1185,51 @@ is_core_module(PyInterpreterState *interp, PyObject *name, PyObject *path) return 0; } +#ifndef NDEBUG +static bool +is_singlephase(PyModuleDef *def) +{ + if (def == NULL) { + /* It must be a module created by reload_singlephase_extension() + * from m_copy. Ideally we'd do away with this case. */ + return true; + } + else if (def->m_slots == NULL) { + return true; + } + else { + return false; + } +} +#endif + + +struct singlephase_global_update { + PyObject *m_dict; +}; static int update_global_state_for_extension(PyThreadState *tstate, - PyObject *mod, PyModuleDef *def, - PyObject *name, PyObject *path) + PyObject *path, PyObject *name, + PyModuleDef *def, + struct singlephase_global_update *singlephase) { - assert(mod != NULL && PyModule_Check(mod)); - assert(def == _PyModule_GetDef(mod)); - - // bpo-44050: Extensions and def->m_base.m_copy can be updated - // when the extension module doesn't support sub-interpreters. - if (def->m_size == -1) { - if (!is_core_module(tstate->interp, name, path)) { + /* Copy the module's __dict__, if applicable. */ + if (singlephase == NULL) { + assert(def->m_base.m_copy == NULL); + } + else { + assert(def->m_base.m_init != NULL + || is_core_module(tstate->interp, name, path)); + if (singlephase->m_dict == NULL) { + assert(def->m_base.m_copy == NULL); + } + else { + assert(PyDict_Check(singlephase->m_dict)); + // gh-88216: Extensions and def->m_base.m_copy can be updated + // when the extension module doesn't support sub-interpreters. + assert(def->m_size == -1); + assert(!is_core_module(tstate->interp, name, path)); assert(PyUnicode_CompareWithASCIIString(name, "sys") != 0); assert(PyUnicode_CompareWithASCIIString(name, "builtins") != 0); if (def->m_base.m_copy) { @@ -1206,17 +1238,16 @@ update_global_state_for_extension(PyThreadState *tstate, XXX this should really not happen. */ Py_CLEAR(def->m_base.m_copy); } - PyObject *dict = PyModule_GetDict(mod); - if (dict == NULL) { - return -1; - } - def->m_base.m_copy = PyDict_Copy(dict); + def->m_base.m_copy = PyDict_Copy(singlephase->m_dict); if (def->m_base.m_copy == NULL) { + // XXX Ignore this error? Doing so would effectively + // mark the module as not loadable. */ return -1; } } } + /* Add the module's def to the global cache. */ // XXX Why special-case the main interpreter? if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) { #ifndef NDEBUG @@ -1258,6 +1289,8 @@ int _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, PyObject *filename, PyObject *modules) { + PyThreadState *tstate = _PyThreadState_GET(); + if (mod == NULL || !PyModule_Check(mod)) { PyErr_BadInternalCall(); return -1; @@ -1268,15 +1301,28 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, return -1; } - PyThreadState *tstate = _PyThreadState_GET(); + /* Only single-phase init extension modules can reach here. */ + assert(is_singlephase(def)); + assert(!is_core_module(tstate->interp, name, filename)); + assert(!is_core_module(tstate->interp, name, name)); + + struct singlephase_global_update singlephase = {0}; + // gh-88216: Extensions and def->m_base.m_copy can be updated + // when the extension module doesn't support sub-interpreters. + if (def->m_size == -1) { + singlephase.m_dict = PyModule_GetDict(mod); + assert(singlephase.m_dict != NULL); + } if (update_global_state_for_extension( - tstate, mod, def, name, filename) < 0) + tstate, filename, name, def, &singlephase) < 0) { return -1; } + if (finish_singlephase_extension(tstate, mod, def, name, modules) < 0) { return -1; } + return 0; } @@ -1407,11 +1453,25 @@ _PyImport_FixupBuiltin(PyThreadState *tstate, PyObject *mod, const char *name, goto finally; } + /* We only use _PyImport_FixupBuiltin() for the core builtin modules + * (sys and builtins). These modules are single-phase init with no + * module state, but we also don't populate def->m_base.m_copy + * for them. */ + assert(is_core_module(tstate->interp, nameobj, nameobj)); + assert(is_singlephase(def)); + assert(def->m_size == -1); + assert(def->m_base.m_copy == NULL); + + struct singlephase_global_update singlephase = { + /* We don't want def->m_base.m_copy populated. */ + .m_dict=NULL, + }; if (update_global_state_for_extension( - tstate, mod, def, nameobj, nameobj) < 0) + tstate, nameobj, nameobj, def, &singlephase) < 0) { goto finally; } + if (finish_singlephase_extension(tstate, mod, def, nameobj, modules) < 0) { goto finally; } @@ -1444,6 +1504,7 @@ is_builtin(PyObject *name) static PyObject* create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) { + PyModuleDef *def = NULL; PyObject *mod = import_find_extension(tstate, name, name); if (mod || _PyErr_Occurred(tstate)) { return mod; @@ -1473,20 +1534,32 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) } if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) { - return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec); + def = (PyModuleDef*)mod; + assert(!is_singlephase(def)); + return PyModule_FromDefAndSpec(def, spec); } else { assert(PyModule_Check(mod)); - PyModuleDef *def = PyModule_GetDef(mod); + def = PyModule_GetDef(mod); if (def == NULL) { return NULL; } + assert(is_singlephase(def)); /* Remember pointer to module init function. */ def->m_base.m_init = p0; + struct singlephase_global_update singlephase = {0}; + // gh-88216: Extensions and def->m_base.m_copy can be updated + // when the extension module doesn't support sub-interpreters. + if (def->m_size == -1 + && !is_core_module(tstate->interp, name, name)) + { + singlephase.m_dict = PyModule_GetDict(mod); + assert(singlephase.m_dict != NULL); + } if (update_global_state_for_extension( - tstate, mod, def, name, name) < 0) + tstate, name, name, def, &singlephase) < 0) { return NULL; } From 9b280ab0ab97902d55ea3bde66b2e23f8b23959f Mon Sep 17 00:00:00 2001 From: David Rubin <87927264+Rexicon226@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:16:06 -0700 Subject: [PATCH 118/127] gh-116988: Remove duplicates of `annotated_rhs` in the Grammar (#117004) --- Grammar/python.gram | 18 +- Parser/parser.c | 3763 ++++++++++------------ Tools/peg_generator/pegen/c_generator.py | 2 +- 3 files changed, 1626 insertions(+), 2157 deletions(-) diff --git a/Grammar/python.gram b/Grammar/python.gram index 11438e57da527bf..3943d7fec5db039 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -915,7 +915,7 @@ fstring_middle[expr_ty]: | fstring_replacement_field | t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) } fstring_replacement_field[expr_ty]: - | '{' a=(yield_expr | star_expressions) debug_expr='='? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' { + | '{' a=annotated_rhs debug_expr='='? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' { _PyPegen_formatted_value(p, a, debug_expr, conversion, format, rbrace, EXTRA) } | invalid_replacement_field fstring_conversion[ResultTokenWithMetadata*]: @@ -1201,7 +1201,7 @@ invalid_assignment: | (star_targets '=')* a=star_expressions '=' { RAISE_SYNTAX_ERROR_INVALID_TARGET(STAR_TARGETS, a) } | (star_targets '=')* a=yield_expr '=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "assignment to yield expression not possible") } - | a=star_expressions augassign (yield_expr | star_expressions) { + | a=star_expressions augassign annotated_rhs { RAISE_SYNTAX_ERROR_KNOWN_LOCATION( a, "'%s' is an illegal expression for augmented assignment", @@ -1407,17 +1407,17 @@ invalid_replacement_field: | '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '!'") } | '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before ':'") } | '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '}'") } - | '{' !(yield_expr | star_expressions) { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'")} - | '{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}') { + | '{' !annotated_rhs { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'")} + | '{' annotated_rhs !('=' | '!' | ':' | '}') { PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '=', or '!', or ':', or '}'") } - | '{' (yield_expr | star_expressions) '=' !('!' | ':' | '}') { + | '{' annotated_rhs '=' !('!' | ':' | '}') { PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '!', or ':', or '}'") } - | '{' (yield_expr | star_expressions) '='? invalid_conversion_character - | '{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}') { + | '{' annotated_rhs '='? invalid_conversion_character + | '{' annotated_rhs '='? ['!' NAME] !(':' | '}') { PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting ':' or '}'") } - | '{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}' { + | '{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}' { PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}', or format specs") } - | '{' (yield_expr | star_expressions) '='? ['!' NAME] !'}' { + | '{' annotated_rhs '='? ['!' NAME] !'}' { PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}'") } invalid_conversion_character: diff --git a/Parser/parser.c b/Parser/parser.c index b6683bfd1f1bc01..0715e9775a8f065 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -442,48 +442,48 @@ static char *soft_keywords[] = { #define _loop1_109_type 1355 #define _loop0_110_type 1356 #define _loop1_111_type 1357 -#define _tmp_112_type 1358 +#define _loop0_112_type 1358 #define _loop0_113_type 1359 -#define _loop0_114_type 1360 -#define _loop1_115_type 1361 -#define _tmp_116_type 1362 -#define _loop0_118_type 1363 -#define _gather_117_type 1364 -#define _loop1_119_type 1365 +#define _loop1_114_type 1360 +#define _tmp_115_type 1361 +#define _loop0_117_type 1362 +#define _gather_116_type 1363 +#define _loop1_118_type 1364 +#define _loop0_119_type 1365 #define _loop0_120_type 1366 -#define _loop0_121_type 1367 +#define _tmp_121_type 1367 #define _tmp_122_type 1368 -#define _tmp_123_type 1369 -#define _loop0_125_type 1370 -#define _gather_124_type 1371 -#define _tmp_126_type 1372 -#define _loop0_128_type 1373 -#define _gather_127_type 1374 -#define _loop0_130_type 1375 -#define _gather_129_type 1376 -#define _loop0_132_type 1377 -#define _gather_131_type 1378 -#define _loop0_134_type 1379 -#define _gather_133_type 1380 -#define _loop0_135_type 1381 -#define _loop0_137_type 1382 -#define _gather_136_type 1383 -#define _loop1_138_type 1384 -#define _tmp_139_type 1385 -#define _loop0_141_type 1386 -#define _gather_140_type 1387 -#define _loop0_143_type 1388 -#define _gather_142_type 1389 -#define _loop0_145_type 1390 -#define _gather_144_type 1391 -#define _loop0_147_type 1392 -#define _gather_146_type 1393 -#define _loop0_149_type 1394 -#define _gather_148_type 1395 +#define _loop0_124_type 1369 +#define _gather_123_type 1370 +#define _tmp_125_type 1371 +#define _loop0_127_type 1372 +#define _gather_126_type 1373 +#define _loop0_129_type 1374 +#define _gather_128_type 1375 +#define _loop0_131_type 1376 +#define _gather_130_type 1377 +#define _loop0_133_type 1378 +#define _gather_132_type 1379 +#define _loop0_134_type 1380 +#define _loop0_136_type 1381 +#define _gather_135_type 1382 +#define _loop1_137_type 1383 +#define _tmp_138_type 1384 +#define _loop0_140_type 1385 +#define _gather_139_type 1386 +#define _loop0_142_type 1387 +#define _gather_141_type 1388 +#define _loop0_144_type 1389 +#define _gather_143_type 1390 +#define _loop0_146_type 1391 +#define _gather_145_type 1392 +#define _loop0_148_type 1393 +#define _gather_147_type 1394 +#define _tmp_149_type 1395 #define _tmp_150_type 1396 -#define _tmp_151_type 1397 -#define _loop0_153_type 1398 -#define _gather_152_type 1399 +#define _loop0_152_type 1397 +#define _gather_151_type 1398 +#define _tmp_153_type 1399 #define _tmp_154_type 1400 #define _tmp_155_type 1401 #define _tmp_156_type 1402 @@ -493,49 +493,49 @@ static char *soft_keywords[] = { #define _tmp_160_type 1406 #define _tmp_161_type 1407 #define _tmp_162_type 1408 -#define _tmp_163_type 1409 +#define _loop0_163_type 1409 #define _loop0_164_type 1410 #define _loop0_165_type 1411 -#define _loop0_166_type 1412 +#define _tmp_166_type 1412 #define _tmp_167_type 1413 #define _tmp_168_type 1414 #define _tmp_169_type 1415 -#define _tmp_170_type 1416 -#define _tmp_171_type 1417 +#define _loop0_170_type 1416 +#define _loop0_171_type 1417 #define _loop0_172_type 1418 -#define _loop0_173_type 1419 -#define _loop0_174_type 1420 -#define _loop1_175_type 1421 +#define _loop1_173_type 1419 +#define _tmp_174_type 1420 +#define _loop0_175_type 1421 #define _tmp_176_type 1422 #define _loop0_177_type 1423 -#define _tmp_178_type 1424 -#define _loop0_179_type 1425 -#define _loop1_180_type 1426 +#define _loop1_178_type 1424 +#define _tmp_179_type 1425 +#define _tmp_180_type 1426 #define _tmp_181_type 1427 -#define _tmp_182_type 1428 +#define _loop0_182_type 1428 #define _tmp_183_type 1429 -#define _loop0_184_type 1430 -#define _tmp_185_type 1431 +#define _tmp_184_type 1430 +#define _loop1_185_type 1431 #define _tmp_186_type 1432 -#define _loop1_187_type 1433 -#define _tmp_188_type 1434 +#define _loop0_187_type 1433 +#define _loop0_188_type 1434 #define _loop0_189_type 1435 -#define _loop0_190_type 1436 -#define _loop0_191_type 1437 -#define _loop0_193_type 1438 -#define _gather_192_type 1439 +#define _loop0_191_type 1436 +#define _gather_190_type 1437 +#define _tmp_192_type 1438 +#define _loop0_193_type 1439 #define _tmp_194_type 1440 #define _loop0_195_type 1441 -#define _tmp_196_type 1442 -#define _loop0_197_type 1443 -#define _loop1_198_type 1444 -#define _loop1_199_type 1445 -#define _tmp_200_type 1446 +#define _loop1_196_type 1442 +#define _loop1_197_type 1443 +#define _tmp_198_type 1444 +#define _tmp_199_type 1445 +#define _loop0_200_type 1446 #define _tmp_201_type 1447 -#define _loop0_202_type 1448 +#define _tmp_202_type 1448 #define _tmp_203_type 1449 -#define _tmp_204_type 1450 -#define _tmp_205_type 1451 +#define _loop0_205_type 1450 +#define _gather_204_type 1451 #define _loop0_207_type 1452 #define _gather_206_type 1453 #define _loop0_209_type 1454 @@ -544,14 +544,14 @@ static char *soft_keywords[] = { #define _gather_210_type 1457 #define _loop0_213_type 1458 #define _gather_212_type 1459 -#define _loop0_215_type 1460 -#define _gather_214_type 1461 -#define _tmp_216_type 1462 -#define _loop0_217_type 1463 -#define _loop1_218_type 1464 -#define _tmp_219_type 1465 -#define _loop0_220_type 1466 -#define _loop1_221_type 1467 +#define _tmp_214_type 1460 +#define _loop0_215_type 1461 +#define _loop1_216_type 1462 +#define _tmp_217_type 1463 +#define _loop0_218_type 1464 +#define _loop1_219_type 1465 +#define _tmp_220_type 1466 +#define _tmp_221_type 1467 #define _tmp_222_type 1468 #define _tmp_223_type 1469 #define _tmp_224_type 1470 @@ -560,16 +560,16 @@ static char *soft_keywords[] = { #define _tmp_227_type 1473 #define _tmp_228_type 1474 #define _tmp_229_type 1475 -#define _tmp_230_type 1476 -#define _tmp_231_type 1477 -#define _loop0_233_type 1478 -#define _gather_232_type 1479 +#define _loop0_231_type 1476 +#define _gather_230_type 1477 +#define _tmp_232_type 1478 +#define _tmp_233_type 1479 #define _tmp_234_type 1480 #define _tmp_235_type 1481 #define _tmp_236_type 1482 #define _tmp_237_type 1483 #define _tmp_238_type 1484 -#define _tmp_239_type 1485 +#define _loop0_239_type 1485 #define _tmp_240_type 1486 #define _tmp_241_type 1487 #define _tmp_242_type 1488 @@ -577,7 +577,7 @@ static char *soft_keywords[] = { #define _tmp_244_type 1490 #define _tmp_245_type 1491 #define _tmp_246_type 1492 -#define _loop0_247_type 1493 +#define _tmp_247_type 1493 #define _tmp_248_type 1494 #define _tmp_249_type 1495 #define _tmp_250_type 1496 @@ -586,7 +586,7 @@ static char *soft_keywords[] = { #define _tmp_253_type 1499 #define _tmp_254_type 1500 #define _tmp_255_type 1501 -#define _tmp_256_type 1502 +#define _loop0_256_type 1502 #define _tmp_257_type 1503 #define _tmp_258_type 1504 #define _tmp_259_type 1505 @@ -595,7 +595,7 @@ static char *soft_keywords[] = { #define _tmp_262_type 1508 #define _tmp_263_type 1509 #define _tmp_264_type 1510 -#define _loop0_265_type 1511 +#define _tmp_265_type 1511 #define _tmp_266_type 1512 #define _tmp_267_type 1513 #define _tmp_268_type 1514 @@ -603,23 +603,14 @@ static char *soft_keywords[] = { #define _tmp_270_type 1516 #define _tmp_271_type 1517 #define _tmp_272_type 1518 -#define _tmp_273_type 1519 -#define _tmp_274_type 1520 +#define _loop0_274_type 1519 +#define _gather_273_type 1520 #define _tmp_275_type 1521 #define _tmp_276_type 1522 #define _tmp_277_type 1523 #define _tmp_278_type 1524 #define _tmp_279_type 1525 #define _tmp_280_type 1526 -#define _tmp_281_type 1527 -#define _loop0_283_type 1528 -#define _gather_282_type 1529 -#define _tmp_284_type 1530 -#define _tmp_285_type 1531 -#define _tmp_286_type 1532 -#define _tmp_287_type 1533 -#define _tmp_288_type 1534 -#define _tmp_289_type 1535 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -979,48 +970,48 @@ static asdl_seq *_loop0_108_rule(Parser *p); static asdl_seq *_loop1_109_rule(Parser *p); static asdl_seq *_loop0_110_rule(Parser *p); static asdl_seq *_loop1_111_rule(Parser *p); -static void *_tmp_112_rule(Parser *p); +static asdl_seq *_loop0_112_rule(Parser *p); static asdl_seq *_loop0_113_rule(Parser *p); -static asdl_seq *_loop0_114_rule(Parser *p); -static asdl_seq *_loop1_115_rule(Parser *p); -static void *_tmp_116_rule(Parser *p); -static asdl_seq *_loop0_118_rule(Parser *p); -static asdl_seq *_gather_117_rule(Parser *p); -static asdl_seq *_loop1_119_rule(Parser *p); +static asdl_seq *_loop1_114_rule(Parser *p); +static void *_tmp_115_rule(Parser *p); +static asdl_seq *_loop0_117_rule(Parser *p); +static asdl_seq *_gather_116_rule(Parser *p); +static asdl_seq *_loop1_118_rule(Parser *p); +static asdl_seq *_loop0_119_rule(Parser *p); static asdl_seq *_loop0_120_rule(Parser *p); -static asdl_seq *_loop0_121_rule(Parser *p); +static void *_tmp_121_rule(Parser *p); static void *_tmp_122_rule(Parser *p); -static void *_tmp_123_rule(Parser *p); -static asdl_seq *_loop0_125_rule(Parser *p); -static asdl_seq *_gather_124_rule(Parser *p); -static void *_tmp_126_rule(Parser *p); -static asdl_seq *_loop0_128_rule(Parser *p); -static asdl_seq *_gather_127_rule(Parser *p); -static asdl_seq *_loop0_130_rule(Parser *p); -static asdl_seq *_gather_129_rule(Parser *p); -static asdl_seq *_loop0_132_rule(Parser *p); -static asdl_seq *_gather_131_rule(Parser *p); +static asdl_seq *_loop0_124_rule(Parser *p); +static asdl_seq *_gather_123_rule(Parser *p); +static void *_tmp_125_rule(Parser *p); +static asdl_seq *_loop0_127_rule(Parser *p); +static asdl_seq *_gather_126_rule(Parser *p); +static asdl_seq *_loop0_129_rule(Parser *p); +static asdl_seq *_gather_128_rule(Parser *p); +static asdl_seq *_loop0_131_rule(Parser *p); +static asdl_seq *_gather_130_rule(Parser *p); +static asdl_seq *_loop0_133_rule(Parser *p); +static asdl_seq *_gather_132_rule(Parser *p); static asdl_seq *_loop0_134_rule(Parser *p); -static asdl_seq *_gather_133_rule(Parser *p); -static asdl_seq *_loop0_135_rule(Parser *p); -static asdl_seq *_loop0_137_rule(Parser *p); -static asdl_seq *_gather_136_rule(Parser *p); -static asdl_seq *_loop1_138_rule(Parser *p); -static void *_tmp_139_rule(Parser *p); -static asdl_seq *_loop0_141_rule(Parser *p); -static asdl_seq *_gather_140_rule(Parser *p); -static asdl_seq *_loop0_143_rule(Parser *p); -static asdl_seq *_gather_142_rule(Parser *p); -static asdl_seq *_loop0_145_rule(Parser *p); -static asdl_seq *_gather_144_rule(Parser *p); -static asdl_seq *_loop0_147_rule(Parser *p); -static asdl_seq *_gather_146_rule(Parser *p); -static asdl_seq *_loop0_149_rule(Parser *p); -static asdl_seq *_gather_148_rule(Parser *p); +static asdl_seq *_loop0_136_rule(Parser *p); +static asdl_seq *_gather_135_rule(Parser *p); +static asdl_seq *_loop1_137_rule(Parser *p); +static void *_tmp_138_rule(Parser *p); +static asdl_seq *_loop0_140_rule(Parser *p); +static asdl_seq *_gather_139_rule(Parser *p); +static asdl_seq *_loop0_142_rule(Parser *p); +static asdl_seq *_gather_141_rule(Parser *p); +static asdl_seq *_loop0_144_rule(Parser *p); +static asdl_seq *_gather_143_rule(Parser *p); +static asdl_seq *_loop0_146_rule(Parser *p); +static asdl_seq *_gather_145_rule(Parser *p); +static asdl_seq *_loop0_148_rule(Parser *p); +static asdl_seq *_gather_147_rule(Parser *p); +static void *_tmp_149_rule(Parser *p); static void *_tmp_150_rule(Parser *p); -static void *_tmp_151_rule(Parser *p); -static asdl_seq *_loop0_153_rule(Parser *p); -static asdl_seq *_gather_152_rule(Parser *p); +static asdl_seq *_loop0_152_rule(Parser *p); +static asdl_seq *_gather_151_rule(Parser *p); +static void *_tmp_153_rule(Parser *p); static void *_tmp_154_rule(Parser *p); static void *_tmp_155_rule(Parser *p); static void *_tmp_156_rule(Parser *p); @@ -1030,49 +1021,49 @@ static void *_tmp_159_rule(Parser *p); static void *_tmp_160_rule(Parser *p); static void *_tmp_161_rule(Parser *p); static void *_tmp_162_rule(Parser *p); -static void *_tmp_163_rule(Parser *p); +static asdl_seq *_loop0_163_rule(Parser *p); static asdl_seq *_loop0_164_rule(Parser *p); static asdl_seq *_loop0_165_rule(Parser *p); -static asdl_seq *_loop0_166_rule(Parser *p); +static void *_tmp_166_rule(Parser *p); static void *_tmp_167_rule(Parser *p); static void *_tmp_168_rule(Parser *p); static void *_tmp_169_rule(Parser *p); -static void *_tmp_170_rule(Parser *p); -static void *_tmp_171_rule(Parser *p); +static asdl_seq *_loop0_170_rule(Parser *p); +static asdl_seq *_loop0_171_rule(Parser *p); static asdl_seq *_loop0_172_rule(Parser *p); -static asdl_seq *_loop0_173_rule(Parser *p); -static asdl_seq *_loop0_174_rule(Parser *p); -static asdl_seq *_loop1_175_rule(Parser *p); +static asdl_seq *_loop1_173_rule(Parser *p); +static void *_tmp_174_rule(Parser *p); +static asdl_seq *_loop0_175_rule(Parser *p); static void *_tmp_176_rule(Parser *p); static asdl_seq *_loop0_177_rule(Parser *p); -static void *_tmp_178_rule(Parser *p); -static asdl_seq *_loop0_179_rule(Parser *p); -static asdl_seq *_loop1_180_rule(Parser *p); +static asdl_seq *_loop1_178_rule(Parser *p); +static void *_tmp_179_rule(Parser *p); +static void *_tmp_180_rule(Parser *p); static void *_tmp_181_rule(Parser *p); -static void *_tmp_182_rule(Parser *p); +static asdl_seq *_loop0_182_rule(Parser *p); static void *_tmp_183_rule(Parser *p); -static asdl_seq *_loop0_184_rule(Parser *p); -static void *_tmp_185_rule(Parser *p); +static void *_tmp_184_rule(Parser *p); +static asdl_seq *_loop1_185_rule(Parser *p); static void *_tmp_186_rule(Parser *p); -static asdl_seq *_loop1_187_rule(Parser *p); -static void *_tmp_188_rule(Parser *p); +static asdl_seq *_loop0_187_rule(Parser *p); +static asdl_seq *_loop0_188_rule(Parser *p); static asdl_seq *_loop0_189_rule(Parser *p); -static asdl_seq *_loop0_190_rule(Parser *p); static asdl_seq *_loop0_191_rule(Parser *p); +static asdl_seq *_gather_190_rule(Parser *p); +static void *_tmp_192_rule(Parser *p); static asdl_seq *_loop0_193_rule(Parser *p); -static asdl_seq *_gather_192_rule(Parser *p); static void *_tmp_194_rule(Parser *p); static asdl_seq *_loop0_195_rule(Parser *p); -static void *_tmp_196_rule(Parser *p); -static asdl_seq *_loop0_197_rule(Parser *p); -static asdl_seq *_loop1_198_rule(Parser *p); -static asdl_seq *_loop1_199_rule(Parser *p); -static void *_tmp_200_rule(Parser *p); +static asdl_seq *_loop1_196_rule(Parser *p); +static asdl_seq *_loop1_197_rule(Parser *p); +static void *_tmp_198_rule(Parser *p); +static void *_tmp_199_rule(Parser *p); +static asdl_seq *_loop0_200_rule(Parser *p); static void *_tmp_201_rule(Parser *p); -static asdl_seq *_loop0_202_rule(Parser *p); +static void *_tmp_202_rule(Parser *p); static void *_tmp_203_rule(Parser *p); -static void *_tmp_204_rule(Parser *p); -static void *_tmp_205_rule(Parser *p); +static asdl_seq *_loop0_205_rule(Parser *p); +static asdl_seq *_gather_204_rule(Parser *p); static asdl_seq *_loop0_207_rule(Parser *p); static asdl_seq *_gather_206_rule(Parser *p); static asdl_seq *_loop0_209_rule(Parser *p); @@ -1081,14 +1072,14 @@ static asdl_seq *_loop0_211_rule(Parser *p); static asdl_seq *_gather_210_rule(Parser *p); static asdl_seq *_loop0_213_rule(Parser *p); static asdl_seq *_gather_212_rule(Parser *p); +static void *_tmp_214_rule(Parser *p); static asdl_seq *_loop0_215_rule(Parser *p); -static asdl_seq *_gather_214_rule(Parser *p); -static void *_tmp_216_rule(Parser *p); -static asdl_seq *_loop0_217_rule(Parser *p); -static asdl_seq *_loop1_218_rule(Parser *p); -static void *_tmp_219_rule(Parser *p); -static asdl_seq *_loop0_220_rule(Parser *p); -static asdl_seq *_loop1_221_rule(Parser *p); +static asdl_seq *_loop1_216_rule(Parser *p); +static void *_tmp_217_rule(Parser *p); +static asdl_seq *_loop0_218_rule(Parser *p); +static asdl_seq *_loop1_219_rule(Parser *p); +static void *_tmp_220_rule(Parser *p); +static void *_tmp_221_rule(Parser *p); static void *_tmp_222_rule(Parser *p); static void *_tmp_223_rule(Parser *p); static void *_tmp_224_rule(Parser *p); @@ -1097,16 +1088,16 @@ static void *_tmp_226_rule(Parser *p); static void *_tmp_227_rule(Parser *p); static void *_tmp_228_rule(Parser *p); static void *_tmp_229_rule(Parser *p); -static void *_tmp_230_rule(Parser *p); -static void *_tmp_231_rule(Parser *p); -static asdl_seq *_loop0_233_rule(Parser *p); -static asdl_seq *_gather_232_rule(Parser *p); +static asdl_seq *_loop0_231_rule(Parser *p); +static asdl_seq *_gather_230_rule(Parser *p); +static void *_tmp_232_rule(Parser *p); +static void *_tmp_233_rule(Parser *p); static void *_tmp_234_rule(Parser *p); static void *_tmp_235_rule(Parser *p); static void *_tmp_236_rule(Parser *p); static void *_tmp_237_rule(Parser *p); static void *_tmp_238_rule(Parser *p); -static void *_tmp_239_rule(Parser *p); +static asdl_seq *_loop0_239_rule(Parser *p); static void *_tmp_240_rule(Parser *p); static void *_tmp_241_rule(Parser *p); static void *_tmp_242_rule(Parser *p); @@ -1114,7 +1105,7 @@ static void *_tmp_243_rule(Parser *p); static void *_tmp_244_rule(Parser *p); static void *_tmp_245_rule(Parser *p); static void *_tmp_246_rule(Parser *p); -static asdl_seq *_loop0_247_rule(Parser *p); +static void *_tmp_247_rule(Parser *p); static void *_tmp_248_rule(Parser *p); static void *_tmp_249_rule(Parser *p); static void *_tmp_250_rule(Parser *p); @@ -1123,7 +1114,7 @@ static void *_tmp_252_rule(Parser *p); static void *_tmp_253_rule(Parser *p); static void *_tmp_254_rule(Parser *p); static void *_tmp_255_rule(Parser *p); -static void *_tmp_256_rule(Parser *p); +static asdl_seq *_loop0_256_rule(Parser *p); static void *_tmp_257_rule(Parser *p); static void *_tmp_258_rule(Parser *p); static void *_tmp_259_rule(Parser *p); @@ -1132,7 +1123,7 @@ static void *_tmp_261_rule(Parser *p); static void *_tmp_262_rule(Parser *p); static void *_tmp_263_rule(Parser *p); static void *_tmp_264_rule(Parser *p); -static asdl_seq *_loop0_265_rule(Parser *p); +static void *_tmp_265_rule(Parser *p); static void *_tmp_266_rule(Parser *p); static void *_tmp_267_rule(Parser *p); static void *_tmp_268_rule(Parser *p); @@ -1140,23 +1131,14 @@ static void *_tmp_269_rule(Parser *p); static void *_tmp_270_rule(Parser *p); static void *_tmp_271_rule(Parser *p); static void *_tmp_272_rule(Parser *p); -static void *_tmp_273_rule(Parser *p); -static void *_tmp_274_rule(Parser *p); +static asdl_seq *_loop0_274_rule(Parser *p); +static asdl_seq *_gather_273_rule(Parser *p); static void *_tmp_275_rule(Parser *p); static void *_tmp_276_rule(Parser *p); static void *_tmp_277_rule(Parser *p); static void *_tmp_278_rule(Parser *p); static void *_tmp_279_rule(Parser *p); static void *_tmp_280_rule(Parser *p); -static void *_tmp_281_rule(Parser *p); -static asdl_seq *_loop0_283_rule(Parser *p); -static asdl_seq *_gather_282_rule(Parser *p); -static void *_tmp_284_rule(Parser *p); -static void *_tmp_285_rule(Parser *p); -static void *_tmp_286_rule(Parser *p); -static void *_tmp_287_rule(Parser *p); -static void *_tmp_288_rule(Parser *p); -static void *_tmp_289_rule(Parser *p); // file: statements? $ @@ -1820,7 +1802,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); stmt_ty import_stmt_var; if ( - _PyPegen_lookahead(1, _tmp_6_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_6_rule, p) && (import_stmt_var = import_stmt_rule(p)) // import_stmt ) @@ -2114,7 +2096,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('def' | '@' | 'async') function_def")); stmt_ty function_def_var; if ( - _PyPegen_lookahead(1, _tmp_7_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_7_rule, p) && (function_def_var = function_def_rule(p)) // function_def ) @@ -2156,7 +2138,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('class' | '@') class_def")); stmt_ty class_def_var; if ( - _PyPegen_lookahead(1, _tmp_8_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_8_rule, p) && (class_def_var = class_def_rule(p)) // class_def ) @@ -2177,7 +2159,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('with' | 'async') with_stmt")); stmt_ty with_stmt_var; if ( - _PyPegen_lookahead(1, _tmp_9_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_9_rule, p) && (with_stmt_var = with_stmt_rule(p)) // with_stmt ) @@ -2198,7 +2180,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('for' | 'async') for_stmt")); stmt_ty for_stmt_var; if ( - _PyPegen_lookahead(1, _tmp_10_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_10_rule, p) && (for_stmt_var = for_stmt_rule(p)) // for_stmt ) @@ -3229,7 +3211,7 @@ del_stmt_rule(Parser *p) && (a = del_targets_rule(p)) // del_targets && - _PyPegen_lookahead(1, _tmp_22_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_22_rule, p) ) { D(fprintf(stderr, "%*c+ del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); @@ -6834,7 +6816,7 @@ with_item_rule(Parser *p) && (t = star_target_rule(p)) // star_target && - _PyPegen_lookahead(1, _tmp_59_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_59_rule, p) ) { D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); @@ -8239,7 +8221,7 @@ literal_pattern_rule(Parser *p) if ( (value = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, _tmp_67_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_67_rule, p) ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -8473,7 +8455,7 @@ literal_expr_rule(Parser *p) if ( (signed_number_var = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, _tmp_68_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_68_rule, p) ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -9073,7 +9055,7 @@ pattern_capture_target_rule(Parser *p) && (name = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(0, _tmp_69_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_69_rule, p) ) { D(fprintf(stderr, "%*c+ pattern_capture_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); @@ -9188,7 +9170,7 @@ value_pattern_rule(Parser *p) if ( (attr = attr_rule(p)) // attr && - _PyPegen_lookahead(0, _tmp_70_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_70_rule, p) ) { D(fprintf(stderr, "%*c+ value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); @@ -14769,7 +14751,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&(STRING | FSTRING_START) strings")); expr_ty strings_var; if ( - _PyPegen_lookahead(1, _tmp_93_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_93_rule, p) && (strings_var = strings_rule(p)) // strings ) @@ -15981,7 +15963,7 @@ fstring_middle_rule(Parser *p) } // fstring_replacement_field: -// | '{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}' +// | '{' annotated_rhs '='? fstring_conversion? fstring_full_format_spec? '}' // | invalid_replacement_field static expr_ty fstring_replacement_field_rule(Parser *p) @@ -16004,14 +15986,14 @@ fstring_replacement_field_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // '{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}' + { // '{' annotated_rhs '='? fstring_conversion? fstring_full_format_spec? '}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> fstring_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}'")); + D(fprintf(stderr, "%*c> fstring_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? fstring_conversion? fstring_full_format_spec? '}'")); Token * _literal; - void *a; + expr_ty a; void *conversion; void *debug_expr; void *format; @@ -16019,7 +16001,7 @@ fstring_replacement_field_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (a = _tmp_112_rule(p)) // yield_expr | star_expressions + (a = annotated_rhs_rule(p)) // annotated_rhs && (debug_expr = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && @@ -16030,7 +16012,7 @@ fstring_replacement_field_rule(Parser *p) (rbrace = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}'")); + D(fprintf(stderr, "%*c+ fstring_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? fstring_conversion? fstring_full_format_spec? '}'")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -16050,7 +16032,7 @@ fstring_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s fstring_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) '='? fstring_conversion? fstring_full_format_spec? '}'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' annotated_rhs '='? fstring_conversion? fstring_full_format_spec? '}'")); } if (p->call_invalid_rules) { // invalid_replacement_field if (p->error_indicator) { @@ -16156,7 +16138,7 @@ fstring_full_format_spec_rule(Parser *p) if ( (colon = _PyPegen_expect_token(p, 11)) // token=':' && - (spec = _loop0_113_rule(p)) // fstring_format_spec* + (spec = _loop0_112_rule(p)) // fstring_format_spec* ) { D(fprintf(stderr, "%*c+ fstring_full_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' fstring_format_spec*")); @@ -16274,7 +16256,7 @@ fstring_rule(Parser *p) if ( (a = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' && - (b = _loop0_114_rule(p)) // fstring_middle* + (b = _loop0_113_rule(p)) // fstring_middle* && (c = _PyPegen_expect_token(p, FSTRING_END)) // token='FSTRING_END' ) @@ -16375,7 +16357,7 @@ strings_rule(Parser *p) D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((fstring | string))+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_loop1_115_rule(p)) // ((fstring | string))+ + (a = (asdl_expr_seq*)_loop1_114_rule(p)) // ((fstring | string))+ ) { D(fprintf(stderr, "%*c+ strings[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((fstring | string))+")); @@ -16508,7 +16490,7 @@ tuple_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_116_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] + (a = _tmp_115_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -16723,7 +16705,7 @@ double_starred_kvpairs_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_117_rule(p)) // ','.double_starred_kvpair+ + (a = _gather_116_rule(p)) // ','.double_starred_kvpair+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -16882,7 +16864,7 @@ for_if_clauses_rule(Parser *p) D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); asdl_comprehension_seq* a; if ( - (a = (asdl_comprehension_seq*)_loop1_119_rule(p)) // for_if_clause+ + (a = (asdl_comprehension_seq*)_loop1_118_rule(p)) // for_if_clause+ ) { D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); @@ -16947,7 +16929,7 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_120_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_119_rule(p)) // (('if' disjunction))* ) { 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))*")); @@ -16990,7 +16972,7 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_121_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_120_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -17019,13 +17001,13 @@ for_if_clause_rule(Parser *p) Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_122_var; + void *_tmp_121_var; if ( (_opt_var = _PyPegen_expect_token(p, 674), !p->error_indicator) // 'async'? && (_keyword = _PyPegen_expect_token(p, 672)) // token='for' && - (_tmp_122_var = _tmp_122_rule(p)) // bitwise_or ((',' bitwise_or))* ','? + (_tmp_121_var = _tmp_121_rule(p)) // bitwise_or ((',' bitwise_or))* ','? && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 673) // token='in' ) @@ -17283,7 +17265,7 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_123_rule(p)) // assignment_expression | expression !':=' + (a = _tmp_122_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && @@ -17532,9 +17514,9 @@ args_rule(Parser *p) asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_124_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + (a = (asdl_expr_seq*)_gather_123_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && - (b = _tmp_126_rule(p), !p->error_indicator) // [',' kwargs] + (b = _tmp_125_rule(p), !p->error_indicator) // [',' kwargs] ) { D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); @@ -17624,11 +17606,11 @@ kwargs_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _gather_127_rule(p)) // ','.kwarg_or_starred+ + (a = _gather_126_rule(p)) // ','.kwarg_or_starred+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _gather_129_rule(p)) // ','.kwarg_or_double_starred+ + (b = _gather_128_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -17650,13 +17632,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - asdl_seq * _gather_131_var; + asdl_seq * _gather_130_var; if ( - (_gather_131_var = _gather_131_rule(p)) // ','.kwarg_or_starred+ + (_gather_130_var = _gather_130_rule(p)) // ','.kwarg_or_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - _res = _gather_131_var; + _res = _gather_130_var; goto done; } p->mark = _mark; @@ -17669,13 +17651,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - asdl_seq * _gather_133_var; + asdl_seq * _gather_132_var; if ( - (_gather_133_var = _gather_133_rule(p)) // ','.kwarg_or_double_starred+ + (_gather_132_var = _gather_132_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - _res = _gather_133_var; + _res = _gather_132_var; goto done; } p->mark = _mark; @@ -18088,7 +18070,7 @@ star_targets_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop0_135_rule(p)) // ((',' star_target))* + (b = _loop0_134_rule(p)) // ((',' star_target))* && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18144,7 +18126,7 @@ star_targets_list_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_136_rule(p)) // ','.star_target+ + (a = (asdl_expr_seq*)_gather_135_rule(p)) // ','.star_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18194,7 +18176,7 @@ star_targets_tuple_seq_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop1_138_rule(p)) // ((',' star_target))+ + (b = _loop1_137_rule(p)) // ((',' star_target))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18282,7 +18264,7 @@ star_target_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (a = _tmp_139_rule(p)) // !'*' star_target + (a = _tmp_138_rule(p)) // !'*' star_target ) { D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -18378,7 +18360,7 @@ target_with_star_atom_rule(Parser *p) && (b = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(0, t_lookahead_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -18422,7 +18404,7 @@ target_with_star_atom_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' && - _PyPegen_lookahead(0, t_lookahead_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -18769,7 +18751,7 @@ single_subscript_attribute_target_rule(Parser *p) && (b = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(0, t_lookahead_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -18813,7 +18795,7 @@ single_subscript_attribute_target_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' && - _PyPegen_lookahead(0, t_lookahead_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ single_subscript_attribute_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -18923,7 +18905,7 @@ t_primary_raw(Parser *p) && (b = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(1, t_lookahead_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME &t_lookahead")); @@ -18967,7 +18949,7 @@ t_primary_raw(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' && - _PyPegen_lookahead(1, t_lookahead_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' &t_lookahead")); @@ -19005,7 +18987,7 @@ t_primary_raw(Parser *p) && (b = genexp_rule(p)) // genexp && - _PyPegen_lookahead(1, t_lookahead_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary genexp &t_lookahead")); @@ -19049,7 +19031,7 @@ t_primary_raw(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - _PyPegen_lookahead(1, t_lookahead_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '(' arguments? ')' &t_lookahead")); @@ -19084,7 +19066,7 @@ t_primary_raw(Parser *p) if ( (a = atom_rule(p)) // atom && - _PyPegen_lookahead(1, t_lookahead_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ t_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "atom &t_lookahead")); @@ -19205,7 +19187,7 @@ del_targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_140_rule(p)) // ','.del_target+ + (a = (asdl_expr_seq*)_gather_139_rule(p)) // ','.del_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -19274,7 +19256,7 @@ del_target_rule(Parser *p) && (b = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(0, t_lookahead_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead")); @@ -19318,7 +19300,7 @@ del_target_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' && - _PyPegen_lookahead(0, t_lookahead_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) t_lookahead_rule, p) ) { D(fprintf(stderr, "%*c+ del_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead")); @@ -19563,7 +19545,7 @@ type_expressions_rule(Parser *p) expr_ty b; expr_ty c; if ( - (a = _gather_142_rule(p)) // ','.expression+ + (a = _gather_141_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19602,7 +19584,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_144_rule(p)) // ','.expression+ + (a = _gather_143_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19635,7 +19617,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_146_rule(p)) // ','.expression+ + (a = _gather_145_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19755,7 +19737,7 @@ type_expressions_rule(Parser *p) D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_148_rule(p)) // ','.expression+ + (a = (asdl_expr_seq*)_gather_147_rule(p)) // ','.expression+ ) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -19806,7 +19788,7 @@ func_type_comment_rule(Parser *p) && (t = _PyPegen_expect_token(p, TYPE_COMMENT)) // token='TYPE_COMMENT' && - _PyPegen_lookahead(1, _tmp_150_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_149_rule, p) ) { D(fprintf(stderr, "%*c+ func_type_comment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -19892,15 +19874,15 @@ invalid_arguments_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' ','.(starred_expression !'=')+")); - asdl_seq * _gather_152_var; - void *_tmp_151_var; + asdl_seq * _gather_151_var; + void *_tmp_150_var; Token * a; if ( - (_tmp_151_var = _tmp_151_rule(p)) // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs + (_tmp_150_var = _tmp_150_rule(p)) // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs && (a = _PyPegen_expect_token(p, 12)) // token=',' && - (_gather_152_var = _gather_152_rule(p)) // ','.(starred_expression !'=')+ + (_gather_151_var = _gather_151_rule(p)) // ','.(starred_expression !'=')+ ) { 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 !'=')+")); @@ -19934,7 +19916,7 @@ invalid_arguments_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_154_rule(p), !p->error_indicator) // [args | expression for_if_clauses] + (_opt_var = _tmp_153_rule(p), !p->error_indicator) // [args | expression for_if_clauses] ) { 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]")); @@ -19994,13 +19976,13 @@ invalid_arguments_rule(Parser *p) expr_ty a; Token * b; if ( - (_opt_var = _tmp_155_rule(p), !p->error_indicator) // [(args ',')] + (_opt_var = _tmp_154_rule(p), !p->error_indicator) // [(args ',')] && (a = _PyPegen_name_token(p)) // NAME && (b = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, _tmp_156_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_155_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(args ',')] NAME '=' &(',' | ')')")); @@ -20138,7 +20120,7 @@ invalid_kwarg_rule(Parser *p) Token* a; Token * b; if ( - (a = (Token*)_tmp_157_rule(p)) // 'True' | 'False' | 'None' + (a = (Token*)_tmp_156_rule(p)) // 'True' | 'False' | 'None' && (b = _PyPegen_expect_token(p, 22)) // token='=' ) @@ -20198,7 +20180,7 @@ invalid_kwarg_rule(Parser *p) expr_ty a; Token * b; if ( - _PyPegen_lookahead(0, _tmp_158_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_157_rule, p) && (a = expression_rule(p)) // expression && @@ -20454,7 +20436,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, _tmp_159_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_158_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -20490,7 +20472,7 @@ invalid_expression_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, _tmp_160_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_159_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -20611,7 +20593,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_161_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_160_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -20637,7 +20619,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, _tmp_162_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_161_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -20645,7 +20627,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_163_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_162_rule, 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 !('=' | ':=')")); @@ -20674,7 +20656,7 @@ invalid_named_expression_rule(Parser *p) // | expression ':' expression // | ((star_targets '='))* star_expressions '=' // | ((star_targets '='))* yield_expr '=' -// | star_expressions augassign (yield_expr | star_expressions) +// | star_expressions augassign annotated_rhs static void * invalid_assignment_rule(Parser *p) { @@ -20725,7 +20707,7 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_164_var; + asdl_seq * _loop0_163_var; expr_ty a; expr_ty expression_var; if ( @@ -20733,7 +20715,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_164_var = _loop0_164_rule(p)) // star_named_expressions* + (_loop0_163_var = _loop0_163_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20790,10 +20772,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_165_var; + asdl_seq * _loop0_164_var; expr_ty a; if ( - (_loop0_165_var = _loop0_165_rule(p)) // ((star_targets '='))* + (_loop0_164_var = _loop0_164_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -20820,10 +20802,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_166_var; + asdl_seq * _loop0_165_var; expr_ty a; if ( - (_loop0_166_var = _loop0_166_rule(p)) // ((star_targets '='))* + (_loop0_165_var = _loop0_165_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -20843,24 +20825,24 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_assignment[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "((star_targets '='))* yield_expr '='")); } - { // star_expressions augassign (yield_expr | star_expressions) + { // star_expressions augassign annotated_rhs if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_167_var; + D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign annotated_rhs")); expr_ty a; + expr_ty annotated_rhs_var; AugOperator* augassign_var; if ( (a = star_expressions_rule(p)) // star_expressions && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_167_var = _tmp_167_rule(p)) // yield_expr | star_expressions + (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs ) { - D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); + 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()) { p->error_indicator = 1; @@ -20871,7 +20853,7 @@ invalid_assignment_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_assignment[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions augassign annotated_rhs")); } _res = NULL; done: @@ -21079,11 +21061,11 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_168_var; + void *_tmp_166_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_168_var = _tmp_168_rule(p)) // '[' | '(' | '{' + (_tmp_166_var = _tmp_166_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -21110,12 +21092,12 @@ invalid_comprehension_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); Token * _literal; - void *_tmp_169_var; + void *_tmp_167_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_169_var = _tmp_169_rule(p)) // '[' | '{' + (_tmp_167_var = _tmp_167_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21145,12 +21127,12 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); - void *_tmp_170_var; + void *_tmp_168_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_170_var = _tmp_170_rule(p)) // '[' | '{' + (_tmp_168_var = _tmp_168_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21285,13 +21267,13 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slash_no_default | slash_with_default) param_maybe_default* '/'")); - asdl_seq * _loop0_172_var; - void *_tmp_171_var; + asdl_seq * _loop0_170_var; + void *_tmp_169_var; Token * a; if ( - (_tmp_171_var = _tmp_171_rule(p)) // slash_no_default | slash_with_default + (_tmp_169_var = _tmp_169_rule(p)) // slash_no_default | slash_with_default && - (_loop0_172_var = _loop0_172_rule(p)) // param_maybe_default* + (_loop0_170_var = _loop0_170_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21315,7 +21297,7 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default? param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_173_var; + asdl_seq * _loop0_171_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -21323,7 +21305,7 @@ invalid_parameters_rule(Parser *p) if ( (_opt_var = slash_no_default_rule(p), !p->error_indicator) // slash_no_default? && - (_loop0_173_var = _loop0_173_rule(p)) // param_no_default* + (_loop0_171_var = _loop0_171_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -21349,18 +21331,18 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); - asdl_seq * _loop0_174_var; - asdl_seq * _loop1_175_var; + asdl_seq * _loop0_172_var; + asdl_seq * _loop1_173_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_174_var = _loop0_174_rule(p)) // param_no_default* + (_loop0_172_var = _loop0_172_rule(p)) // param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_loop1_175_var = _loop1_175_rule(p)) // param_no_default+ + (_loop1_173_var = _loop1_173_rule(p)) // param_no_default+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -21387,22 +21369,22 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[(slash_no_default | slash_with_default)] param_maybe_default* '*' (',' | param_no_default) param_maybe_default* '/'")); Token * _literal; + asdl_seq * _loop0_175_var; asdl_seq * _loop0_177_var; - asdl_seq * _loop0_179_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_178_var; + void *_tmp_176_var; Token * a; if ( - (_opt_var = _tmp_176_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] + (_opt_var = _tmp_174_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] && - (_loop0_177_var = _loop0_177_rule(p)) // param_maybe_default* + (_loop0_175_var = _loop0_175_rule(p)) // param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_178_var = _tmp_178_rule(p)) // ',' | param_no_default + (_tmp_176_var = _tmp_176_rule(p)) // ',' | param_no_default && - (_loop0_179_var = _loop0_179_rule(p)) // param_maybe_default* + (_loop0_177_var = _loop0_177_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21427,10 +21409,10 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_180_var; + asdl_seq * _loop1_178_var; Token * a; if ( - (_loop1_180_var = _loop1_180_rule(p)) // param_maybe_default+ + (_loop1_178_var = _loop1_178_rule(p)) // param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -21479,7 +21461,7 @@ invalid_default_rule(Parser *p) if ( (a = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, _tmp_181_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_179_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' &(')' | ',')")); @@ -21524,12 +21506,12 @@ invalid_star_etc_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_182_var; + void *_tmp_180_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_182_var = _tmp_182_rule(p)) // ')' | ',' (')' | '**') + (_tmp_180_var = _tmp_180_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -21612,20 +21594,20 @@ invalid_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_184_var; + asdl_seq * _loop0_182_var; + void *_tmp_181_var; void *_tmp_183_var; - void *_tmp_185_var; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_183_var = _tmp_183_rule(p)) // param_no_default | ',' + (_tmp_181_var = _tmp_181_rule(p)) // param_no_default | ',' && - (_loop0_184_var = _loop0_184_rule(p)) // param_maybe_default* + (_loop0_182_var = _loop0_182_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_185_var = _tmp_185_rule(p)) // param_no_default | ',' + (_tmp_183_var = _tmp_183_rule(p)) // param_no_default | ',' ) { 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 | ',')")); @@ -21740,7 +21722,7 @@ invalid_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_186_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_184_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' ('*' | '**' | '/')")); @@ -21805,13 +21787,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_187_var; + asdl_seq * _loop1_185_var; if ( - (_loop1_187_var = _loop1_187_rule(p)) // param_with_default+ + (_loop1_185_var = _loop1_185_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_187_var; + _res = _loop1_185_var; goto done; } p->mark = _mark; @@ -21876,13 +21858,13 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* '/'")); - asdl_seq * _loop0_189_var; - void *_tmp_188_var; + asdl_seq * _loop0_187_var; + void *_tmp_186_var; Token * a; if ( - (_tmp_188_var = _tmp_188_rule(p)) // lambda_slash_no_default | lambda_slash_with_default + (_tmp_186_var = _tmp_186_rule(p)) // lambda_slash_no_default | lambda_slash_with_default && - (_loop0_189_var = _loop0_189_rule(p)) // lambda_param_maybe_default* + (_loop0_187_var = _loop0_187_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21906,7 +21888,7 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_190_var; + asdl_seq * _loop0_188_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -21914,7 +21896,7 @@ invalid_lambda_parameters_rule(Parser *p) if ( (_opt_var = lambda_slash_no_default_rule(p), !p->error_indicator) // lambda_slash_no_default? && - (_loop0_190_var = _loop0_190_rule(p)) // lambda_param_no_default* + (_loop0_188_var = _loop0_188_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -21940,18 +21922,18 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); - asdl_seq * _gather_192_var; - asdl_seq * _loop0_191_var; + asdl_seq * _gather_190_var; + asdl_seq * _loop0_189_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_191_var = _loop0_191_rule(p)) // lambda_param_no_default* + (_loop0_189_var = _loop0_189_rule(p)) // lambda_param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_192_var = _gather_192_rule(p)) // ','.lambda_param+ + (_gather_190_var = _gather_190_rule(p)) // ','.lambda_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -21978,22 +21960,22 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\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* '/'")); Token * _literal; + asdl_seq * _loop0_193_var; asdl_seq * _loop0_195_var; - asdl_seq * _loop0_197_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_196_var; + void *_tmp_194_var; Token * a; if ( - (_opt_var = _tmp_194_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] + (_opt_var = _tmp_192_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] && - (_loop0_195_var = _loop0_195_rule(p)) // lambda_param_maybe_default* + (_loop0_193_var = _loop0_193_rule(p)) // lambda_param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_196_var = _tmp_196_rule(p)) // ',' | lambda_param_no_default + (_tmp_194_var = _tmp_194_rule(p)) // ',' | lambda_param_no_default && - (_loop0_197_var = _loop0_197_rule(p)) // lambda_param_maybe_default* + (_loop0_195_var = _loop0_195_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -22018,10 +22000,10 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_198_var; + asdl_seq * _loop1_196_var; Token * a; if ( - (_loop1_198_var = _loop1_198_rule(p)) // lambda_param_maybe_default+ + (_loop1_196_var = _loop1_196_rule(p)) // lambda_param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -22092,13 +22074,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_199_var; + asdl_seq * _loop1_197_var; if ( - (_loop1_199_var = _loop1_199_rule(p)) // lambda_param_with_default+ + (_loop1_197_var = _loop1_197_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_199_var; + _res = _loop1_197_var; goto done; } p->mark = _mark; @@ -22134,11 +22116,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_200_var; + void *_tmp_198_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_200_var = _tmp_200_rule(p)) // ':' | ',' (':' | '**') + (_tmp_198_var = _tmp_198_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -22191,20 +22173,20 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_202_var; + asdl_seq * _loop0_200_var; + void *_tmp_199_var; void *_tmp_201_var; - void *_tmp_203_var; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_201_var = _tmp_201_rule(p)) // lambda_param_no_default | ',' + (_tmp_199_var = _tmp_199_rule(p)) // lambda_param_no_default | ',' && - (_loop0_202_var = _loop0_202_rule(p)) // lambda_param_maybe_default* + (_loop0_200_var = _loop0_200_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_203_var = _tmp_203_rule(p)) // lambda_param_no_default | ',' + (_tmp_201_var = _tmp_201_rule(p)) // lambda_param_no_default | ',' ) { 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 | ',')")); @@ -22322,7 +22304,7 @@ invalid_lambda_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_204_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_202_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' ('*' | '**' | '/')")); @@ -22428,7 +22410,7 @@ invalid_with_item_rule(Parser *p) && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_205_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_203_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -22601,14 +22583,14 @@ invalid_import_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_import[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name")); - asdl_seq * _gather_206_var; + asdl_seq * _gather_204_var; Token * _keyword; Token * a; expr_ty dotted_name_var; if ( (a = _PyPegen_expect_token(p, 622)) // token='import' && - (_gather_206_var = _gather_206_rule(p)) // ','.dotted_name+ + (_gather_204_var = _gather_204_rule(p)) // ','.dotted_name+ && (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && @@ -22831,7 +22813,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE")); - asdl_seq * _gather_208_var; + asdl_seq * _gather_206_var; Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22841,7 +22823,7 @@ invalid_with_stmt_rule(Parser *p) && (_keyword = _PyPegen_expect_token(p, 635)) // token='with' && - (_gather_208_var = _gather_208_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_206_var = _gather_206_rule(p)) // ','.(expression ['as' star_target])+ && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -22865,7 +22847,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE")); - asdl_seq * _gather_210_var; + asdl_seq * _gather_208_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -22881,7 +22863,7 @@ invalid_with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_210_var = _gather_210_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_208_var = _gather_208_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22930,7 +22912,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_212_var; + asdl_seq * _gather_210_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22941,7 +22923,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (a = _PyPegen_expect_token(p, 635)) // token='with' && - (_gather_212_var = _gather_212_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_210_var = _gather_210_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -22969,7 +22951,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_214_var; + asdl_seq * _gather_212_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -22986,7 +22968,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_214_var = _gather_214_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_212_var = _gather_212_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -23083,7 +23065,7 @@ invalid_try_stmt_rule(Parser *p) && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, _tmp_216_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_214_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -23108,8 +23090,8 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_217_var; - asdl_seq * _loop1_218_var; + asdl_seq * _loop0_215_var; + asdl_seq * _loop1_216_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; @@ -23120,9 +23102,9 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_217_var = _loop0_217_rule(p)) // block* + (_loop0_215_var = _loop0_215_rule(p)) // block* && - (_loop1_218_var = _loop1_218_rule(p)) // except_block+ + (_loop1_216_var = _loop1_216_rule(p)) // except_block+ && (a = _PyPegen_expect_token(p, 657)) // token='except' && @@ -23130,7 +23112,7 @@ invalid_try_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_219_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_217_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23157,8 +23139,8 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_220_var; - asdl_seq * _loop1_221_var; + asdl_seq * _loop0_218_var; + asdl_seq * _loop1_219_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; @@ -23167,13 +23149,13 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_220_var = _loop0_220_rule(p)) // block* + (_loop0_218_var = _loop0_218_rule(p)) // block* && - (_loop1_221_var = _loop1_221_rule(p)) // except_star_block+ + (_loop1_219_var = _loop1_219_rule(p)) // except_star_block+ && (a = _PyPegen_expect_token(p, 657)) // token='except' && - (_opt_var = _tmp_222_rule(p), !p->error_indicator) // [expression ['as' NAME]] + (_opt_var = _tmp_220_rule(p), !p->error_indicator) // [expression ['as' NAME]] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23240,7 +23222,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var_1 = _tmp_223_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_221_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23278,7 +23260,7 @@ invalid_except_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var_1 = _tmp_224_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_222_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -23330,14 +23312,14 @@ invalid_except_stmt_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); Token * _literal; - void *_tmp_225_var; + void *_tmp_223_var; Token * a; if ( (a = _PyPegen_expect_token(p, 657)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_225_var = _tmp_225_rule(p)) // NEWLINE | ':' + (_tmp_223_var = _tmp_223_rule(p)) // NEWLINE | ':' ) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); @@ -23442,7 +23424,7 @@ invalid_except_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_226_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_224_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23536,7 +23518,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_227_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_225_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23900,7 +23882,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_228_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_226_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -24392,7 +24374,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_3 = _tmp_229_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_3 = _tmp_227_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24455,7 +24437,7 @@ invalid_class_def_raw_rule(Parser *p) && (_opt_var = type_params_rule(p), !p->error_indicator) // type_params? && - (_opt_var_1 = _tmp_230_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var_1 = _tmp_228_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -24494,7 +24476,7 @@ invalid_class_def_raw_rule(Parser *p) && (_opt_var = type_params_rule(p), !p->error_indicator) // type_params? && - (_opt_var_1 = _tmp_231_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var_1 = _tmp_229_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24544,11 +24526,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_232_var; + asdl_seq * _gather_230_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_232_var = _gather_232_rule(p)) // ','.double_starred_kvpair+ + (_gather_230_var = _gather_230_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -24556,7 +24538,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, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_232_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_230_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -24609,7 +24591,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_234_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_232_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -24719,7 +24701,7 @@ invalid_kvpair_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_235_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_233_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -24798,13 +24780,13 @@ invalid_starred_expression_rule(Parser *p) // | '{' '!' // | '{' ':' // | '{' '}' -// | '{' !(yield_expr | star_expressions) -// | '{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}') -// | '{' (yield_expr | star_expressions) '=' !('!' | ':' | '}') -// | '{' (yield_expr | star_expressions) '='? invalid_conversion_character -// | '{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}') -// | '{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}' -// | '{' (yield_expr | star_expressions) '='? ['!' NAME] !'}' +// | '{' !annotated_rhs +// | '{' annotated_rhs !('=' | '!' | ':' | '}') +// | '{' annotated_rhs '=' !('!' | ':' | '}') +// | '{' annotated_rhs '='? invalid_conversion_character +// | '{' annotated_rhs '='? ['!' NAME] !(':' | '}') +// | '{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}' +// | '{' annotated_rhs '='? ['!' NAME] !'}' static void * invalid_replacement_field_rule(Parser *p) { @@ -24925,20 +24907,20 @@ invalid_replacement_field_rule(Parser *p) D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' '}'")); } - { // '{' !(yield_expr | star_expressions) + { // '{' !annotated_rhs if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' !(yield_expr | star_expressions)")); + D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' !annotated_rhs")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - _PyPegen_lookahead(0, _tmp_236_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) annotated_rhs_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !(yield_expr | star_expressions)")); + D(fprintf(stderr, "%*c+ invalid_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()) { p->error_indicator = 1; @@ -24949,25 +24931,25 @@ invalid_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' !(yield_expr | star_expressions)")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' !annotated_rhs")); } - { // '{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}') + { // '{' annotated_rhs !('=' | '!' | ':' | '}') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')")); + D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); Token * _literal; - void *_tmp_237_var; + expr_ty annotated_rhs_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_237_var = _tmp_237_rule(p)) // yield_expr | star_expressions + (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && - _PyPegen_lookahead(0, _tmp_238_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_234_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')")); + D(fprintf(stderr, "%*c+ invalid_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()) { p->error_indicator = 1; @@ -24978,28 +24960,28 @@ invalid_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); } - { // '{' (yield_expr | star_expressions) '=' !('!' | ':' | '}') + { // '{' annotated_rhs '=' !('!' | ':' | '}') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')")); + D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); Token * _literal; Token * _literal_1; - void *_tmp_239_var; + expr_ty annotated_rhs_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_239_var = _tmp_239_rule(p)) // yield_expr | star_expressions + (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && (_literal_1 = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(0, _tmp_240_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_235_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')")); + D(fprintf(stderr, "%*c+ invalid_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()) { p->error_indicator = 1; @@ -25010,62 +24992,62 @@ invalid_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); } - { // '{' (yield_expr | star_expressions) '='? invalid_conversion_character + { // '{' annotated_rhs '='? invalid_conversion_character if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? invalid_conversion_character")); + D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? invalid_conversion_character")); Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_241_var; + expr_ty annotated_rhs_var; void *invalid_conversion_character_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_241_var = _tmp_241_rule(p)) // yield_expr | star_expressions + (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && (invalid_conversion_character_var = invalid_conversion_character_rule(p)) // invalid_conversion_character ) { - D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? invalid_conversion_character")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_241_var, _opt_var, invalid_conversion_character_var); + D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? invalid_conversion_character")); + _res = _PyPegen_dummy_name(p, _literal, annotated_rhs_var, _opt_var, invalid_conversion_character_var); goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) '='? invalid_conversion_character")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' annotated_rhs '='? invalid_conversion_character")); } - { // '{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}') + { // '{' annotated_rhs '='? ['!' NAME] !(':' | '}') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}')")); + D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_242_var; + expr_ty annotated_rhs_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_242_var = _tmp_242_rule(p)) // yield_expr | star_expressions + (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_243_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_236_rule(p), !p->error_indicator) // ['!' NAME] && - _PyPegen_lookahead(0, _tmp_244_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_237_rule, p) ) { - D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}')")); + D(fprintf(stderr, "%*c+ invalid_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()) { p->error_indicator = 1; @@ -25076,39 +25058,39 @@ invalid_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}')")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); } - { // '{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}' + { // '{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}'")); + D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}'")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_247_var; + asdl_seq * _loop0_239_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_245_var; + expr_ty annotated_rhs_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_245_var = _tmp_245_rule(p)) // yield_expr | star_expressions + (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_246_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_238_rule(p), !p->error_indicator) // ['!' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_247_var = _loop0_247_rule(p)) // fstring_format_spec* + (_loop0_239_var = _loop0_239_rule(p)) // fstring_format_spec* && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) { - D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}'")); + D(fprintf(stderr, "%*c+ invalid_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()) { p->error_indicator = 1; @@ -25119,33 +25101,33 @@ invalid_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}'")); } - { // '{' (yield_expr | star_expressions) '='? ['!' NAME] !'}' + { // '{' annotated_rhs '='? ['!' NAME] !'}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !'}'")); + D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !'}'")); Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_248_var; + expr_ty annotated_rhs_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_248_var = _tmp_248_rule(p)) // yield_expr | star_expressions + (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_249_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_240_rule(p), !p->error_indicator) // ['!' NAME] && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) { - D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !'}'")); + D(fprintf(stderr, "%*c+ invalid_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()) { p->error_indicator = 1; @@ -25156,7 +25138,7 @@ invalid_replacement_field_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s invalid_replacement_field[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !'}'")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !'}'")); } _res = NULL; done: @@ -25187,7 +25169,7 @@ invalid_conversion_character_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' && - _PyPegen_lookahead(1, _tmp_250_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_241_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); @@ -25254,14 +25236,14 @@ invalid_arithmetic_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_arithmetic[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum ('+' | '-' | '*' | '/' | '%' | '//' | '@') 'not' inversion")); - void *_tmp_251_var; + void *_tmp_242_var; Token * a; expr_ty b; expr_ty sum_var; if ( (sum_var = sum_rule(p)) // sum && - (_tmp_251_var = _tmp_251_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' + (_tmp_242_var = _tmp_242_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' && (a = _PyPegen_expect_token(p, 679)) // token='not' && @@ -25306,11 +25288,11 @@ invalid_factor_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('+' | '-' | '~') 'not' factor")); - void *_tmp_252_var; + void *_tmp_243_var; Token * a; expr_ty b; if ( - (_tmp_252_var = _tmp_252_rule(p)) // '+' | '-' | '~' + (_tmp_243_var = _tmp_243_rule(p)) // '+' | '-' | '~' && (a = _PyPegen_expect_token(p, 679)) // token='not' && @@ -26151,12 +26133,12 @@ _loop1_14_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_253_var; + void *_tmp_244_var; while ( - (_tmp_253_var = _tmp_253_rule(p)) // star_targets '=' + (_tmp_244_var = _tmp_244_rule(p)) // star_targets '=' ) { - _res = _tmp_253_var; + _res = _tmp_244_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26720,12 +26702,12 @@ _loop0_24_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_254_var; + void *_tmp_245_var; while ( - (_tmp_254_var = _tmp_254_rule(p)) // '.' | '...' + (_tmp_245_var = _tmp_245_rule(p)) // '.' | '...' ) { - _res = _tmp_254_var; + _res = _tmp_245_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26787,12 +26769,12 @@ _loop1_25_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_255_var; + void *_tmp_246_var; while ( - (_tmp_255_var = _tmp_255_rule(p)) // '.' | '...' + (_tmp_246_var = _tmp_246_rule(p)) // '.' | '...' ) { - _res = _tmp_255_var; + _res = _tmp_246_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27185,12 +27167,12 @@ _loop1_32_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_256_var; + void *_tmp_247_var; while ( - (_tmp_256_var = _tmp_256_rule(p)) // '@' named_expression NEWLINE + (_tmp_247_var = _tmp_247_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_256_var; + _res = _tmp_247_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30315,12 +30297,12 @@ _loop1_82_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_257_var; + void *_tmp_248_var; while ( - (_tmp_257_var = _tmp_257_rule(p)) // ',' expression + (_tmp_248_var = _tmp_248_rule(p)) // ',' expression ) { - _res = _tmp_257_var; + _res = _tmp_248_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30387,12 +30369,12 @@ _loop1_83_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_258_var; + void *_tmp_249_var; while ( - (_tmp_258_var = _tmp_258_rule(p)) // ',' star_expression + (_tmp_249_var = _tmp_249_rule(p)) // ',' star_expression ) { - _res = _tmp_258_var; + _res = _tmp_249_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30576,12 +30558,12 @@ _loop1_86_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_259_var; + void *_tmp_250_var; while ( - (_tmp_259_var = _tmp_259_rule(p)) // 'or' conjunction + (_tmp_250_var = _tmp_250_rule(p)) // 'or' conjunction ) { - _res = _tmp_259_var; + _res = _tmp_250_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30648,12 +30630,12 @@ _loop1_87_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_260_var; + void *_tmp_251_var; while ( - (_tmp_260_var = _tmp_260_rule(p)) // 'and' inversion + (_tmp_251_var = _tmp_251_rule(p)) // 'and' inversion ) { - _res = _tmp_260_var; + _res = _tmp_251_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30840,7 +30822,7 @@ _loop0_91_rule(Parser *p) while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_261_rule(p)) // slice | starred_expression + (elem = _tmp_252_rule(p)) // slice | starred_expression ) { _res = elem; @@ -30905,7 +30887,7 @@ _gather_90_rule(Parser *p) void *elem; asdl_seq * seq; if ( - (elem = _tmp_261_rule(p)) // slice | starred_expression + (elem = _tmp_252_rule(p)) // slice | starred_expression && (seq = _loop0_91_rule(p)) // _loop0_91 ) @@ -32285,66 +32267,9 @@ _loop1_111_rule(Parser *p) return _seq; } -// _tmp_112: yield_expr | star_expressions -static void * -_tmp_112_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_113: fstring_format_spec +// _loop0_112: fstring_format_spec static asdl_seq * -_loop0_113_rule(Parser *p) +_loop0_112_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32369,7 +32294,7 @@ _loop0_113_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); + D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); expr_ty fstring_format_spec_var; while ( (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec @@ -32392,7 +32317,7 @@ _loop0_113_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32409,9 +32334,9 @@ _loop0_113_rule(Parser *p) return _seq; } -// _loop0_114: fstring_middle +// _loop0_113: fstring_middle static asdl_seq * -_loop0_114_rule(Parser *p) +_loop0_113_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32436,7 +32361,7 @@ _loop0_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_middle")); + D(fprintf(stderr, "%*c> _loop0_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_middle")); expr_ty fstring_middle_var; while ( (fstring_middle_var = fstring_middle_rule(p)) // fstring_middle @@ -32459,7 +32384,7 @@ _loop0_114_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_113[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_middle")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32476,9 +32401,9 @@ _loop0_114_rule(Parser *p) return _seq; } -// _loop1_115: (fstring | string) +// _loop1_114: (fstring | string) static asdl_seq * -_loop1_115_rule(Parser *p) +_loop1_114_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32503,13 +32428,13 @@ _loop1_115_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); - void *_tmp_262_var; + D(fprintf(stderr, "%*c> _loop1_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); + void *_tmp_253_var; while ( - (_tmp_262_var = _tmp_262_rule(p)) // fstring | string + (_tmp_253_var = _tmp_253_rule(p)) // fstring | string ) { - _res = _tmp_262_var; + _res = _tmp_253_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32526,7 +32451,7 @@ _loop1_115_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_115[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_114[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(fstring | string)")); } if (_n == 0 || p->error_indicator) { @@ -32548,9 +32473,9 @@ _loop1_115_rule(Parser *p) return _seq; } -// _tmp_116: star_named_expression ',' star_named_expressions? +// _tmp_115: star_named_expression ',' star_named_expressions? static void * -_tmp_116_rule(Parser *p) +_tmp_115_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32566,7 +32491,7 @@ _tmp_116_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); Token * _literal; expr_ty y; void *z; @@ -32578,7 +32503,7 @@ _tmp_116_rule(Parser *p) (z = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? ) { - D(fprintf(stderr, "%*c+ _tmp_116[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32588,7 +32513,7 @@ _tmp_116_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_116[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_115[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression ',' star_named_expressions?")); } _res = NULL; @@ -32597,9 +32522,9 @@ _tmp_116_rule(Parser *p) return _res; } -// _loop0_118: ',' double_starred_kvpair +// _loop0_117: ',' double_starred_kvpair static asdl_seq * -_loop0_118_rule(Parser *p) +_loop0_117_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32624,7 +32549,7 @@ _loop0_118_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -32656,7 +32581,7 @@ _loop0_118_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_118[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_117[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32673,9 +32598,9 @@ _loop0_118_rule(Parser *p) return _seq; } -// _gather_117: double_starred_kvpair _loop0_118 +// _gather_116: double_starred_kvpair _loop0_117 static asdl_seq * -_gather_117_rule(Parser *p) +_gather_116_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32686,27 +32611,27 @@ _gather_117_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_118 + { // double_starred_kvpair _loop0_117 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_118")); + D(fprintf(stderr, "%*c> _gather_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_117")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_118_rule(p)) // _loop0_118 + (seq = _loop0_117_rule(p)) // _loop0_117 ) { - D(fprintf(stderr, "%*c+ _gather_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_118")); + D(fprintf(stderr, "%*c+ _gather_116[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_117")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_117[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_118")); + D(fprintf(stderr, "%*c%s _gather_116[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_117")); } _res = NULL; done: @@ -32714,9 +32639,9 @@ _gather_117_rule(Parser *p) return _res; } -// _loop1_119: for_if_clause +// _loop1_118: for_if_clause static asdl_seq * -_loop1_119_rule(Parser *p) +_loop1_118_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32741,7 +32666,7 @@ _loop1_119_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); + D(fprintf(stderr, "%*c> _loop1_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); comprehension_ty for_if_clause_var; while ( (for_if_clause_var = for_if_clause_rule(p)) // for_if_clause @@ -32764,7 +32689,7 @@ _loop1_119_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_119[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_118[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "for_if_clause")); } if (_n == 0 || p->error_indicator) { @@ -32786,9 +32711,9 @@ _loop1_119_rule(Parser *p) return _seq; } -// _loop0_120: ('if' disjunction) +// _loop0_119: ('if' disjunction) static asdl_seq * -_loop0_120_rule(Parser *p) +_loop0_119_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32813,13 +32738,13 @@ _loop0_120_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_263_var; + D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_254_var; while ( - (_tmp_263_var = _tmp_263_rule(p)) // 'if' disjunction + (_tmp_254_var = _tmp_254_rule(p)) // 'if' disjunction ) { - _res = _tmp_263_var; + _res = _tmp_254_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32836,7 +32761,7 @@ _loop0_120_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_119[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32853,9 +32778,9 @@ _loop0_120_rule(Parser *p) return _seq; } -// _loop0_121: ('if' disjunction) +// _loop0_120: ('if' disjunction) static asdl_seq * -_loop0_121_rule(Parser *p) +_loop0_120_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32880,13 +32805,13 @@ _loop0_121_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_264_var; + D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_255_var; while ( - (_tmp_264_var = _tmp_264_rule(p)) // 'if' disjunction + (_tmp_255_var = _tmp_255_rule(p)) // 'if' disjunction ) { - _res = _tmp_264_var; + _res = _tmp_255_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32903,7 +32828,7 @@ _loop0_121_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_121[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32920,9 +32845,9 @@ _loop0_121_rule(Parser *p) return _seq; } -// _tmp_122: bitwise_or ((',' bitwise_or))* ','? +// _tmp_121: bitwise_or ((',' bitwise_or))* ','? static void * -_tmp_122_rule(Parser *p) +_tmp_121_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32938,25 +32863,25 @@ _tmp_122_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); - asdl_seq * _loop0_265_var; + D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + asdl_seq * _loop0_256_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty bitwise_or_var; if ( (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - (_loop0_265_var = _loop0_265_rule(p)) // ((',' bitwise_or))* + (_loop0_256_var = _loop0_256_rule(p)) // ((',' bitwise_or))* && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { - D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); - _res = _PyPegen_dummy_name(p, bitwise_or_var, _loop0_265_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + _res = _PyPegen_dummy_name(p, bitwise_or_var, _loop0_256_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_121[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); } _res = NULL; @@ -32965,9 +32890,9 @@ _tmp_122_rule(Parser *p) return _res; } -// _tmp_123: assignment_expression | expression !':=' +// _tmp_122: assignment_expression | expression !':=' static void * -_tmp_123_rule(Parser *p) +_tmp_122_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32983,18 +32908,18 @@ _tmp_123_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_123[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -33002,7 +32927,7 @@ _tmp_123_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -33010,12 +32935,12 @@ _tmp_123_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_123[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -33024,9 +32949,9 @@ _tmp_123_rule(Parser *p) return _res; } -// _loop0_125: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +// _loop0_124: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * -_loop0_125_rule(Parser *p) +_loop0_124_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33051,13 +32976,13 @@ _loop0_125_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_266_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_257_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -33083,7 +33008,7 @@ _loop0_125_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_125[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33100,10 +33025,10 @@ _loop0_125_rule(Parser *p) return _seq; } -// _gather_124: -// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125 +// _gather_123: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 static asdl_seq * -_gather_124_rule(Parser *p) +_gather_123_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33114,27 +33039,27 @@ _gather_124_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125")); + D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_266_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_257_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && - (seq = _loop0_125_rule(p)) // _loop0_125 + (seq = _loop0_124_rule(p)) // _loop0_124 ) { - D(fprintf(stderr, "%*c+ _gather_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125")); + D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_124[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_125")); + D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); } _res = NULL; done: @@ -33142,9 +33067,9 @@ _gather_124_rule(Parser *p) return _res; } -// _tmp_126: ',' kwargs +// _tmp_125: ',' kwargs static void * -_tmp_126_rule(Parser *p) +_tmp_125_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33160,7 +33085,7 @@ _tmp_126_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); Token * _literal; asdl_seq* k; if ( @@ -33169,7 +33094,7 @@ _tmp_126_rule(Parser *p) (k = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -33179,7 +33104,7 @@ _tmp_126_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); } _res = NULL; @@ -33188,9 +33113,9 @@ _tmp_126_rule(Parser *p) return _res; } -// _loop0_128: ',' kwarg_or_starred +// _loop0_127: ',' kwarg_or_starred static asdl_seq * -_loop0_128_rule(Parser *p) +_loop0_127_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33215,7 +33140,7 @@ _loop0_128_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33247,7 +33172,7 @@ _loop0_128_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33264,9 +33189,9 @@ _loop0_128_rule(Parser *p) return _seq; } -// _gather_127: kwarg_or_starred _loop0_128 +// _gather_126: kwarg_or_starred _loop0_127 static asdl_seq * -_gather_127_rule(Parser *p) +_gather_126_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33277,27 +33202,27 @@ _gather_127_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_128 + { // kwarg_or_starred _loop0_127 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_128")); + D(fprintf(stderr, "%*c> _gather_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_128_rule(p)) // _loop0_128 + (seq = _loop0_127_rule(p)) // _loop0_127 ) { - D(fprintf(stderr, "%*c+ _gather_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_128")); + D(fprintf(stderr, "%*c+ _gather_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_127[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_128")); + D(fprintf(stderr, "%*c%s _gather_126[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_127")); } _res = NULL; done: @@ -33305,9 +33230,9 @@ _gather_127_rule(Parser *p) return _res; } -// _loop0_130: ',' kwarg_or_double_starred +// _loop0_129: ',' kwarg_or_double_starred static asdl_seq * -_loop0_130_rule(Parser *p) +_loop0_129_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33332,7 +33257,7 @@ _loop0_130_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33364,7 +33289,7 @@ _loop0_130_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_130[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33381,9 +33306,9 @@ _loop0_130_rule(Parser *p) return _seq; } -// _gather_129: kwarg_or_double_starred _loop0_130 +// _gather_128: kwarg_or_double_starred _loop0_129 static asdl_seq * -_gather_129_rule(Parser *p) +_gather_128_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33394,27 +33319,27 @@ _gather_129_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_130 + { // kwarg_or_double_starred _loop0_129 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_130")); + D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_130_rule(p)) // _loop0_130 + (seq = _loop0_129_rule(p)) // _loop0_129 ) { - D(fprintf(stderr, "%*c+ _gather_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_130")); + D(fprintf(stderr, "%*c+ _gather_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_129[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_130")); + D(fprintf(stderr, "%*c%s _gather_128[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_129")); } _res = NULL; done: @@ -33422,9 +33347,9 @@ _gather_129_rule(Parser *p) return _res; } -// _loop0_132: ',' kwarg_or_starred +// _loop0_131: ',' kwarg_or_starred static asdl_seq * -_loop0_132_rule(Parser *p) +_loop0_131_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33449,7 +33374,7 @@ _loop0_132_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33481,7 +33406,7 @@ _loop0_132_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_131[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33498,9 +33423,9 @@ _loop0_132_rule(Parser *p) return _seq; } -// _gather_131: kwarg_or_starred _loop0_132 +// _gather_130: kwarg_or_starred _loop0_131 static asdl_seq * -_gather_131_rule(Parser *p) +_gather_130_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33511,27 +33436,27 @@ _gather_131_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_132 + { // kwarg_or_starred _loop0_131 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_132")); + D(fprintf(stderr, "%*c> _gather_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_132_rule(p)) // _loop0_132 + (seq = _loop0_131_rule(p)) // _loop0_131 ) { - D(fprintf(stderr, "%*c+ _gather_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_132")); + D(fprintf(stderr, "%*c+ _gather_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_131[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_132")); + D(fprintf(stderr, "%*c%s _gather_130[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_131")); } _res = NULL; done: @@ -33539,9 +33464,9 @@ _gather_131_rule(Parser *p) return _res; } -// _loop0_134: ',' kwarg_or_double_starred +// _loop0_133: ',' kwarg_or_double_starred static asdl_seq * -_loop0_134_rule(Parser *p) +_loop0_133_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33566,7 +33491,7 @@ _loop0_134_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -33598,7 +33523,7 @@ _loop0_134_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33615,9 +33540,9 @@ _loop0_134_rule(Parser *p) return _seq; } -// _gather_133: kwarg_or_double_starred _loop0_134 +// _gather_132: kwarg_or_double_starred _loop0_133 static asdl_seq * -_gather_133_rule(Parser *p) +_gather_132_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33628,27 +33553,27 @@ _gather_133_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_134 + { // kwarg_or_double_starred _loop0_133 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_134")); + D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_134_rule(p)) // _loop0_134 + (seq = _loop0_133_rule(p)) // _loop0_133 ) { - D(fprintf(stderr, "%*c+ _gather_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_134")); + D(fprintf(stderr, "%*c+ _gather_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_133[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_134")); + D(fprintf(stderr, "%*c%s _gather_132[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_133")); } _res = NULL; done: @@ -33656,9 +33581,9 @@ _gather_133_rule(Parser *p) return _res; } -// _loop0_135: (',' star_target) +// _loop0_134: (',' star_target) static asdl_seq * -_loop0_135_rule(Parser *p) +_loop0_134_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33683,13 +33608,13 @@ _loop0_135_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_267_var; + D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_258_var; while ( - (_tmp_267_var = _tmp_267_rule(p)) // ',' star_target + (_tmp_258_var = _tmp_258_rule(p)) // ',' star_target ) { - _res = _tmp_267_var; + _res = _tmp_258_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -33706,7 +33631,7 @@ _loop0_135_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33723,9 +33648,9 @@ _loop0_135_rule(Parser *p) return _seq; } -// _loop0_137: ',' star_target +// _loop0_136: ',' star_target static asdl_seq * -_loop0_137_rule(Parser *p) +_loop0_136_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33750,7 +33675,7 @@ _loop0_137_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _loop0_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty elem; while ( @@ -33782,7 +33707,7 @@ _loop0_137_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_137[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_136[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33799,9 +33724,9 @@ _loop0_137_rule(Parser *p) return _seq; } -// _gather_136: star_target _loop0_137 +// _gather_135: star_target _loop0_136 static asdl_seq * -_gather_136_rule(Parser *p) +_gather_135_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33812,27 +33737,27 @@ _gather_136_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_target _loop0_137 + { // star_target _loop0_136 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_137")); + D(fprintf(stderr, "%*c> _gather_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); expr_ty elem; asdl_seq * seq; if ( (elem = star_target_rule(p)) // star_target && - (seq = _loop0_137_rule(p)) // _loop0_137 + (seq = _loop0_136_rule(p)) // _loop0_136 ) { - D(fprintf(stderr, "%*c+ _gather_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_137")); + D(fprintf(stderr, "%*c+ _gather_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_136[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_137")); + D(fprintf(stderr, "%*c%s _gather_135[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_136")); } _res = NULL; done: @@ -33840,9 +33765,9 @@ _gather_136_rule(Parser *p) return _res; } -// _loop1_138: (',' star_target) +// _loop1_137: (',' star_target) static asdl_seq * -_loop1_138_rule(Parser *p) +_loop1_137_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33867,13 +33792,13 @@ _loop1_138_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_268_var; + D(fprintf(stderr, "%*c> _loop1_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_259_var; while ( - (_tmp_268_var = _tmp_268_rule(p)) // ',' star_target + (_tmp_259_var = _tmp_259_rule(p)) // ',' star_target ) { - _res = _tmp_268_var; + _res = _tmp_259_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -33890,7 +33815,7 @@ _loop1_138_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_138[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_137[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } if (_n == 0 || p->error_indicator) { @@ -33912,9 +33837,9 @@ _loop1_138_rule(Parser *p) return _seq; } -// _tmp_139: !'*' star_target +// _tmp_138: !'*' star_target static void * -_tmp_139_rule(Parser *p) +_tmp_138_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33930,7 +33855,7 @@ _tmp_139_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); expr_ty star_target_var; if ( _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' @@ -33938,12 +33863,12 @@ _tmp_139_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); _res = star_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); } _res = NULL; @@ -33952,9 +33877,9 @@ _tmp_139_rule(Parser *p) return _res; } -// _loop0_141: ',' del_target +// _loop0_140: ',' del_target static asdl_seq * -_loop0_141_rule(Parser *p) +_loop0_140_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33979,7 +33904,7 @@ _loop0_141_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); + D(fprintf(stderr, "%*c> _loop0_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); Token * _literal; expr_ty elem; while ( @@ -34011,7 +33936,7 @@ _loop0_141_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_141[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_140[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34028,9 +33953,9 @@ _loop0_141_rule(Parser *p) return _seq; } -// _gather_140: del_target _loop0_141 +// _gather_139: del_target _loop0_140 static asdl_seq * -_gather_140_rule(Parser *p) +_gather_139_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34041,27 +33966,27 @@ _gather_140_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // del_target _loop0_141 + { // del_target _loop0_140 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_141")); + D(fprintf(stderr, "%*c> _gather_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); expr_ty elem; asdl_seq * seq; if ( (elem = del_target_rule(p)) // del_target && - (seq = _loop0_141_rule(p)) // _loop0_141 + (seq = _loop0_140_rule(p)) // _loop0_140 ) { - D(fprintf(stderr, "%*c+ _gather_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_141")); + D(fprintf(stderr, "%*c+ _gather_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_140[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_141")); + D(fprintf(stderr, "%*c%s _gather_139[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_140")); } _res = NULL; done: @@ -34069,9 +33994,9 @@ _gather_140_rule(Parser *p) return _res; } -// _loop0_143: ',' expression +// _loop0_142: ',' expression static asdl_seq * -_loop0_143_rule(Parser *p) +_loop0_142_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34096,7 +34021,7 @@ _loop0_143_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34128,7 +34053,7 @@ _loop0_143_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_142[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34145,9 +34070,9 @@ _loop0_143_rule(Parser *p) return _seq; } -// _gather_142: expression _loop0_143 +// _gather_141: expression _loop0_142 static asdl_seq * -_gather_142_rule(Parser *p) +_gather_141_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34158,27 +34083,27 @@ _gather_142_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_143 + { // expression _loop0_142 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_143")); + D(fprintf(stderr, "%*c> _gather_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_143_rule(p)) // _loop0_143 + (seq = _loop0_142_rule(p)) // _loop0_142 ) { - D(fprintf(stderr, "%*c+ _gather_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_143")); + D(fprintf(stderr, "%*c+ _gather_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_142[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_143")); + D(fprintf(stderr, "%*c%s _gather_141[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_142")); } _res = NULL; done: @@ -34186,9 +34111,9 @@ _gather_142_rule(Parser *p) return _res; } -// _loop0_145: ',' expression +// _loop0_144: ',' expression static asdl_seq * -_loop0_145_rule(Parser *p) +_loop0_144_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34213,7 +34138,7 @@ _loop0_145_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34245,7 +34170,7 @@ _loop0_145_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34262,9 +34187,9 @@ _loop0_145_rule(Parser *p) return _seq; } -// _gather_144: expression _loop0_145 +// _gather_143: expression _loop0_144 static asdl_seq * -_gather_144_rule(Parser *p) +_gather_143_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34275,27 +34200,27 @@ _gather_144_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_145 + { // expression _loop0_144 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_145")); + D(fprintf(stderr, "%*c> _gather_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_145_rule(p)) // _loop0_145 + (seq = _loop0_144_rule(p)) // _loop0_144 ) { - D(fprintf(stderr, "%*c+ _gather_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_145")); + D(fprintf(stderr, "%*c+ _gather_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_144[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_145")); + D(fprintf(stderr, "%*c%s _gather_143[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_144")); } _res = NULL; done: @@ -34303,9 +34228,9 @@ _gather_144_rule(Parser *p) return _res; } -// _loop0_147: ',' expression +// _loop0_146: ',' expression static asdl_seq * -_loop0_147_rule(Parser *p) +_loop0_146_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34330,7 +34255,7 @@ _loop0_147_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34362,7 +34287,7 @@ _loop0_147_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34379,9 +34304,9 @@ _loop0_147_rule(Parser *p) return _seq; } -// _gather_146: expression _loop0_147 +// _gather_145: expression _loop0_146 static asdl_seq * -_gather_146_rule(Parser *p) +_gather_145_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34392,27 +34317,27 @@ _gather_146_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_147 + { // expression _loop0_146 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_147")); + D(fprintf(stderr, "%*c> _gather_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_147_rule(p)) // _loop0_147 + (seq = _loop0_146_rule(p)) // _loop0_146 ) { - D(fprintf(stderr, "%*c+ _gather_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_147")); + D(fprintf(stderr, "%*c+ _gather_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_146[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_147")); + D(fprintf(stderr, "%*c%s _gather_145[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_146")); } _res = NULL; done: @@ -34420,9 +34345,9 @@ _gather_146_rule(Parser *p) return _res; } -// _loop0_149: ',' expression +// _loop0_148: ',' expression static asdl_seq * -_loop0_149_rule(Parser *p) +_loop0_148_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34447,7 +34372,7 @@ _loop0_149_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -34479,7 +34404,7 @@ _loop0_149_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_149[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34496,9 +34421,9 @@ _loop0_149_rule(Parser *p) return _seq; } -// _gather_148: expression _loop0_149 +// _gather_147: expression _loop0_148 static asdl_seq * -_gather_148_rule(Parser *p) +_gather_147_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34509,27 +34434,27 @@ _gather_148_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_149 + { // expression _loop0_148 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_149")); + D(fprintf(stderr, "%*c> _gather_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_148")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_149_rule(p)) // _loop0_149 + (seq = _loop0_148_rule(p)) // _loop0_148 ) { - D(fprintf(stderr, "%*c+ _gather_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_149")); + D(fprintf(stderr, "%*c+ _gather_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_148")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_148[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_149")); + D(fprintf(stderr, "%*c%s _gather_147[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_148")); } _res = NULL; done: @@ -34537,9 +34462,9 @@ _gather_148_rule(Parser *p) return _res; } -// _tmp_150: NEWLINE INDENT +// _tmp_149: NEWLINE INDENT static void * -_tmp_150_rule(Parser *p) +_tmp_149_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34555,7 +34480,7 @@ _tmp_150_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); Token * indent_var; Token * newline_var; if ( @@ -34564,12 +34489,12 @@ _tmp_150_rule(Parser *p) (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' ) { - D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); _res = _PyPegen_dummy_name(p, newline_var, indent_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE INDENT")); } _res = NULL; @@ -34578,11 +34503,11 @@ _tmp_150_rule(Parser *p) return _res; } -// _tmp_151: +// _tmp_150: // | (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) // | kwargs static void * -_tmp_151_rule(Parser *p) +_tmp_150_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34598,18 +34523,18 @@ _tmp_151_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); - void *_tmp_269_var; + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); + void *_tmp_260_var; if ( - (_tmp_269_var = _tmp_269_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs + (_tmp_260_var = _tmp_260_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); - _res = _tmp_269_var; + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); + _res = _tmp_260_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); } { // kwargs @@ -34617,18 +34542,18 @@ _tmp_151_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); asdl_seq* kwargs_var; if ( (kwargs_var = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); _res = kwargs_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwargs")); } _res = NULL; @@ -34637,9 +34562,9 @@ _tmp_151_rule(Parser *p) return _res; } -// _loop0_153: ',' (starred_expression !'=') +// _loop0_152: ',' (starred_expression !'=') static asdl_seq * -_loop0_153_rule(Parser *p) +_loop0_152_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34664,13 +34589,13 @@ _loop0_153_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression !'=')")); + D(fprintf(stderr, "%*c> _loop0_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_270_rule(p)) // starred_expression !'=' + (elem = _tmp_261_rule(p)) // starred_expression !'=' ) { _res = elem; @@ -34696,7 +34621,7 @@ _loop0_153_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34713,9 +34638,9 @@ _loop0_153_rule(Parser *p) return _seq; } -// _gather_152: (starred_expression !'=') _loop0_153 +// _gather_151: (starred_expression !'=') _loop0_152 static asdl_seq * -_gather_152_rule(Parser *p) +_gather_151_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34726,27 +34651,27 @@ _gather_152_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression !'=') _loop0_153 + { // (starred_expression !'=') _loop0_152 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_153")); + D(fprintf(stderr, "%*c> _gather_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_152")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_270_rule(p)) // starred_expression !'=' + (elem = _tmp_261_rule(p)) // starred_expression !'=' && - (seq = _loop0_153_rule(p)) // _loop0_153 + (seq = _loop0_152_rule(p)) // _loop0_152 ) { - D(fprintf(stderr, "%*c+ _gather_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_153")); + D(fprintf(stderr, "%*c+ _gather_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_152")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_152[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression !'=') _loop0_153")); + D(fprintf(stderr, "%*c%s _gather_151[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression !'=') _loop0_152")); } _res = NULL; done: @@ -34754,9 +34679,9 @@ _gather_152_rule(Parser *p) return _res; } -// _tmp_154: args | expression for_if_clauses +// _tmp_153: args | expression for_if_clauses static void * -_tmp_154_rule(Parser *p) +_tmp_153_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34772,18 +34697,18 @@ _tmp_154_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); expr_ty args_var; if ( (args_var = args_rule(p)) // args ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); _res = args_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args")); } { // expression for_if_clauses @@ -34791,7 +34716,7 @@ _tmp_154_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); expr_ty expression_var; asdl_comprehension_seq* for_if_clauses_var; if ( @@ -34800,12 +34725,12 @@ _tmp_154_rule(Parser *p) (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses")); } _res = NULL; @@ -34814,9 +34739,9 @@ _tmp_154_rule(Parser *p) return _res; } -// _tmp_155: args ',' +// _tmp_154: args ',' static void * -_tmp_155_rule(Parser *p) +_tmp_154_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34832,7 +34757,7 @@ _tmp_155_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); Token * _literal; expr_ty args_var; if ( @@ -34841,12 +34766,12 @@ _tmp_155_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); _res = _PyPegen_dummy_name(p, args_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ','")); } _res = NULL; @@ -34855,9 +34780,9 @@ _tmp_155_rule(Parser *p) return _res; } -// _tmp_156: ',' | ')' +// _tmp_155: ',' | ')' static void * -_tmp_156_rule(Parser *p) +_tmp_155_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34873,18 +34798,18 @@ _tmp_156_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -34892,18 +34817,18 @@ _tmp_156_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } _res = NULL; @@ -34912,9 +34837,9 @@ _tmp_156_rule(Parser *p) return _res; } -// _tmp_157: 'True' | 'False' | 'None' +// _tmp_156: 'True' | 'False' | 'None' static void * -_tmp_157_rule(Parser *p) +_tmp_156_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34930,18 +34855,18 @@ _tmp_157_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 613)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'False' @@ -34949,18 +34874,18 @@ _tmp_157_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 615)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } { // 'None' @@ -34968,18 +34893,18 @@ _tmp_157_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 614)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } _res = NULL; @@ -34988,9 +34913,9 @@ _tmp_157_rule(Parser *p) return _res; } -// _tmp_158: NAME '=' +// _tmp_157: NAME '=' static void * -_tmp_158_rule(Parser *p) +_tmp_157_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35006,7 +34931,7 @@ _tmp_158_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); Token * _literal; expr_ty name_var; if ( @@ -35015,12 +34940,12 @@ _tmp_158_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); _res = _PyPegen_dummy_name(p, name_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); } _res = NULL; @@ -35029,9 +34954,9 @@ _tmp_158_rule(Parser *p) return _res; } -// _tmp_159: NAME STRING | SOFT_KEYWORD +// _tmp_158: NAME STRING | SOFT_KEYWORD static void * -_tmp_159_rule(Parser *p) +_tmp_158_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35047,7 +34972,7 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -35056,12 +34981,12 @@ _tmp_159_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); _res = _PyPegen_dummy_name(p, name_var, string_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } { // SOFT_KEYWORD @@ -35069,18 +34994,18 @@ _tmp_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); expr_ty soft_keyword_var; if ( (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); _res = soft_keyword_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; @@ -35089,9 +35014,9 @@ _tmp_159_rule(Parser *p) return _res; } -// _tmp_160: 'else' | ':' +// _tmp_159: 'else' | ':' static void * -_tmp_160_rule(Parser *p) +_tmp_159_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35107,18 +35032,18 @@ _tmp_160_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 665)) // token='else' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } { // ':' @@ -35126,18 +35051,18 @@ _tmp_160_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -35146,9 +35071,9 @@ _tmp_160_rule(Parser *p) return _res; } -// _tmp_161: '=' | ':=' +// _tmp_160: '=' | ':=' static void * -_tmp_161_rule(Parser *p) +_tmp_160_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35164,18 +35089,18 @@ _tmp_161_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -35183,18 +35108,18 @@ _tmp_161_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -35203,9 +35128,9 @@ _tmp_161_rule(Parser *p) return _res; } -// _tmp_162: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_161: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_162_rule(Parser *p) +_tmp_161_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35221,18 +35146,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); expr_ty list_var; if ( (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // tuple @@ -35240,18 +35165,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); expr_ty tuple_var; if ( (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // genexp @@ -35259,18 +35184,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); expr_ty genexp_var; if ( (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } { // 'True' @@ -35278,18 +35203,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 613)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'None' @@ -35297,18 +35222,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 614)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } { // 'False' @@ -35316,18 +35241,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 615)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; @@ -35336,9 +35261,9 @@ _tmp_162_rule(Parser *p) return _res; } -// _tmp_163: '=' | ':=' +// _tmp_162: '=' | ':=' static void * -_tmp_163_rule(Parser *p) +_tmp_162_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35354,18 +35279,18 @@ _tmp_163_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_163[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -35373,18 +35298,18 @@ _tmp_163_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_163[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -35393,9 +35318,9 @@ _tmp_163_rule(Parser *p) return _res; } -// _loop0_164: star_named_expressions +// _loop0_163: star_named_expressions static asdl_seq * -_loop0_164_rule(Parser *p) +_loop0_163_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35420,7 +35345,7 @@ _loop0_164_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); asdl_expr_seq* star_named_expressions_var; while ( (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions @@ -35443,7 +35368,7 @@ _loop0_164_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35460,6 +35385,73 @@ _loop0_164_rule(Parser *p) return _seq; } +// _loop0_164: (star_targets '=') +static asdl_seq * +_loop0_164_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // (star_targets '=') + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_262_var; + while ( + (_tmp_262_var = _tmp_262_rule(p)) // star_targets '=' + ) + { + _res = _tmp_262_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + // _loop0_165: (star_targets '=') static asdl_seq * _loop0_165_rule(Parser *p) @@ -35488,12 +35480,12 @@ _loop0_165_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_271_var; + void *_tmp_263_var; while ( - (_tmp_271_var = _tmp_271_rule(p)) // star_targets '=' + (_tmp_263_var = _tmp_263_rule(p)) // star_targets '=' ) { - _res = _tmp_271_var; + _res = _tmp_263_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -35527,133 +35519,9 @@ _loop0_165_rule(Parser *p) return _seq; } -// _loop0_166: (star_targets '=') -static asdl_seq * -_loop0_166_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (star_targets '=') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_272_var; - while ( - (_tmp_272_var = _tmp_272_rule(p)) // star_targets '=' - ) - { - _res = _tmp_272_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_166[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_167: yield_expr | star_expressions +// _tmp_166: '[' | '(' | '{' static void * -_tmp_167_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_168: '[' | '(' | '{' -static void * -_tmp_168_rule(Parser *p) +_tmp_166_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35669,18 +35537,18 @@ _tmp_168_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' @@ -35688,18 +35556,18 @@ _tmp_168_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' @@ -35707,18 +35575,18 @@ _tmp_168_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -35727,9 +35595,9 @@ _tmp_168_rule(Parser *p) return _res; } -// _tmp_169: '[' | '{' +// _tmp_167: '[' | '{' static void * -_tmp_169_rule(Parser *p) +_tmp_167_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35745,18 +35613,18 @@ _tmp_169_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -35764,18 +35632,18 @@ _tmp_169_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -35784,9 +35652,9 @@ _tmp_169_rule(Parser *p) return _res; } -// _tmp_170: '[' | '{' +// _tmp_168: '[' | '{' static void * -_tmp_170_rule(Parser *p) +_tmp_168_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35802,18 +35670,18 @@ _tmp_170_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -35821,18 +35689,18 @@ _tmp_170_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_170[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -35841,9 +35709,9 @@ _tmp_170_rule(Parser *p) return _res; } -// _tmp_171: slash_no_default | slash_with_default +// _tmp_169: slash_no_default | slash_with_default static void * -_tmp_171_rule(Parser *p) +_tmp_169_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35859,18 +35727,18 @@ _tmp_171_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); asdl_arg_seq* slash_no_default_var; if ( (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); _res = slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); } { // slash_with_default @@ -35878,18 +35746,18 @@ _tmp_171_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); SlashWithDefault* slash_with_default_var; if ( (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } _res = NULL; @@ -35898,9 +35766,9 @@ _tmp_171_rule(Parser *p) return _res; } -// _loop0_172: param_maybe_default +// _loop0_170: param_maybe_default static asdl_seq * -_loop0_172_rule(Parser *p) +_loop0_170_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35925,7 +35793,7 @@ _loop0_172_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -35948,7 +35816,7 @@ _loop0_172_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_172[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35965,9 +35833,9 @@ _loop0_172_rule(Parser *p) return _seq; } -// _loop0_173: param_no_default +// _loop0_171: param_no_default static asdl_seq * -_loop0_173_rule(Parser *p) +_loop0_171_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35992,7 +35860,7 @@ _loop0_173_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -36015,7 +35883,7 @@ _loop0_173_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36032,9 +35900,9 @@ _loop0_173_rule(Parser *p) return _seq; } -// _loop0_174: param_no_default +// _loop0_172: param_no_default static asdl_seq * -_loop0_174_rule(Parser *p) +_loop0_172_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36059,7 +35927,7 @@ _loop0_174_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -36082,7 +35950,7 @@ _loop0_174_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_174[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_172[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36099,9 +35967,9 @@ _loop0_174_rule(Parser *p) return _seq; } -// _loop1_175: param_no_default +// _loop1_173: param_no_default static asdl_seq * -_loop1_175_rule(Parser *p) +_loop1_173_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36126,7 +35994,7 @@ _loop1_175_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -36149,7 +36017,7 @@ _loop1_175_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -36171,9 +36039,9 @@ _loop1_175_rule(Parser *p) return _seq; } -// _tmp_176: slash_no_default | slash_with_default +// _tmp_174: slash_no_default | slash_with_default static void * -_tmp_176_rule(Parser *p) +_tmp_174_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36189,18 +36057,18 @@ _tmp_176_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); asdl_arg_seq* slash_no_default_var; if ( (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); _res = slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); } { // slash_with_default @@ -36208,18 +36076,18 @@ _tmp_176_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); SlashWithDefault* slash_with_default_var; if ( (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_174[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } _res = NULL; @@ -36228,9 +36096,9 @@ _tmp_176_rule(Parser *p) return _res; } -// _loop0_177: param_maybe_default +// _loop0_175: param_maybe_default static asdl_seq * -_loop0_177_rule(Parser *p) +_loop0_175_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36255,7 +36123,7 @@ _loop0_177_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36278,7 +36146,7 @@ _loop0_177_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_177[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36295,9 +36163,9 @@ _loop0_177_rule(Parser *p) return _seq; } -// _tmp_178: ',' | param_no_default +// _tmp_176: ',' | param_no_default static void * -_tmp_178_rule(Parser *p) +_tmp_176_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36313,18 +36181,18 @@ _tmp_178_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // param_no_default @@ -36332,18 +36200,18 @@ _tmp_178_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; if ( (param_no_default_var = param_no_default_rule(p)) // param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); _res = param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } _res = NULL; @@ -36352,9 +36220,9 @@ _tmp_178_rule(Parser *p) return _res; } -// _loop0_179: param_maybe_default +// _loop0_177: param_maybe_default static asdl_seq * -_loop0_179_rule(Parser *p) +_loop0_177_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36379,7 +36247,7 @@ _loop0_179_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36402,7 +36270,7 @@ _loop0_179_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36419,9 +36287,9 @@ _loop0_179_rule(Parser *p) return _seq; } -// _loop1_180: param_maybe_default +// _loop1_178: param_maybe_default static asdl_seq * -_loop1_180_rule(Parser *p) +_loop1_178_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36446,7 +36314,7 @@ _loop1_180_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36469,7 +36337,7 @@ _loop1_180_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_178[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -36491,9 +36359,9 @@ _loop1_180_rule(Parser *p) return _seq; } -// _tmp_181: ')' | ',' +// _tmp_179: ')' | ',' static void * -_tmp_181_rule(Parser *p) +_tmp_179_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36509,18 +36377,18 @@ _tmp_181_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' @@ -36528,18 +36396,18 @@ _tmp_181_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -36548,9 +36416,9 @@ _tmp_181_rule(Parser *p) return _res; } -// _tmp_182: ')' | ',' (')' | '**') +// _tmp_180: ')' | ',' (')' | '**') static void * -_tmp_182_rule(Parser *p) +_tmp_180_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36566,18 +36434,18 @@ _tmp_182_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -36585,21 +36453,21 @@ _tmp_182_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_273_var; + void *_tmp_264_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_273_var = _tmp_273_rule(p)) // ')' | '**' + (_tmp_264_var = _tmp_264_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_273_var); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_264_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -36608,9 +36476,9 @@ _tmp_182_rule(Parser *p) return _res; } -// _tmp_183: param_no_default | ',' +// _tmp_181: param_no_default | ',' static void * -_tmp_183_rule(Parser *p) +_tmp_181_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36626,18 +36494,18 @@ _tmp_183_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; if ( (param_no_default_var = param_no_default_rule(p)) // param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); _res = param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } { // ',' @@ -36645,18 +36513,18 @@ _tmp_183_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -36665,9 +36533,9 @@ _tmp_183_rule(Parser *p) return _res; } -// _loop0_184: param_maybe_default +// _loop0_182: param_maybe_default static asdl_seq * -_loop0_184_rule(Parser *p) +_loop0_182_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36692,7 +36560,7 @@ _loop0_184_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -36715,7 +36583,7 @@ _loop0_184_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36732,9 +36600,9 @@ _loop0_184_rule(Parser *p) return _seq; } -// _tmp_185: param_no_default | ',' +// _tmp_183: param_no_default | ',' static void * -_tmp_185_rule(Parser *p) +_tmp_183_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36750,18 +36618,18 @@ _tmp_185_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; if ( (param_no_default_var = param_no_default_rule(p)) // param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); _res = param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } { // ',' @@ -36769,18 +36637,18 @@ _tmp_185_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -36789,9 +36657,9 @@ _tmp_185_rule(Parser *p) return _res; } -// _tmp_186: '*' | '**' | '/' +// _tmp_184: '*' | '**' | '/' static void * -_tmp_186_rule(Parser *p) +_tmp_184_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36807,18 +36675,18 @@ _tmp_186_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } { // '**' @@ -36826,18 +36694,18 @@ _tmp_186_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } { // '/' @@ -36845,18 +36713,18 @@ _tmp_186_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_184[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } _res = NULL; @@ -36865,9 +36733,9 @@ _tmp_186_rule(Parser *p) return _res; } -// _loop1_187: param_with_default +// _loop1_185: param_with_default static asdl_seq * -_loop1_187_rule(Parser *p) +_loop1_185_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36892,7 +36760,7 @@ _loop1_187_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -36915,7 +36783,7 @@ _loop1_187_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_187[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -36937,9 +36805,9 @@ _loop1_187_rule(Parser *p) return _seq; } -// _tmp_188: lambda_slash_no_default | lambda_slash_with_default +// _tmp_186: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_188_rule(Parser *p) +_tmp_186_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -36955,18 +36823,18 @@ _tmp_188_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); asdl_arg_seq* lambda_slash_no_default_var; if ( (lambda_slash_no_default_var = lambda_slash_no_default_rule(p)) // lambda_slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); _res = lambda_slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); } { // lambda_slash_with_default @@ -36974,18 +36842,18 @@ _tmp_188_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); SlashWithDefault* lambda_slash_with_default_var; if ( (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_188[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_186[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); _res = lambda_slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; @@ -36994,9 +36862,9 @@ _tmp_188_rule(Parser *p) return _res; } -// _loop0_189: lambda_param_maybe_default +// _loop0_187: lambda_param_maybe_default static asdl_seq * -_loop0_189_rule(Parser *p) +_loop0_187_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37021,7 +36889,7 @@ _loop0_189_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37044,7 +36912,7 @@ _loop0_189_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37061,9 +36929,9 @@ _loop0_189_rule(Parser *p) return _seq; } -// _loop0_190: lambda_param_no_default +// _loop0_188: lambda_param_no_default static asdl_seq * -_loop0_190_rule(Parser *p) +_loop0_188_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37088,7 +36956,7 @@ _loop0_190_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -37111,7 +36979,7 @@ _loop0_190_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37128,9 +36996,9 @@ _loop0_190_rule(Parser *p) return _seq; } -// _loop0_191: lambda_param_no_default +// _loop0_189: lambda_param_no_default static asdl_seq * -_loop0_191_rule(Parser *p) +_loop0_189_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37155,7 +37023,7 @@ _loop0_191_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -37178,7 +37046,7 @@ _loop0_191_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_189[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37195,9 +37063,9 @@ _loop0_191_rule(Parser *p) return _seq; } -// _loop0_193: ',' lambda_param +// _loop0_191: ',' lambda_param static asdl_seq * -_loop0_193_rule(Parser *p) +_loop0_191_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37222,7 +37090,7 @@ _loop0_193_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); + D(fprintf(stderr, "%*c> _loop0_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); Token * _literal; arg_ty elem; while ( @@ -37254,7 +37122,7 @@ _loop0_193_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' lambda_param")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37271,9 +37139,9 @@ _loop0_193_rule(Parser *p) return _seq; } -// _gather_192: lambda_param _loop0_193 +// _gather_190: lambda_param _loop0_191 static asdl_seq * -_gather_192_rule(Parser *p) +_gather_190_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37284,27 +37152,27 @@ _gather_192_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // lambda_param _loop0_193 + { // lambda_param _loop0_191 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_193")); + D(fprintf(stderr, "%*c> _gather_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_191")); arg_ty elem; asdl_seq * seq; if ( (elem = lambda_param_rule(p)) // lambda_param && - (seq = _loop0_193_rule(p)) // _loop0_193 + (seq = _loop0_191_rule(p)) // _loop0_191 ) { - D(fprintf(stderr, "%*c+ _gather_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_193")); + D(fprintf(stderr, "%*c+ _gather_190[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_191")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_192[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_193")); + D(fprintf(stderr, "%*c%s _gather_190[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_191")); } _res = NULL; done: @@ -37312,9 +37180,9 @@ _gather_192_rule(Parser *p) return _res; } -// _tmp_194: lambda_slash_no_default | lambda_slash_with_default +// _tmp_192: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_194_rule(Parser *p) +_tmp_192_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37330,18 +37198,18 @@ _tmp_194_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); asdl_arg_seq* lambda_slash_no_default_var; if ( (lambda_slash_no_default_var = lambda_slash_no_default_rule(p)) // lambda_slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); _res = lambda_slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); } { // lambda_slash_with_default @@ -37349,18 +37217,18 @@ _tmp_194_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); SlashWithDefault* lambda_slash_with_default_var; if ( (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_192[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); _res = lambda_slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; @@ -37369,9 +37237,9 @@ _tmp_194_rule(Parser *p) return _res; } -// _loop0_195: lambda_param_maybe_default +// _loop0_193: lambda_param_maybe_default static asdl_seq * -_loop0_195_rule(Parser *p) +_loop0_193_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37396,7 +37264,7 @@ _loop0_195_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37419,7 +37287,7 @@ _loop0_195_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37436,9 +37304,9 @@ _loop0_195_rule(Parser *p) return _seq; } -// _tmp_196: ',' | lambda_param_no_default +// _tmp_194: ',' | lambda_param_no_default static void * -_tmp_196_rule(Parser *p) +_tmp_194_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37454,18 +37322,18 @@ _tmp_196_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // lambda_param_no_default @@ -37473,18 +37341,18 @@ _tmp_196_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; if ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_194[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } _res = NULL; @@ -37493,9 +37361,9 @@ _tmp_196_rule(Parser *p) return _res; } -// _loop0_197: lambda_param_maybe_default +// _loop0_195: lambda_param_maybe_default static asdl_seq * -_loop0_197_rule(Parser *p) +_loop0_195_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37520,7 +37388,7 @@ _loop0_197_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37543,7 +37411,7 @@ _loop0_197_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37560,9 +37428,9 @@ _loop0_197_rule(Parser *p) return _seq; } -// _loop1_198: lambda_param_maybe_default +// _loop1_196: lambda_param_maybe_default static asdl_seq * -_loop1_198_rule(Parser *p) +_loop1_196_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37587,7 +37455,7 @@ _loop1_198_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37610,7 +37478,7 @@ _loop1_198_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -37632,9 +37500,9 @@ _loop1_198_rule(Parser *p) return _seq; } -// _loop1_199: lambda_param_with_default +// _loop1_197: lambda_param_with_default static asdl_seq * -_loop1_199_rule(Parser *p) +_loop1_197_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37659,7 +37527,7 @@ _loop1_199_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -37682,7 +37550,7 @@ _loop1_199_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -37704,9 +37572,9 @@ _loop1_199_rule(Parser *p) return _seq; } -// _tmp_200: ':' | ',' (':' | '**') +// _tmp_198: ':' | ',' (':' | '**') static void * -_tmp_200_rule(Parser *p) +_tmp_198_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37722,18 +37590,18 @@ _tmp_200_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -37741,21 +37609,21 @@ _tmp_200_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_274_var; + void *_tmp_265_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_274_var = _tmp_274_rule(p)) // ':' | '**' + (_tmp_265_var = _tmp_265_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_274_var); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_265_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -37764,9 +37632,9 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: lambda_param_no_default | ',' +// _tmp_199: lambda_param_no_default | ',' static void * -_tmp_201_rule(Parser *p) +_tmp_199_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37782,18 +37650,18 @@ _tmp_201_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; if ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } { // ',' @@ -37801,18 +37669,18 @@ _tmp_201_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -37821,9 +37689,9 @@ _tmp_201_rule(Parser *p) return _res; } -// _loop0_202: lambda_param_maybe_default +// _loop0_200: lambda_param_maybe_default static asdl_seq * -_loop0_202_rule(Parser *p) +_loop0_200_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37848,7 +37716,7 @@ _loop0_202_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37871,7 +37739,7 @@ _loop0_202_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37888,9 +37756,9 @@ _loop0_202_rule(Parser *p) return _seq; } -// _tmp_203: lambda_param_no_default | ',' +// _tmp_201: lambda_param_no_default | ',' static void * -_tmp_203_rule(Parser *p) +_tmp_201_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37906,18 +37774,18 @@ _tmp_203_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; if ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } { // ',' @@ -37925,18 +37793,18 @@ _tmp_203_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -37945,9 +37813,9 @@ _tmp_203_rule(Parser *p) return _res; } -// _tmp_204: '*' | '**' | '/' +// _tmp_202: '*' | '**' | '/' static void * -_tmp_204_rule(Parser *p) +_tmp_202_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -37963,18 +37831,18 @@ _tmp_204_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } { // '**' @@ -37982,18 +37850,18 @@ _tmp_204_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } { // '/' @@ -38001,18 +37869,18 @@ _tmp_204_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } _res = NULL; @@ -38021,9 +37889,9 @@ _tmp_204_rule(Parser *p) return _res; } -// _tmp_205: ',' | ')' | ':' +// _tmp_203: ',' | ')' | ':' static void * -_tmp_205_rule(Parser *p) +_tmp_203_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38039,18 +37907,18 @@ _tmp_205_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -38058,18 +37926,18 @@ _tmp_205_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -38077,18 +37945,18 @@ _tmp_205_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_205[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -38097,9 +37965,9 @@ _tmp_205_rule(Parser *p) return _res; } -// _loop0_207: ',' dotted_name +// _loop0_205: ',' dotted_name static asdl_seq * -_loop0_207_rule(Parser *p) +_loop0_205_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38124,7 +37992,7 @@ _loop0_207_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name")); + D(fprintf(stderr, "%*c> _loop0_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name")); Token * _literal; expr_ty elem; while ( @@ -38156,7 +38024,7 @@ _loop0_207_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_207[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_205[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' dotted_name")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38173,9 +38041,9 @@ _loop0_207_rule(Parser *p) return _seq; } -// _gather_206: dotted_name _loop0_207 +// _gather_204: dotted_name _loop0_205 static asdl_seq * -_gather_206_rule(Parser *p) +_gather_204_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38186,27 +38054,27 @@ _gather_206_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // dotted_name _loop0_207 + { // dotted_name _loop0_205 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_207")); + D(fprintf(stderr, "%*c> _gather_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_205")); expr_ty elem; asdl_seq * seq; if ( (elem = dotted_name_rule(p)) // dotted_name && - (seq = _loop0_207_rule(p)) // _loop0_207 + (seq = _loop0_205_rule(p)) // _loop0_205 ) { - D(fprintf(stderr, "%*c+ _gather_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_207")); + D(fprintf(stderr, "%*c+ _gather_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_205")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_206[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_207")); + D(fprintf(stderr, "%*c%s _gather_204[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_205")); } _res = NULL; done: @@ -38214,9 +38082,9 @@ _gather_206_rule(Parser *p) return _res; } -// _loop0_209: ',' (expression ['as' star_target]) +// _loop0_207: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_209_rule(Parser *p) +_loop0_207_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38241,13 +38109,13 @@ _loop0_209_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_275_rule(p)) // expression ['as' star_target] + (elem = _tmp_266_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -38273,7 +38141,7 @@ _loop0_209_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_209[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_207[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38290,9 +38158,9 @@ _loop0_209_rule(Parser *p) return _seq; } -// _gather_208: (expression ['as' star_target]) _loop0_209 +// _gather_206: (expression ['as' star_target]) _loop0_207 static asdl_seq * -_gather_208_rule(Parser *p) +_gather_206_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38303,27 +38171,27 @@ _gather_208_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_209 + { // (expression ['as' star_target]) _loop0_207 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_209")); + D(fprintf(stderr, "%*c> _gather_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_275_rule(p)) // expression ['as' star_target] + (elem = _tmp_266_rule(p)) // expression ['as' star_target] && - (seq = _loop0_209_rule(p)) // _loop0_209 + (seq = _loop0_207_rule(p)) // _loop0_207 ) { - D(fprintf(stderr, "%*c+ _gather_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_209")); + D(fprintf(stderr, "%*c+ _gather_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_208[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_209")); + D(fprintf(stderr, "%*c%s _gather_206[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); } _res = NULL; done: @@ -38331,9 +38199,9 @@ _gather_208_rule(Parser *p) return _res; } -// _loop0_211: ',' (expressions ['as' star_target]) +// _loop0_209: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_211_rule(Parser *p) +_loop0_209_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38358,13 +38226,13 @@ _loop0_211_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_276_rule(p)) // expressions ['as' star_target] + (elem = _tmp_267_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -38390,7 +38258,7 @@ _loop0_211_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_211[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_209[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38407,9 +38275,9 @@ _loop0_211_rule(Parser *p) return _seq; } -// _gather_210: (expressions ['as' star_target]) _loop0_211 +// _gather_208: (expressions ['as' star_target]) _loop0_209 static asdl_seq * -_gather_210_rule(Parser *p) +_gather_208_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38420,27 +38288,27 @@ _gather_210_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_211 + { // (expressions ['as' star_target]) _loop0_209 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_211")); + D(fprintf(stderr, "%*c> _gather_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_276_rule(p)) // expressions ['as' star_target] + (elem = _tmp_267_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_211_rule(p)) // _loop0_211 + (seq = _loop0_209_rule(p)) // _loop0_209 ) { - D(fprintf(stderr, "%*c+ _gather_210[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_211")); + D(fprintf(stderr, "%*c+ _gather_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_210[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_211")); + D(fprintf(stderr, "%*c%s _gather_208[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); } _res = NULL; done: @@ -38448,9 +38316,9 @@ _gather_210_rule(Parser *p) return _res; } -// _loop0_213: ',' (expression ['as' star_target]) +// _loop0_211: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_213_rule(Parser *p) +_loop0_211_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38475,13 +38343,13 @@ _loop0_213_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_277_rule(p)) // expression ['as' star_target] + (elem = _tmp_268_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -38507,7 +38375,7 @@ _loop0_213_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_213[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_211[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38524,9 +38392,9 @@ _loop0_213_rule(Parser *p) return _seq; } -// _gather_212: (expression ['as' star_target]) _loop0_213 +// _gather_210: (expression ['as' star_target]) _loop0_211 static asdl_seq * -_gather_212_rule(Parser *p) +_gather_210_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38537,27 +38405,27 @@ _gather_212_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_213 + { // (expression ['as' star_target]) _loop0_211 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_213")); + D(fprintf(stderr, "%*c> _gather_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_277_rule(p)) // expression ['as' star_target] + (elem = _tmp_268_rule(p)) // expression ['as' star_target] && - (seq = _loop0_213_rule(p)) // _loop0_213 + (seq = _loop0_211_rule(p)) // _loop0_211 ) { - D(fprintf(stderr, "%*c+ _gather_212[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_213")); + D(fprintf(stderr, "%*c+ _gather_210[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_212[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_213")); + D(fprintf(stderr, "%*c%s _gather_210[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); } _res = NULL; done: @@ -38565,9 +38433,9 @@ _gather_212_rule(Parser *p) return _res; } -// _loop0_215: ',' (expressions ['as' star_target]) +// _loop0_213: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_215_rule(Parser *p) +_loop0_213_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38592,13 +38460,13 @@ _loop0_215_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_278_rule(p)) // expressions ['as' star_target] + (elem = _tmp_269_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -38624,7 +38492,7 @@ _loop0_215_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_215[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_213[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38641,9 +38509,9 @@ _loop0_215_rule(Parser *p) return _seq; } -// _gather_214: (expressions ['as' star_target]) _loop0_215 +// _gather_212: (expressions ['as' star_target]) _loop0_213 static asdl_seq * -_gather_214_rule(Parser *p) +_gather_212_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38654,27 +38522,27 @@ _gather_214_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_215 + { // (expressions ['as' star_target]) _loop0_213 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_215")); + D(fprintf(stderr, "%*c> _gather_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_278_rule(p)) // expressions ['as' star_target] + (elem = _tmp_269_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_215_rule(p)) // _loop0_215 + (seq = _loop0_213_rule(p)) // _loop0_213 ) { - D(fprintf(stderr, "%*c+ _gather_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_215")); + D(fprintf(stderr, "%*c+ _gather_212[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_214[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_215")); + D(fprintf(stderr, "%*c%s _gather_212[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); } _res = NULL; done: @@ -38682,9 +38550,9 @@ _gather_214_rule(Parser *p) return _res; } -// _tmp_216: 'except' | 'finally' +// _tmp_214: 'except' | 'finally' static void * -_tmp_216_rule(Parser *p) +_tmp_214_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38700,18 +38568,18 @@ _tmp_216_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 657)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_216[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -38719,18 +38587,18 @@ _tmp_216_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 653)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_216[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -38739,9 +38607,9 @@ _tmp_216_rule(Parser *p) return _res; } -// _loop0_217: block +// _loop0_215: block static asdl_seq * -_loop0_217_rule(Parser *p) +_loop0_215_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38766,7 +38634,7 @@ _loop0_217_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + D(fprintf(stderr, "%*c> _loop0_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); asdl_stmt_seq* block_var; while ( (block_var = block_rule(p)) // block @@ -38789,7 +38657,7 @@ _loop0_217_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_217[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_215[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38806,9 +38674,9 @@ _loop0_217_rule(Parser *p) return _seq; } -// _loop1_218: except_block +// _loop1_216: except_block static asdl_seq * -_loop1_218_rule(Parser *p) +_loop1_216_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38833,7 +38701,7 @@ _loop1_218_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); + D(fprintf(stderr, "%*c> _loop1_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); excepthandler_ty except_block_var; while ( (except_block_var = except_block_rule(p)) // except_block @@ -38856,7 +38724,7 @@ _loop1_218_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_218[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_216[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); } if (_n == 0 || p->error_indicator) { @@ -38878,9 +38746,9 @@ _loop1_218_rule(Parser *p) return _seq; } -// _tmp_219: 'as' NAME +// _tmp_217: 'as' NAME static void * -_tmp_219_rule(Parser *p) +_tmp_217_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38896,7 +38764,7 @@ _tmp_219_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -38905,12 +38773,12 @@ _tmp_219_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_219[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_217[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_219[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_217[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -38919,9 +38787,9 @@ _tmp_219_rule(Parser *p) return _res; } -// _loop0_220: block +// _loop0_218: block static asdl_seq * -_loop0_220_rule(Parser *p) +_loop0_218_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38946,7 +38814,7 @@ _loop0_220_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + D(fprintf(stderr, "%*c> _loop0_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); asdl_stmt_seq* block_var; while ( (block_var = block_rule(p)) // block @@ -38969,7 +38837,7 @@ _loop0_220_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_220[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_218[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38986,9 +38854,9 @@ _loop0_220_rule(Parser *p) return _seq; } -// _loop1_221: except_star_block +// _loop1_219: except_star_block static asdl_seq * -_loop1_221_rule(Parser *p) +_loop1_219_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39013,7 +38881,7 @@ _loop1_221_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); + D(fprintf(stderr, "%*c> _loop1_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); excepthandler_ty except_star_block_var; while ( (except_star_block_var = except_star_block_rule(p)) // except_star_block @@ -39036,7 +38904,7 @@ _loop1_221_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_221[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_219[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); } if (_n == 0 || p->error_indicator) { @@ -39058,9 +38926,9 @@ _loop1_221_rule(Parser *p) return _seq; } -// _tmp_222: expression ['as' NAME] +// _tmp_220: expression ['as' NAME] static void * -_tmp_222_rule(Parser *p) +_tmp_220_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39076,22 +38944,22 @@ _tmp_222_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_279_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_270_rule(p), !p->error_indicator) // ['as' NAME] ) { - D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' NAME]")); } _res = NULL; @@ -39100,9 +38968,9 @@ _tmp_222_rule(Parser *p) return _res; } -// _tmp_223: 'as' NAME +// _tmp_221: 'as' NAME static void * -_tmp_223_rule(Parser *p) +_tmp_221_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39118,7 +38986,7 @@ _tmp_223_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -39127,12 +38995,12 @@ _tmp_223_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_221[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39141,9 +39009,9 @@ _tmp_223_rule(Parser *p) return _res; } -// _tmp_224: 'as' NAME +// _tmp_222: 'as' NAME static void * -_tmp_224_rule(Parser *p) +_tmp_222_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39159,7 +39027,7 @@ _tmp_224_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -39168,12 +39036,12 @@ _tmp_224_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39182,9 +39050,9 @@ _tmp_224_rule(Parser *p) return _res; } -// _tmp_225: NEWLINE | ':' +// _tmp_223: NEWLINE | ':' static void * -_tmp_225_rule(Parser *p) +_tmp_223_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39200,18 +39068,18 @@ _tmp_225_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token * newline_var; if ( (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); _res = newline_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); } { // ':' @@ -39219,18 +39087,18 @@ _tmp_225_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -39239,9 +39107,9 @@ _tmp_225_rule(Parser *p) return _res; } -// _tmp_226: 'as' NAME +// _tmp_224: 'as' NAME static void * -_tmp_226_rule(Parser *p) +_tmp_224_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39257,7 +39125,7 @@ _tmp_226_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -39266,12 +39134,12 @@ _tmp_226_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39280,9 +39148,9 @@ _tmp_226_rule(Parser *p) return _res; } -// _tmp_227: 'as' NAME +// _tmp_225: 'as' NAME static void * -_tmp_227_rule(Parser *p) +_tmp_225_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39298,7 +39166,7 @@ _tmp_227_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -39307,12 +39175,12 @@ _tmp_227_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -39321,9 +39189,9 @@ _tmp_227_rule(Parser *p) return _res; } -// _tmp_228: positional_patterns ',' +// _tmp_226: positional_patterns ',' static void * -_tmp_228_rule(Parser *p) +_tmp_226_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39339,7 +39207,7 @@ _tmp_228_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; asdl_pattern_seq* positional_patterns_var; if ( @@ -39348,12 +39216,12 @@ _tmp_228_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; @@ -39362,9 +39230,9 @@ _tmp_228_rule(Parser *p) return _res; } -// _tmp_229: '->' expression +// _tmp_227: '->' expression static void * -_tmp_229_rule(Parser *p) +_tmp_227_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39380,7 +39248,7 @@ _tmp_229_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty expression_var; if ( @@ -39389,12 +39257,12 @@ _tmp_229_rule(Parser *p) (expression_var = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = _PyPegen_dummy_name(p, _literal, expression_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -39403,9 +39271,9 @@ _tmp_229_rule(Parser *p) return _res; } -// _tmp_230: '(' arguments? ')' +// _tmp_228: '(' arguments? ')' static void * -_tmp_230_rule(Parser *p) +_tmp_228_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39421,7 +39289,7 @@ _tmp_230_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -39434,12 +39302,12 @@ _tmp_230_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -39448,9 +39316,9 @@ _tmp_230_rule(Parser *p) return _res; } -// _tmp_231: '(' arguments? ')' +// _tmp_229: '(' arguments? ')' static void * -_tmp_231_rule(Parser *p) +_tmp_229_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39466,7 +39334,7 @@ _tmp_231_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -39479,12 +39347,12 @@ _tmp_231_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -39493,9 +39361,9 @@ _tmp_231_rule(Parser *p) return _res; } -// _loop0_233: ',' double_starred_kvpair +// _loop0_231: ',' double_starred_kvpair static asdl_seq * -_loop0_233_rule(Parser *p) +_loop0_231_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39520,7 +39388,7 @@ _loop0_233_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -39552,7 +39420,7 @@ _loop0_233_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_233[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_231[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -39569,9 +39437,9 @@ _loop0_233_rule(Parser *p) return _seq; } -// _gather_232: double_starred_kvpair _loop0_233 +// _gather_230: double_starred_kvpair _loop0_231 static asdl_seq * -_gather_232_rule(Parser *p) +_gather_230_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39582,27 +39450,27 @@ _gather_232_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_233 + { // double_starred_kvpair _loop0_231 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_233")); + D(fprintf(stderr, "%*c> _gather_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_231")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_233_rule(p)) // _loop0_233 + (seq = _loop0_231_rule(p)) // _loop0_231 ) { - D(fprintf(stderr, "%*c+ _gather_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_233")); + D(fprintf(stderr, "%*c+ _gather_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_231")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_232[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_233")); + D(fprintf(stderr, "%*c%s _gather_230[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_231")); } _res = NULL; done: @@ -39610,9 +39478,9 @@ _gather_232_rule(Parser *p) return _res; } -// _tmp_234: '}' | ',' +// _tmp_232: '}' | ',' static void * -_tmp_234_rule(Parser *p) +_tmp_232_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39628,18 +39496,18 @@ _tmp_234_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -39647,18 +39515,18 @@ _tmp_234_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -39667,9 +39535,9 @@ _tmp_234_rule(Parser *p) return _res; } -// _tmp_235: '}' | ',' +// _tmp_233: '}' | ',' static void * -_tmp_235_rule(Parser *p) +_tmp_233_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39685,18 +39553,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -39704,18 +39572,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -39724,123 +39592,9 @@ _tmp_235_rule(Parser *p) return _res; } -// _tmp_236: yield_expr | star_expressions -static void * -_tmp_236_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_237: yield_expr | star_expressions -static void * -_tmp_237_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_238: '=' | '!' | ':' | '}' +// _tmp_234: '=' | '!' | ':' | '}' static void * -_tmp_238_rule(Parser *p) +_tmp_234_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39856,18 +39610,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // '!' @@ -39875,18 +39629,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -39894,18 +39648,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -39913,18 +39667,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -39933,66 +39687,9 @@ _tmp_238_rule(Parser *p) return _res; } -// _tmp_239: yield_expr | star_expressions +// _tmp_235: '!' | ':' | '}' static void * -_tmp_239_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_240: '!' | ':' | '}' -static void * -_tmp_240_rule(Parser *p) +_tmp_235_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40008,18 +39705,18 @@ _tmp_240_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -40027,18 +39724,18 @@ _tmp_240_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -40046,18 +39743,18 @@ _tmp_240_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -40066,123 +39763,9 @@ _tmp_240_rule(Parser *p) return _res; } -// _tmp_241: yield_expr | star_expressions +// _tmp_236: '!' NAME static void * -_tmp_241_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_242: yield_expr | star_expressions -static void * -_tmp_242_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_243: '!' NAME -static void * -_tmp_243_rule(Parser *p) +_tmp_236_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40198,7 +39781,7 @@ _tmp_243_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -40207,12 +39790,12 @@ _tmp_243_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -40221,9 +39804,9 @@ _tmp_243_rule(Parser *p) return _res; } -// _tmp_244: ':' | '}' +// _tmp_237: ':' | '}' static void * -_tmp_244_rule(Parser *p) +_tmp_237_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40239,18 +39822,18 @@ _tmp_244_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -40258,18 +39841,18 @@ _tmp_244_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -40278,66 +39861,9 @@ _tmp_244_rule(Parser *p) return _res; } -// _tmp_245: yield_expr | star_expressions -static void * -_tmp_245_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_246: '!' NAME +// _tmp_238: '!' NAME static void * -_tmp_246_rule(Parser *p) +_tmp_238_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40353,7 +39879,7 @@ _tmp_246_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -40362,12 +39888,12 @@ _tmp_246_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -40376,9 +39902,9 @@ _tmp_246_rule(Parser *p) return _res; } -// _loop0_247: fstring_format_spec +// _loop0_239: fstring_format_spec static asdl_seq * -_loop0_247_rule(Parser *p) +_loop0_239_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40403,7 +39929,7 @@ _loop0_247_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); + D(fprintf(stderr, "%*c> _loop0_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); expr_ty fstring_format_spec_var; while ( (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec @@ -40426,7 +39952,7 @@ _loop0_247_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_247[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_239[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -40443,66 +39969,9 @@ _loop0_247_rule(Parser *p) return _seq; } -// _tmp_248: yield_expr | star_expressions -static void * -_tmp_248_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_249: '!' NAME +// _tmp_240: '!' NAME static void * -_tmp_249_rule(Parser *p) +_tmp_240_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40518,7 +39987,7 @@ _tmp_249_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -40527,12 +39996,12 @@ _tmp_249_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -40541,9 +40010,9 @@ _tmp_249_rule(Parser *p) return _res; } -// _tmp_250: ':' | '}' +// _tmp_241: ':' | '}' static void * -_tmp_250_rule(Parser *p) +_tmp_241_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40559,18 +40028,18 @@ _tmp_250_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -40578,18 +40047,18 @@ _tmp_250_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -40598,9 +40067,9 @@ _tmp_250_rule(Parser *p) return _res; } -// _tmp_251: '+' | '-' | '*' | '/' | '%' | '//' | '@' +// _tmp_242: '+' | '-' | '*' | '/' | '%' | '//' | '@' static void * -_tmp_251_rule(Parser *p) +_tmp_242_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40616,18 +40085,18 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } { // '-' @@ -40635,18 +40104,18 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } { // '*' @@ -40654,18 +40123,18 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } { // '/' @@ -40673,18 +40142,18 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } { // '%' @@ -40692,18 +40161,18 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 24)) // token='%' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'%'")); } { // '//' @@ -40711,18 +40180,18 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 47)) // token='//' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'//'")); } { // '@' @@ -40730,18 +40199,18 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 49)) // token='@' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@'")); } _res = NULL; @@ -40750,9 +40219,9 @@ _tmp_251_rule(Parser *p) return _res; } -// _tmp_252: '+' | '-' | '~' +// _tmp_243: '+' | '-' | '~' static void * -_tmp_252_rule(Parser *p) +_tmp_243_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40768,18 +40237,18 @@ _tmp_252_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } { // '-' @@ -40787,18 +40256,18 @@ _tmp_252_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } { // '~' @@ -40806,18 +40275,18 @@ _tmp_252_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~'")); + D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 31)) // token='~' ) { - D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~'")); + D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'~'")); } _res = NULL; @@ -40826,9 +40295,9 @@ _tmp_252_rule(Parser *p) return _res; } -// _tmp_253: star_targets '=' +// _tmp_244: star_targets '=' static void * -_tmp_253_rule(Parser *p) +_tmp_244_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40844,7 +40313,7 @@ _tmp_253_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -40853,7 +40322,7 @@ _tmp_253_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40863,7 +40332,7 @@ _tmp_253_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -40872,9 +40341,9 @@ _tmp_253_rule(Parser *p) return _res; } -// _tmp_254: '.' | '...' +// _tmp_245: '.' | '...' static void * -_tmp_254_rule(Parser *p) +_tmp_245_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40890,18 +40359,18 @@ _tmp_254_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -40909,18 +40378,18 @@ _tmp_254_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -40929,9 +40398,9 @@ _tmp_254_rule(Parser *p) return _res; } -// _tmp_255: '.' | '...' +// _tmp_246: '.' | '...' static void * -_tmp_255_rule(Parser *p) +_tmp_246_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40947,18 +40416,18 @@ _tmp_255_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -40966,18 +40435,18 @@ _tmp_255_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -40986,9 +40455,9 @@ _tmp_255_rule(Parser *p) return _res; } -// _tmp_256: '@' named_expression NEWLINE +// _tmp_247: '@' named_expression NEWLINE static void * -_tmp_256_rule(Parser *p) +_tmp_247_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41004,7 +40473,7 @@ _tmp_256_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -41016,7 +40485,7 @@ _tmp_256_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41026,7 +40495,7 @@ _tmp_256_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -41035,9 +40504,9 @@ _tmp_256_rule(Parser *p) return _res; } -// _tmp_257: ',' expression +// _tmp_248: ',' expression static void * -_tmp_257_rule(Parser *p) +_tmp_248_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41053,7 +40522,7 @@ _tmp_257_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -41062,7 +40531,7 @@ _tmp_257_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41072,7 +40541,7 @@ _tmp_257_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -41081,9 +40550,9 @@ _tmp_257_rule(Parser *p) return _res; } -// _tmp_258: ',' star_expression +// _tmp_249: ',' star_expression static void * -_tmp_258_rule(Parser *p) +_tmp_249_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41099,7 +40568,7 @@ _tmp_258_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -41108,7 +40577,7 @@ _tmp_258_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41118,7 +40587,7 @@ _tmp_258_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -41127,9 +40596,9 @@ _tmp_258_rule(Parser *p) return _res; } -// _tmp_259: 'or' conjunction +// _tmp_250: 'or' conjunction static void * -_tmp_259_rule(Parser *p) +_tmp_250_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41145,7 +40614,7 @@ _tmp_259_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -41154,7 +40623,7 @@ _tmp_259_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41164,7 +40633,7 @@ _tmp_259_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -41173,9 +40642,9 @@ _tmp_259_rule(Parser *p) return _res; } -// _tmp_260: 'and' inversion +// _tmp_251: 'and' inversion static void * -_tmp_260_rule(Parser *p) +_tmp_251_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41191,7 +40660,7 @@ _tmp_260_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -41200,7 +40669,7 @@ _tmp_260_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41210,7 +40679,7 @@ _tmp_260_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -41219,9 +40688,9 @@ _tmp_260_rule(Parser *p) return _res; } -// _tmp_261: slice | starred_expression +// _tmp_252: slice | starred_expression static void * -_tmp_261_rule(Parser *p) +_tmp_252_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41237,18 +40706,18 @@ _tmp_261_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice")); expr_ty slice_var; if ( (slice_var = slice_rule(p)) // slice ) { - D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); _res = slice_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice")); } { // starred_expression @@ -41256,18 +40725,18 @@ _tmp_261_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } _res = NULL; @@ -41276,9 +40745,9 @@ _tmp_261_rule(Parser *p) return _res; } -// _tmp_262: fstring | string +// _tmp_253: fstring | string static void * -_tmp_262_rule(Parser *p) +_tmp_253_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41294,18 +40763,18 @@ _tmp_262_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring")); expr_ty fstring_var; if ( (fstring_var = fstring_rule(p)) // fstring ) { - D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); _res = fstring_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring")); } { // string @@ -41313,18 +40782,18 @@ _tmp_262_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string")); + D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string")); expr_ty string_var; if ( (string_var = string_rule(p)) // string ) { - D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); + D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); _res = string_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "string")); } _res = NULL; @@ -41333,9 +40802,9 @@ _tmp_262_rule(Parser *p) return _res; } -// _tmp_263: 'if' disjunction +// _tmp_254: 'if' disjunction static void * -_tmp_263_rule(Parser *p) +_tmp_254_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41351,7 +40820,7 @@ _tmp_263_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -41360,7 +40829,7 @@ _tmp_263_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41370,7 +40839,7 @@ _tmp_263_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -41379,9 +40848,9 @@ _tmp_263_rule(Parser *p) return _res; } -// _tmp_264: 'if' disjunction +// _tmp_255: 'if' disjunction static void * -_tmp_264_rule(Parser *p) +_tmp_255_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41397,7 +40866,7 @@ _tmp_264_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -41406,7 +40875,7 @@ _tmp_264_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41416,7 +40885,7 @@ _tmp_264_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -41425,9 +40894,9 @@ _tmp_264_rule(Parser *p) return _res; } -// _loop0_265: (',' bitwise_or) +// _loop0_256: (',' bitwise_or) static asdl_seq * -_loop0_265_rule(Parser *p) +_loop0_256_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41452,13 +40921,13 @@ _loop0_265_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' bitwise_or)")); - void *_tmp_280_var; + D(fprintf(stderr, "%*c> _loop0_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' bitwise_or)")); + void *_tmp_271_var; while ( - (_tmp_280_var = _tmp_280_rule(p)) // ',' bitwise_or + (_tmp_271_var = _tmp_271_rule(p)) // ',' bitwise_or ) { - _res = _tmp_280_var; + _res = _tmp_271_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -41475,7 +40944,7 @@ _loop0_265_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_265[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_256[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' bitwise_or)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -41492,9 +40961,9 @@ _loop0_265_rule(Parser *p) return _seq; } -// _tmp_266: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_257: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_266_rule(Parser *p) +_tmp_257_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41510,18 +40979,18 @@ _tmp_266_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -41529,20 +40998,20 @@ _tmp_266_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_281_var; + D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_272_var; if ( - (_tmp_281_var = _tmp_281_rule(p)) // assignment_expression | expression !':=' + (_tmp_272_var = _tmp_272_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_281_var; + D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_272_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -41551,9 +41020,9 @@ _tmp_266_rule(Parser *p) return _res; } -// _tmp_267: ',' star_target +// _tmp_258: ',' star_target static void * -_tmp_267_rule(Parser *p) +_tmp_258_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41569,7 +41038,7 @@ _tmp_267_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -41578,7 +41047,7 @@ _tmp_267_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41588,7 +41057,7 @@ _tmp_267_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -41597,9 +41066,9 @@ _tmp_267_rule(Parser *p) return _res; } -// _tmp_268: ',' star_target +// _tmp_259: ',' star_target static void * -_tmp_268_rule(Parser *p) +_tmp_259_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41615,7 +41084,7 @@ _tmp_268_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -41624,7 +41093,7 @@ _tmp_268_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -41634,7 +41103,7 @@ _tmp_268_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -41643,10 +41112,10 @@ _tmp_268_rule(Parser *p) return _res; } -// _tmp_269: +// _tmp_260: // | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs static void * -_tmp_269_rule(Parser *p) +_tmp_260_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41662,24 +41131,24 @@ _tmp_269_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); - asdl_seq * _gather_282_var; + D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + asdl_seq * _gather_273_var; Token * _literal; asdl_seq* kwargs_var; if ( - (_gather_282_var = _gather_282_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + (_gather_273_var = _gather_273_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && (kwargs_var = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); - _res = _PyPegen_dummy_name(p, _gather_282_var, _literal, kwargs_var); + D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + _res = _PyPegen_dummy_name(p, _gather_273_var, _literal, kwargs_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); } _res = NULL; @@ -41688,9 +41157,9 @@ _tmp_269_rule(Parser *p) return _res; } -// _tmp_270: starred_expression !'=' +// _tmp_261: starred_expression !'=' static void * -_tmp_270_rule(Parser *p) +_tmp_261_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41706,7 +41175,7 @@ _tmp_270_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); + D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression @@ -41714,12 +41183,12 @@ _tmp_270_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); + D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression !'='")); } _res = NULL; @@ -41728,9 +41197,9 @@ _tmp_270_rule(Parser *p) return _res; } -// _tmp_271: star_targets '=' +// _tmp_262: star_targets '=' static void * -_tmp_271_rule(Parser *p) +_tmp_262_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41746,7 +41215,7 @@ _tmp_271_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -41755,12 +41224,12 @@ _tmp_271_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -41769,9 +41238,9 @@ _tmp_271_rule(Parser *p) return _res; } -// _tmp_272: star_targets '=' +// _tmp_263: star_targets '=' static void * -_tmp_272_rule(Parser *p) +_tmp_263_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41787,7 +41256,7 @@ _tmp_272_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -41796,12 +41265,12 @@ _tmp_272_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -41810,9 +41279,9 @@ _tmp_272_rule(Parser *p) return _res; } -// _tmp_273: ')' | '**' +// _tmp_264: ')' | '**' static void * -_tmp_273_rule(Parser *p) +_tmp_264_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41828,18 +41297,18 @@ _tmp_273_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -41847,18 +41316,18 @@ _tmp_273_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -41867,9 +41336,9 @@ _tmp_273_rule(Parser *p) return _res; } -// _tmp_274: ':' | '**' +// _tmp_265: ':' | '**' static void * -_tmp_274_rule(Parser *p) +_tmp_265_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41885,18 +41354,18 @@ _tmp_274_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -41904,18 +41373,18 @@ _tmp_274_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -41924,9 +41393,9 @@ _tmp_274_rule(Parser *p) return _res; } -// _tmp_275: expression ['as' star_target] +// _tmp_266: expression ['as' star_target] static void * -_tmp_275_rule(Parser *p) +_tmp_266_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41942,22 +41411,22 @@ _tmp_275_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_275[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_284_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_275_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_275[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_275[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -41966,9 +41435,9 @@ _tmp_275_rule(Parser *p) return _res; } -// _tmp_276: expressions ['as' star_target] +// _tmp_267: expressions ['as' star_target] static void * -_tmp_276_rule(Parser *p) +_tmp_267_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41984,22 +41453,22 @@ _tmp_276_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_276[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_285_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_276_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_276[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_276[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -42008,9 +41477,9 @@ _tmp_276_rule(Parser *p) return _res; } -// _tmp_277: expression ['as' star_target] +// _tmp_268: expression ['as' star_target] static void * -_tmp_277_rule(Parser *p) +_tmp_268_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42026,22 +41495,22 @@ _tmp_277_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_277[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_286_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_277_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_277[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_277[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -42050,9 +41519,9 @@ _tmp_277_rule(Parser *p) return _res; } -// _tmp_278: expressions ['as' star_target] +// _tmp_269: expressions ['as' star_target] static void * -_tmp_278_rule(Parser *p) +_tmp_269_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42068,22 +41537,22 @@ _tmp_278_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_278[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expressions_var; if ( (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_287_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_278_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_278[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_278[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -42092,9 +41561,9 @@ _tmp_278_rule(Parser *p) return _res; } -// _tmp_279: 'as' NAME +// _tmp_270: 'as' NAME static void * -_tmp_279_rule(Parser *p) +_tmp_270_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42110,7 +41579,7 @@ _tmp_279_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_279[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -42119,12 +41588,12 @@ _tmp_279_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_279[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_279[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -42133,9 +41602,9 @@ _tmp_279_rule(Parser *p) return _res; } -// _tmp_280: ',' bitwise_or +// _tmp_271: ',' bitwise_or static void * -_tmp_280_rule(Parser *p) +_tmp_271_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42151,7 +41620,7 @@ _tmp_280_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_280[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); Token * _literal; expr_ty bitwise_or_var; if ( @@ -42160,12 +41629,12 @@ _tmp_280_rule(Parser *p) (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or ) { - D(fprintf(stderr, "%*c+ _tmp_280[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); _res = _PyPegen_dummy_name(p, _literal, bitwise_or_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_280[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' bitwise_or")); } _res = NULL; @@ -42174,9 +41643,9 @@ _tmp_280_rule(Parser *p) return _res; } -// _tmp_281: assignment_expression | expression !':=' +// _tmp_272: assignment_expression | expression !':=' static void * -_tmp_281_rule(Parser *p) +_tmp_272_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42192,18 +41661,18 @@ _tmp_281_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_281[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_281[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_281[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -42211,7 +41680,7 @@ _tmp_281_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_281[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -42219,12 +41688,12 @@ _tmp_281_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_281[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_281[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -42233,9 +41702,9 @@ _tmp_281_rule(Parser *p) return _res; } -// _loop0_283: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +// _loop0_274: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * -_loop0_283_rule(Parser *p) +_loop0_274_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42260,13 +41729,13 @@ _loop0_283_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_283[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c> _loop0_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_288_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_279_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -42292,7 +41761,7 @@ _loop0_283_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_283[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_274[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -42309,10 +41778,10 @@ _loop0_283_rule(Parser *p) return _seq; } -// _gather_282: -// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_283 +// _gather_273: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_274 static asdl_seq * -_gather_282_rule(Parser *p) +_gather_273_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42323,27 +41792,27 @@ _gather_282_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_283 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_274 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_282[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_283")); + D(fprintf(stderr, "%*c> _gather_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_274")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_288_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_279_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && - (seq = _loop0_283_rule(p)) // _loop0_283 + (seq = _loop0_274_rule(p)) // _loop0_274 ) { - D(fprintf(stderr, "%*c+ _gather_282[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_283")); + D(fprintf(stderr, "%*c+ _gather_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_274")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_282[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_283")); + D(fprintf(stderr, "%*c%s _gather_273[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_274")); } _res = NULL; done: @@ -42351,9 +41820,9 @@ _gather_282_rule(Parser *p) return _res; } -// _tmp_284: 'as' star_target +// _tmp_275: 'as' star_target static void * -_tmp_284_rule(Parser *p) +_tmp_275_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42369,7 +41838,7 @@ _tmp_284_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_284[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_275[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -42378,12 +41847,12 @@ _tmp_284_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_284[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_275[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_284[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_275[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -42392,9 +41861,9 @@ _tmp_284_rule(Parser *p) return _res; } -// _tmp_285: 'as' star_target +// _tmp_276: 'as' star_target static void * -_tmp_285_rule(Parser *p) +_tmp_276_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42410,7 +41879,7 @@ _tmp_285_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_285[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_276[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -42419,12 +41888,12 @@ _tmp_285_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_285[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_276[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_285[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_276[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -42433,9 +41902,9 @@ _tmp_285_rule(Parser *p) return _res; } -// _tmp_286: 'as' star_target +// _tmp_277: 'as' star_target static void * -_tmp_286_rule(Parser *p) +_tmp_277_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42451,7 +41920,7 @@ _tmp_286_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_286[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_277[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -42460,12 +41929,12 @@ _tmp_286_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_286[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_277[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_286[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_277[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -42474,9 +41943,9 @@ _tmp_286_rule(Parser *p) return _res; } -// _tmp_287: 'as' star_target +// _tmp_278: 'as' star_target static void * -_tmp_287_rule(Parser *p) +_tmp_278_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42492,7 +41961,7 @@ _tmp_287_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_287[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_278[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -42501,12 +41970,12 @@ _tmp_287_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_287[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_278[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_287[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_278[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -42515,9 +41984,9 @@ _tmp_287_rule(Parser *p) return _res; } -// _tmp_288: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_279: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_288_rule(Parser *p) +_tmp_279_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42533,18 +42002,18 @@ _tmp_288_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_288[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_279[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); expr_ty starred_expression_var; if ( (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_288[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_279[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_288[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_279[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -42552,20 +42021,20 @@ _tmp_288_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_288[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_289_var; + D(fprintf(stderr, "%*c> _tmp_279[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_280_var; if ( - (_tmp_289_var = _tmp_289_rule(p)) // assignment_expression | expression !':=' + (_tmp_280_var = _tmp_280_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_288[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_289_var; + D(fprintf(stderr, "%*c+ _tmp_279[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_280_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_288[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_279[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -42574,9 +42043,9 @@ _tmp_288_rule(Parser *p) return _res; } -// _tmp_289: assignment_expression | expression !':=' +// _tmp_280: assignment_expression | expression !':=' static void * -_tmp_289_rule(Parser *p) +_tmp_280_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42592,18 +42061,18 @@ _tmp_289_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_289[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_280[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_289[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_280[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_289[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_280[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -42611,7 +42080,7 @@ _tmp_289_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_289[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_280[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -42619,12 +42088,12 @@ _tmp_289_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_289[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_280[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_289[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_280[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index 7cdd5debe9a225f..84ed183c762e403 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -253,7 +253,7 @@ def lookahead_call_helper(self, node: Lookahead, positive: int) -> FunctionCall: else: return FunctionCall( function=f"_PyPegen_lookahead", - arguments=[positive, call.function, *call.arguments], + arguments=[positive, f"(void *(*)(Parser *)) {call.function}", *call.arguments], return_type="int", ) From 5865fa5f9b33ce003dad99cac5e5378d6aed47c5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 Apr 2024 11:42:01 -0600 Subject: [PATCH 119/127] gh-117953: Add Internal struct _Py_ext_module_loader_info (gh-118194) This helps with a later change that splits up _PyImport_LoadDynamicModuleWithSpec(). --- Include/internal/pycore_importdl.h | 30 +++++- Python/import.c | 94 ++++++++++-------- Python/importdl.c | 150 +++++++++++++++++++---------- 3 files changed, 180 insertions(+), 94 deletions(-) diff --git a/Include/internal/pycore_importdl.h b/Include/internal/pycore_importdl.h index c8583582b358ac1..8bf7c2a48f66bea 100644 --- a/Include/internal/pycore_importdl.h +++ b/Include/internal/pycore_importdl.h @@ -14,10 +14,38 @@ extern "C" { extern const char *_PyImport_DynLoadFiletab[]; -extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *); typedef PyObject *(*PyModInitFunction)(void); +struct _Py_ext_module_loader_info { + PyObject *filename; +#ifndef MS_WINDOWS + PyObject *filename_encoded; +#endif + PyObject *name; + PyObject *name_encoded; + /* path is always a borrowed ref of name or filename, + * depending on if it's builtin or not. */ + PyObject *path; + const char *hook_prefix; + const char *newcontext; +}; +extern void _Py_ext_module_loader_info_clear( + struct _Py_ext_module_loader_info *info); +extern int _Py_ext_module_loader_info_init( + struct _Py_ext_module_loader_info *info, + PyObject *name, + PyObject *filename); +extern int _Py_ext_module_loader_info_init_from_spec( + struct _Py_ext_module_loader_info *info, + PyObject *spec); + +extern PyObject *_PyImport_LoadDynamicModuleWithSpec( + struct _Py_ext_module_loader_info *info, + PyObject *spec, + FILE *fp); + + /* Max length of module suffix searched for -- accommodates "module.slb" */ #define MAXSUFFIXSIZE 12 diff --git a/Python/import.c b/Python/import.c index 739f506fe03100a..56011295f95190f 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1328,11 +1328,11 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, static PyObject * -import_find_extension(PyThreadState *tstate, PyObject *name, - PyObject *path) +import_find_extension(PyThreadState *tstate, + struct _Py_ext_module_loader_info *info) { /* Only single-phase init modules will be in the cache. */ - PyModuleDef *def = _extensions_cache_get(path, name); + PyModuleDef *def = _extensions_cache_get(info->path, info->name); if (def == NULL) { return NULL; } @@ -1340,7 +1340,7 @@ import_find_extension(PyThreadState *tstate, PyObject *name, /* It may have been successfully imported previously in an interpreter that allows legacy modules but is not allowed in the current interpreter. */ - const char *name_buf = PyUnicode_AsUTF8(name); + const char *name_buf = PyUnicode_AsUTF8(info->name); assert(name_buf != NULL); if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) { return NULL; @@ -1355,12 +1355,13 @@ import_find_extension(PyThreadState *tstate, PyObject *name, if (m_copy == NULL) { /* It might be a core module (e.g. sys & builtins), for which we don't set m_copy. */ - m_copy = get_core_module_dict(tstate->interp, name, path); + m_copy = get_core_module_dict( + tstate->interp, info->name, info->path); if (m_copy == NULL) { return NULL; } } - mod = import_add_module(tstate, name); + mod = import_add_module(tstate, info->name); if (mod == NULL) { return NULL; } @@ -1378,15 +1379,16 @@ import_find_extension(PyThreadState *tstate, PyObject *name, if (def->m_base.m_init == NULL) return NULL; mod = def->m_base.m_init(); - if (mod == NULL) + if (mod == NULL) { return NULL; - if (PyObject_SetItem(modules, name, mod) == -1) { + } + if (PyObject_SetItem(modules, info->name, mod) == -1) { Py_DECREF(mod); return NULL; } } if (_modules_by_index_set(tstate->interp, def, mod) < 0) { - PyMapping_DelItem(modules, name); + PyMapping_DelItem(modules, info->name); Py_DECREF(mod); return NULL; } @@ -1394,7 +1396,7 @@ import_find_extension(PyThreadState *tstate, PyObject *name, int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose; if (verbose) { PySys_FormatStderr("import %U # previously loaded (%R)\n", - name, path); + info->name, info->path); } return mod; } @@ -1505,44 +1507,56 @@ static PyObject* create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) { PyModuleDef *def = NULL; - PyObject *mod = import_find_extension(tstate, name, name); + + struct _Py_ext_module_loader_info info; + if (_Py_ext_module_loader_info_init(&info, name, NULL) < 0) { + return NULL; + } + + PyObject *mod = import_find_extension(tstate, &info); if (mod || _PyErr_Occurred(tstate)) { - return mod; + goto finally; } struct _inittab *found = NULL; for (struct _inittab *p = INITTAB; p->name != NULL; p++) { - if (_PyUnicode_EqualToASCIIString(name, p->name)) { + if (_PyUnicode_EqualToASCIIString(info.name, p->name)) { found = p; } } if (found == NULL) { // not found - Py_RETURN_NONE; + mod = Py_NewRef(Py_None); + goto finally; } PyModInitFunction p0 = (PyModInitFunction)found->initfunc; if (p0 == NULL) { /* Cannot re-init internal module ("sys" or "builtins") */ - assert(is_core_module(tstate->interp, name, name)); - return import_add_module(tstate, name); + assert(is_core_module(tstate->interp, info.name, info.path)); + mod = import_add_module(tstate, info.name); + goto finally; } mod = p0(); if (mod == NULL) { - return NULL; + goto finally; } if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) { def = (PyModuleDef*)mod; assert(!is_singlephase(def)); - return PyModule_FromDefAndSpec(def, spec); + mod = PyModule_FromDefAndSpec(def, spec); + if (mod == NULL) { + goto finally; + } } else { assert(PyModule_Check(mod)); def = PyModule_GetDef(mod); if (def == NULL) { - return NULL; + Py_CLEAR(mod); + goto finally; } assert(is_singlephase(def)); @@ -1553,22 +1567,29 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) // gh-88216: Extensions and def->m_base.m_copy can be updated // when the extension module doesn't support sub-interpreters. if (def->m_size == -1 - && !is_core_module(tstate->interp, name, name)) + && !is_core_module(tstate->interp, info.name, info.path)) { singlephase.m_dict = PyModule_GetDict(mod); assert(singlephase.m_dict != NULL); } if (update_global_state_for_extension( - tstate, name, name, def, &singlephase) < 0) + tstate, info.name, info.path, def, &singlephase) < 0) { - return NULL; + Py_CLEAR(mod); + goto finally; } PyObject *modules = get_modules_dict(tstate, true); - if (finish_singlephase_extension(tstate, mod, def, name, modules) < 0) { - return NULL; + if (finish_singlephase_extension( + tstate, mod, def, info.name, modules) < 0) + { + Py_CLEAR(mod); + goto finally; } - return mod; } + +finally: + _Py_ext_module_loader_info_clear(&info); + return mod; } @@ -3878,28 +3899,22 @@ static PyObject * _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) /*[clinic end generated code: output=83249b827a4fde77 input=c31b954f4cf4e09d]*/ { - PyObject *mod, *name, *filename; + PyObject *mod = NULL; FILE *fp; - name = PyObject_GetAttrString(spec, "name"); - if (name == NULL) { - return NULL; - } - - filename = PyObject_GetAttrString(spec, "origin"); - if (filename == NULL) { - Py_DECREF(name); + struct _Py_ext_module_loader_info info; + if (_Py_ext_module_loader_info_init_from_spec(&info, spec) < 0) { return NULL; } PyThreadState *tstate = _PyThreadState_GET(); - mod = import_find_extension(tstate, name, filename); + mod = import_find_extension(tstate, &info); if (mod != NULL || _PyErr_Occurred(tstate)) { assert(mod == NULL || !_PyErr_Occurred(tstate)); goto finally; } - if (PySys_Audit("import", "OOOOO", name, filename, + if (PySys_Audit("import", "OOOOO", info.name, info.filename, Py_None, Py_None, Py_None) < 0) { goto finally; @@ -3911,7 +3926,7 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) * _PyImport_GetModInitFunc(), but it isn't clear if the intervening * code relies on fp still being open. */ if (file != NULL) { - fp = _Py_fopen_obj(filename, "r"); + fp = _Py_fopen_obj(info.filename, "r"); if (fp == NULL) { goto finally; } @@ -3920,7 +3935,7 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) fp = NULL; } - mod = _PyImport_LoadDynamicModuleWithSpec(spec, fp); + mod = _PyImport_LoadDynamicModuleWithSpec(&info, spec, fp); // XXX Shouldn't this happen in the error cases too. if (fp) { @@ -3928,8 +3943,7 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file) } finally: - Py_DECREF(name); - Py_DECREF(filename); + _Py_ext_module_loader_info_clear(&info); return mod; } diff --git a/Python/importdl.c b/Python/importdl.c index e512161d3071f2d..65370249493325e 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -93,57 +93,108 @@ get_encoded_name(PyObject *name, const char **hook_prefix) { return NULL; } -PyObject * -_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) +void +_Py_ext_module_loader_info_clear(struct _Py_ext_module_loader_info *info) { + Py_CLEAR(info->filename); #ifndef MS_WINDOWS - PyObject *filename_bytes = NULL; - const char *filename_buf; + Py_CLEAR(info->filename_encoded); #endif - PyObject *name_unicode = NULL, *name = NULL, *filename = NULL, *m = NULL; - const char *name_buf, *hook_prefix; - const char *oldcontext, *newcontext; - dl_funcptr exportfunc; - PyModuleDef *def; - PyModInitFunction p0; + Py_CLEAR(info->name); + Py_CLEAR(info->name_encoded); +} - name_unicode = PyObject_GetAttrString(spec, "name"); - if (name_unicode == NULL) { - return NULL; - } - if (!PyUnicode_Check(name_unicode)) { +int +_Py_ext_module_loader_info_init(struct _Py_ext_module_loader_info *p_info, + PyObject *name, PyObject *filename) +{ + struct _Py_ext_module_loader_info info = {0}; + + assert(name != NULL); + if (!PyUnicode_Check(name)) { PyErr_SetString(PyExc_TypeError, - "spec.name must be a string"); - goto error; + "module name must be a string"); + _Py_ext_module_loader_info_clear(&info); + return -1; } - newcontext = PyUnicode_AsUTF8(name_unicode); - if (newcontext == NULL) { - goto error; + info.name = Py_NewRef(name); + + info.name_encoded = get_encoded_name(info.name, &info.hook_prefix); + if (info.name_encoded == NULL) { + _Py_ext_module_loader_info_clear(&info); + return -1; } - name = get_encoded_name(name_unicode, &hook_prefix); - if (name == NULL) { - goto error; + info.newcontext = PyUnicode_AsUTF8(info.name); + if (info.newcontext == NULL) { + _Py_ext_module_loader_info_clear(&info); + return -1; } - name_buf = PyBytes_AS_STRING(name); - filename = PyObject_GetAttrString(spec, "origin"); + if (filename != NULL) { + if (!PyUnicode_Check(filename)) { + PyErr_SetString(PyExc_TypeError, + "module filename must be a string"); + _Py_ext_module_loader_info_clear(&info); + return -1; + } + info.filename = Py_NewRef(filename); + +#ifndef MS_WINDOWS + info.filename_encoded = PyUnicode_EncodeFSDefault(info.filename); + if (info.filename_encoded == NULL) { + _Py_ext_module_loader_info_clear(&info); + return -1; + } +#endif + + info.path = info.filename; + } + else { + info.path = info.name; + } + + *p_info = info; + return 0; +} + +int +_Py_ext_module_loader_info_init_from_spec( + struct _Py_ext_module_loader_info *p_info, + PyObject *spec) +{ + PyObject *name = PyObject_GetAttrString(spec, "name"); + if (name == NULL) { + return -1; + } + PyObject *filename = PyObject_GetAttrString(spec, "origin"); if (filename == NULL) { - goto error; + return -1; } + return _Py_ext_module_loader_info_init(p_info, name, filename); +} + + +PyObject * +_PyImport_LoadDynamicModuleWithSpec(struct _Py_ext_module_loader_info *info, + PyObject *spec, FILE *fp) +{ + PyObject *m = NULL; + const char *name_buf = PyBytes_AS_STRING(info->name_encoded); + const char *oldcontext; + dl_funcptr exportfunc; + PyModInitFunction p0; + PyModuleDef *def; #ifdef MS_WINDOWS exportfunc = _PyImport_FindSharedFuncptrWindows( - hook_prefix, name_buf, filename, fp); + info->hook_prefix, name_buf, info->filename, fp); #else - filename_bytes = PyUnicode_EncodeFSDefault(filename); - if (filename_bytes == NULL) { - goto error; + { + const char *path_buf = PyBytes_AS_STRING(info->filename_encoded); + exportfunc = _PyImport_FindSharedFuncptr( + info->hook_prefix, name_buf, path_buf, fp); } - filename_buf = PyBytes_AS_STRING(filename_bytes); - exportfunc = _PyImport_FindSharedFuncptr( - hook_prefix, name_buf, filename_buf, fp); - Py_DECREF(filename_bytes); #endif if (exportfunc == NULL) { @@ -152,11 +203,11 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) msg = PyUnicode_FromFormat( "dynamic module does not define " "module export function (%s_%s)", - hook_prefix, name_buf); - if (msg == NULL) - goto error; - PyErr_SetImportError(msg, name_unicode, filename); - Py_DECREF(msg); + info->hook_prefix, name_buf); + if (msg != NULL) { + PyErr_SetImportError(msg, info->name, info->filename); + Py_DECREF(msg); + } } goto error; } @@ -164,7 +215,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) p0 = (PyModInitFunction)exportfunc; /* Package context is needed for single-phase init */ - oldcontext = _PyImport_SwapPackageContext(newcontext); + oldcontext = _PyImport_SwapPackageContext(info->newcontext); m = p0(); _PyImport_SwapPackageContext(oldcontext); @@ -195,9 +246,6 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) goto error; } if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { - Py_DECREF(name_unicode); - Py_DECREF(name); - Py_DECREF(filename); return PyModule_FromDefAndSpec((PyModuleDef*)m, spec); } @@ -207,7 +255,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) goto error; } - if (hook_prefix == nonascii_prefix) { + if (info->hook_prefix == nonascii_prefix) { /* don't allow legacy init for non-ASCII module names */ PyErr_Format( PyExc_SystemError, @@ -227,24 +275,20 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) def->m_base.m_init = p0; /* Remember the filename as the __file__ attribute */ - if (PyModule_AddObjectRef(m, "__file__", filename) < 0) { + if (PyModule_AddObjectRef(m, "__file__", info->filename) < 0) { PyErr_Clear(); /* Not important enough to report */ } PyObject *modules = PyImport_GetModuleDict(); - if (_PyImport_FixupExtensionObject(m, name_unicode, filename, modules) < 0) + if (_PyImport_FixupExtensionObject( + m, info->name, info->filename, modules) < 0) + { goto error; - - Py_DECREF(name_unicode); - Py_DECREF(name); - Py_DECREF(filename); + } return m; error: - Py_DECREF(name_unicode); - Py_XDECREF(name); - Py_XDECREF(filename); Py_XDECREF(m); return NULL; } From 809aa9a682fc865f7502e7421da0a74d204aab6d Mon Sep 17 00:00:00 2001 From: edson duarte Date: Wed, 24 Apr 2024 16:53:52 -0300 Subject: [PATCH 120/127] gh-85453: Adapt datetime.rst to devguide recommendations for code snippets and variables (#118068) Also remove formatting from numeric literals. Co-authored-by: Serhiy Storchaka Co-authored-by: Jelle Zijlstra Co-authored-by: Erlend E. Aasland --- Doc/library/datetime.rst | 90 ++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index e8bd51ba20802ed..84fede472eeacc3 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -85,7 +85,7 @@ The :mod:`!datetime` module exports the following constants: .. data:: MINYEAR The smallest year number allowed in a :class:`date` or :class:`.datetime` object. - :const:`MINYEAR` is ``1``. + :const:`MINYEAR` is 1. .. data:: MAXYEAR @@ -207,7 +207,7 @@ A :class:`timedelta` object represents a duration, the difference between two .. class:: timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) - All arguments are optional and default to ``0``. Arguments may be integers + All arguments are optional and default to 0. Arguments may be integers or floats, and may be positive or negative. Only *days*, *seconds* and *microseconds* are stored internally. @@ -280,7 +280,7 @@ Class attributes: The smallest possible difference between non-equal :class:`timedelta` objects, ``timedelta(microseconds=1)``. -Note that, because of normalization, ``timedelta.max`` > ``-timedelta.min``. +Note that, because of normalization, ``timedelta.max`` is greater than ``-timedelta.min``. ``-timedelta.max`` is not representable as a :class:`timedelta` object. Instance attributes (read-only): @@ -302,26 +302,27 @@ Supported operations: +--------------------------------+-----------------------------------------------+ | Operation | Result | +================================+===============================================+ -| ``t1 = t2 + t3`` | Sum of *t2* and *t3*. Afterwards *t1*-*t2* == | -| | *t3* and *t1*-*t3* == *t2* are true. (1) | +| ``t1 = t2 + t3`` | Sum of ``t2`` and ``t3``. | +| | Afterwards ``t1 - t2 == t3`` and | +| | ``t1 - t3 == t2`` are true. (1) | +--------------------------------+-----------------------------------------------+ -| ``t1 = t2 - t3`` | Difference of *t2* and *t3*. Afterwards *t1* | -| | == *t2* - *t3* and *t2* == *t1* + *t3* are | +| ``t1 = t2 - t3`` | Difference of ``t2`` and ``t3``. Afterwards | +| | ``t1 == t2 - t3`` and ``t2 == t1 + t3`` are | | | true. (1)(6) | +--------------------------------+-----------------------------------------------+ | ``t1 = t2 * i or t1 = i * t2`` | Delta multiplied by an integer. | -| | Afterwards *t1* // i == *t2* is true, | +| | Afterwards ``t1 // i == t2`` is true, | | | provided ``i != 0``. | +--------------------------------+-----------------------------------------------+ -| | In general, *t1* \* i == *t1* \* (i-1) + *t1* | +| | In general, ``t1 * i == t1 * (i-1) + t1`` | | | is true. (1) | +--------------------------------+-----------------------------------------------+ | ``t1 = t2 * f or t1 = f * t2`` | Delta multiplied by a float. The result is | | | rounded to the nearest multiple of | | | timedelta.resolution using round-half-to-even.| +--------------------------------+-----------------------------------------------+ -| ``f = t2 / t3`` | Division (3) of overall duration *t2* by | -| | interval unit *t3*. Returns a :class:`float` | +| ``f = t2 / t3`` | Division (3) of overall duration ``t2`` by | +| | interval unit ``t3``. Returns a :class:`float`| | | object. | +--------------------------------+-----------------------------------------------+ | ``t1 = t2 / f or t1 = t2 / i`` | Delta divided by a float or an int. The result| @@ -343,13 +344,12 @@ Supported operations: | ``+t1`` | Returns a :class:`timedelta` object with the | | | same value. (2) | +--------------------------------+-----------------------------------------------+ -| ``-t1`` | equivalent to | -| | :class:`timedelta`\ (-*t1.days*, | -| | -*t1.seconds*, -*t1.microseconds*), | -| | and to *t1*\* -1. (1)(4) | +| ``-t1`` | Equivalent to ``timedelta(-t1.days, | +| | -t1.seconds*, -t1.microseconds)``, | +| | and to ``t1 * -1``. (1)(4) | +--------------------------------+-----------------------------------------------+ -| ``abs(t)`` | equivalent to +\ *t* when ``t.days >= 0``, | -| | and to -*t* when ``t.days < 0``. (2) | +| ``abs(t)`` | Equivalent to ``+t`` when ``t.days >= 0``, | +| | and to ``-t`` when ``t.days < 0``. (2) | +--------------------------------+-----------------------------------------------+ | ``str(t)`` | Returns a string in the form | | | ``[D day[s], ][H]H:MM:SS[.UUUUUU]``, where D | @@ -370,10 +370,10 @@ Notes: This is exact and cannot overflow. (3) - Division by 0 raises :exc:`ZeroDivisionError`. + Division by zero raises :exc:`ZeroDivisionError`. (4) - -*timedelta.max* is not representable as a :class:`timedelta` object. + ``-timedelta.max`` is not representable as a :class:`timedelta` object. (5) String representations of :class:`timedelta` objects are normalized @@ -583,10 +583,10 @@ Supported operations: +-------------------------------+----------------------------------------------+ | Operation | Result | +===============================+==============================================+ -| ``date2 = date1 + timedelta`` | *date2* will be ``timedelta.days`` days | -| | after *date1*. (1) | +| ``date2 = date1 + timedelta`` | ``date2`` will be ``timedelta.days`` days | +| | after ``date1``. (1) | +-------------------------------+----------------------------------------------+ -| ``date2 = date1 - timedelta`` | Computes *date2* such that ``date2 + | +| ``date2 = date1 - timedelta`` | Computes ``date2`` such that ``date2 + | | | timedelta == date1``. (2) | +-------------------------------+----------------------------------------------+ | ``timedelta = date1 - date2`` | \(3) | @@ -613,8 +613,8 @@ Notes: ``timedelta.seconds`` and ``timedelta.microseconds`` are ignored. (3) - This is exact, and cannot overflow. timedelta.seconds and - timedelta.microseconds are 0, and date2 + timedelta == date1 after. + This is exact, and cannot overflow. ``timedelta.seconds`` and + ``timedelta.microseconds`` are 0, and ``date2 + timedelta == date1`` after. (4) :class:`date` objects are equal if they represent the same date. @@ -671,7 +671,7 @@ Instance methods: time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1)) where ``yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1`` - is the day number within the current year starting with ``1`` for January 1st. + is the day number within the current year starting with 1 for January 1st. .. method:: date.toordinal() @@ -991,8 +991,8 @@ Other constructors, all class methods: .. classmethod:: datetime.fromordinal(ordinal) Return the :class:`.datetime` corresponding to the proleptic Gregorian ordinal, - where January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless ``1 - <= ordinal <= datetime.max.toordinal()``. The hour, minute, second and + where January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless + ``1 <= ordinal <= datetime.max.toordinal()``. The hour, minute, second and microsecond of the result are all 0, and :attr:`.tzinfo` is ``None``. @@ -1167,8 +1167,8 @@ Instance attributes (read-only): In ``[0, 1]``. Used to disambiguate wall times during a repeated interval. (A repeated interval occurs when clocks are rolled back at the end of daylight saving time or when the UTC offset for the current zone is decreased for political reasons.) - The value 0 (1) represents the earlier (later) of the two moments with the same wall - time representation. + The values 0 and 1 represent, respectively, the earlier and later of the two + moments with the same wall time representation. .. versionadded:: 3.6 @@ -1193,16 +1193,16 @@ Supported operations: +---------------------------------------+--------------------------------+ (1) - datetime2 is a duration of timedelta removed from datetime1, moving forward in - time if ``timedelta.days`` > 0, or backward if ``timedelta.days`` < 0. The + ``datetime2`` is a duration of ``timedelta`` removed from ``datetime1``, moving forward in + time if ``timedelta.days > 0``, or backward if ``timedelta.days < 0``. The result has the same :attr:`~.datetime.tzinfo` attribute as the input datetime, and - datetime2 - datetime1 == timedelta after. :exc:`OverflowError` is raised if - datetime2.year would be smaller than :const:`MINYEAR` or larger than + ``datetime2 - datetime1 == timedelta`` after. :exc:`OverflowError` is raised if + ``datetime2.year`` would be smaller than :const:`MINYEAR` or larger than :const:`MAXYEAR`. Note that no time zone adjustments are done even if the input is an aware object. (2) - Computes the datetime2 such that datetime2 + timedelta == datetime1. As for + Computes the ``datetime2`` such that ``datetime2 + timedelta == datetime1``. As for addition, the result has the same :attr:`~.datetime.tzinfo` attribute as the input datetime, and no time zone adjustments are done even if the input is aware. @@ -1387,12 +1387,12 @@ Instance methods: d.weekday(), yday, dst)) where ``yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1`` - is the day number within the current year starting with ``1`` for January + is the day number within the current year starting with 1 for January 1st. The :attr:`~time.struct_time.tm_isdst` flag of the result is set according to the :meth:`dst` method: :attr:`.tzinfo` is ``None`` or :meth:`dst` returns ``None``, :attr:`!tm_isdst` is set to ``-1``; else if :meth:`dst` returns a - non-zero value, :attr:`!tm_isdst` is set to ``1``; else :attr:`!tm_isdst` is - set to ``0``. + non-zero value, :attr:`!tm_isdst` is set to 1; else :attr:`!tm_isdst` is + set to 0. .. method:: datetime.utctimetuple() @@ -1404,7 +1404,7 @@ Instance methods: If *d* is aware, *d* is normalized to UTC time, by subtracting ``d.utcoffset()``, and a :class:`time.struct_time` for the normalized time is returned. :attr:`!tm_isdst` is forced to 0. Note - that an :exc:`OverflowError` may be raised if *d*.year was + that an :exc:`OverflowError` may be raised if ``d.year`` was ``MINYEAR`` or ``MAXYEAR`` and UTC adjustment spills over a year boundary. @@ -1735,7 +1735,7 @@ day, and subject to adjustment via a :class:`tzinfo` object. * ``fold in [0, 1]``. If an argument outside those ranges is given, :exc:`ValueError` is raised. All - default to ``0`` except *tzinfo*, which defaults to :const:`None`. + default to 0 except *tzinfo*, which defaults to :const:`None`. Class attributes: @@ -1790,8 +1790,8 @@ Instance attributes (read-only): In ``[0, 1]``. Used to disambiguate wall times during a repeated interval. (A repeated interval occurs when clocks are rolled back at the end of daylight saving time or when the UTC offset for the current zone is decreased for political reasons.) - The value 0 (1) represents the earlier (later) of the two moments with the same wall - time representation. + The values 0 and 1 represent, respectively, the earlier and later of the two + moments with the same wall time representation. .. versionadded:: 3.6 @@ -2083,7 +2083,7 @@ Examples of working with a :class:`.time` object:: ``tz.utcoffset(dt) - tz.dst(dt)`` must return the same result for every :class:`.datetime` *dt* with ``dt.tzinfo == - tz`` For sane :class:`tzinfo` subclasses, this expression yields the time + tz``. For sane :class:`tzinfo` subclasses, this expression yields the time zone's "standard offset", which should not depend on the date or the time, but only on geographic location. The implementation of :meth:`datetime.astimezone` relies on this, but cannot detect violations; it's the programmer's @@ -2120,7 +2120,7 @@ Examples of working with a :class:`.time` object:: Return the time zone name corresponding to the :class:`.datetime` object *dt*, as a string. Nothing about string names is defined by the :mod:`!datetime` module, and there's no requirement that it mean anything in particular. For example, - "GMT", "UTC", "-500", "-5:00", "EDT", "US/Eastern", "America/New York" are all + ``"GMT"``, ``"UTC"``, ``"-500"``, ``"-5:00"``, ``"EDT"``, ``"US/Eastern"``, ``"America/New York"`` are all valid replies. Return ``None`` if a string name isn't known. Note that this is a method rather than a fixed string primarily because some :class:`tzinfo` subclasses will wish to return different names depending on the specific value @@ -2561,11 +2561,11 @@ information, which are supported in ``datetime.strptime`` but are discarded by For :class:`.time` objects, the format codes for year, month, and day should not be used, as :class:`!time` objects have no such values. If they're used anyway, -``1900`` is substituted for the year, and ``1`` for the month and day. +``1900`` is substituted for the year, and 1 for the month and day. For :class:`date` objects, the format codes for hours, minutes, seconds, and microseconds should not be used, as :class:`date` objects have no such -values. If they're used anyway, ``0`` is substituted for them. +values. If they're used anyway, 0 is substituted for them. For the same reason, handling of format strings containing Unicode code points that can't be represented in the charset of the current locale is also From 59a4d52973ca73bd739f914e88243a31dbef6b32 Mon Sep 17 00:00:00 2001 From: edson duarte Date: Wed, 24 Apr 2024 17:19:54 -0300 Subject: [PATCH 121/127] gh-85453: Make numeric literals consistent across datetime.rst (#118245) Remove code formatting from remaining numeric literals. --- Doc/library/datetime.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 84fede472eeacc3..b1b5e04c74b0666 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -91,7 +91,7 @@ The :mod:`!datetime` module exports the following constants: .. data:: MAXYEAR The largest year number allowed in a :class:`date` or :class:`.datetime` object. - :const:`MAXYEAR` is ``9999``. + :const:`MAXYEAR` is 9999. .. attribute:: UTC @@ -2561,7 +2561,7 @@ information, which are supported in ``datetime.strptime`` but are discarded by For :class:`.time` objects, the format codes for year, month, and day should not be used, as :class:`!time` objects have no such values. If they're used anyway, -``1900`` is substituted for the year, and 1 for the month and day. +1900 is substituted for the year, and 1 for the month and day. For :class:`date` objects, the format codes for hours, minutes, seconds, and microseconds should not be used, as :class:`date` objects have no such @@ -2708,4 +2708,4 @@ Notes: `_ for a good explanation. -.. [#] Passing ``datetime.strptime('Feb 29', '%b %d')`` will fail since ``1900`` is not a leap year. +.. [#] Passing ``datetime.strptime('Feb 29', '%b %d')`` will fail since 1900 is not a leap year. From 345e1e04ec72698a1e257c805b3840d9f55eb80d Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Wed, 24 Apr 2024 21:25:22 +0100 Subject: [PATCH 122/127] gh-112730: Make the test suite resilient to color-activation environment variables (#117672) --- .github/workflows/reusable-ubuntu.yml | 1 + Lib/doctest.py | 10 +++++++++- Lib/idlelib/idle_test/test_run.py | 3 +++ Lib/test/support/__init__.py | 20 ++++++++++++++++++++ Lib/test/test_cmd_line.py | 2 ++ Lib/test/test_exceptions.py | 7 ++++++- Lib/test/test_interpreters/test_api.py | 2 ++ Lib/test/test_sys.py | 5 +++++ Lib/test/test_threading.py | 3 +++ Lib/test/test_traceback.py | 21 ++++++++++++++++++--- Lib/test/test_tracemalloc.py | 2 +- Lib/test/test_warnings/__init__.py | 3 +++ Lib/traceback.py | 26 ++++++++++++++++---------- 13 files changed, 89 insertions(+), 16 deletions(-) diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml index ee64fe62a0bd0a2..e6fbaaf74c5a4bd 100644 --- a/.github/workflows/reusable-ubuntu.yml +++ b/.github/workflows/reusable-ubuntu.yml @@ -14,6 +14,7 @@ jobs: timeout-minutes: 60 runs-on: ubuntu-20.04 env: + FORCE_COLOR: 1 OPENSSL_VER: 3.0.13 PYTHONSTRICTEXTENSIONBUILD: 1 steps: diff --git a/Lib/doctest.py b/Lib/doctest.py index a3b42fdfb12254d..d8c632e47e7b7a3 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -1556,7 +1556,11 @@ def out(s): # Make sure sys.displayhook just prints the value to stdout save_displayhook = sys.displayhook sys.displayhook = sys.__displayhook__ - + saved_can_colorize = traceback._can_colorize + traceback._can_colorize = lambda: False + color_variables = {"PYTHON_COLORS": None, "FORCE_COLOR": None} + for key in color_variables: + color_variables[key] = os.environ.pop(key, None) try: return self.__run(test, compileflags, out) finally: @@ -1565,6 +1569,10 @@ def out(s): sys.settrace(save_trace) linecache.getlines = self.save_linecache_getlines sys.displayhook = save_displayhook + traceback._can_colorize = saved_can_colorize + for key, value in color_variables.items(): + if value is not None: + os.environ[key] = value if clear_globs: test.globs.clear() import builtins diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index a38e43dcb9d1c4a..83ecbffa2a197e7 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -8,6 +8,7 @@ from unittest import mock import idlelib from idlelib.idle_test.mock_idle import Func +from test.support import force_not_colorized idlelib.testing = True # Use {} for executing test user code. @@ -46,6 +47,7 @@ def __eq__(self, other): "Did you mean: 'real'?\n"), ) + @force_not_colorized def test_get_message(self): for code, exc, msg in self.data: with self.subTest(code=code): @@ -57,6 +59,7 @@ def test_get_message(self): expect = f'{exc.__name__}: {msg}' self.assertEqual(actual, expect) + @force_not_colorized @mock.patch.object(run, 'cleanup_traceback', new_callable=lambda: (lambda t, e: None)) def test_get_multiple_message(self, mock): diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 6eb0f84b02ea22a..ea4945466cac823 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -59,6 +59,7 @@ "Py_DEBUG", "exceeds_recursion_limit", "get_c_recursion_limit", "skip_on_s390x", "without_optimizer", + "force_not_colorized" ] @@ -2557,3 +2558,22 @@ def copy_python_src_ignore(path, names): 'build', } return ignored + +def force_not_colorized(func): + """Force the terminal not to be colorized.""" + @functools.wraps(func) + def wrapper(*args, **kwargs): + import traceback + original_fn = traceback._can_colorize + variables = {"PYTHON_COLORS": None, "FORCE_COLOR": None} + try: + for key in variables: + variables[key] = os.environ.pop(key, None) + traceback._can_colorize = lambda: False + return func(*args, **kwargs) + finally: + traceback._can_colorize = original_fn + for key, value in variables.items(): + if value is not None: + os.environ[key] = value + return wrapper diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index fb832aed3152ff2..9624d35d0c3948e 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -10,6 +10,7 @@ import unittest from test import support from test.support import os_helper +from test.support import force_not_colorized from test.support.script_helper import ( spawn_python, kill_python, assert_python_ok, assert_python_failure, interpreter_requires_environment @@ -1027,6 +1028,7 @@ def test_sys_flags_not_set(self): class SyntaxErrorTests(unittest.TestCase): + @force_not_colorized def check_string(self, code): proc = subprocess.run([sys.executable, "-"], input=code, stdout=subprocess.PIPE, stderr=subprocess.PIPE) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 1224f143b5441f7..3138f50076f1df0 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -12,7 +12,8 @@ from test.support import (captured_stderr, check_impl_detail, cpython_only, gc_collect, no_tracing, script_helper, - SuppressCrashReport) + SuppressCrashReport, + force_not_colorized) from test.support.import_helper import import_module from test.support.os_helper import TESTFN, unlink from test.support.warnings_helper import check_warnings @@ -41,6 +42,7 @@ def __str__(self): # XXX This is not really enough, each *operation* should be tested! + class ExceptionTests(unittest.TestCase): def raise_catch(self, exc, excname): @@ -1994,6 +1996,7 @@ def write_source(self, source): _rc, _out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN) return err.decode('utf-8').splitlines() + @force_not_colorized def test_assertion_error_location(self): cases = [ ('assert None', @@ -2070,6 +2073,7 @@ def test_assertion_error_location(self): result = self.write_source(source) self.assertEqual(result[-3:], expected) + @force_not_colorized def test_multiline_not_highlighted(self): cases = [ (""" @@ -2102,6 +2106,7 @@ def test_multiline_not_highlighted(self): class SyntaxErrorTests(unittest.TestCase): + @force_not_colorized def test_range_of_offsets(self): cases = [ # Basic range from 2->7 diff --git a/Lib/test/test_interpreters/test_api.py b/Lib/test/test_interpreters/test_api.py index 0039fa46496c53f..719c1c721cad7c0 100644 --- a/Lib/test/test_interpreters/test_api.py +++ b/Lib/test/test_interpreters/test_api.py @@ -12,6 +12,7 @@ _interpreters = import_helper.import_module('_interpreters') from test.support import Py_GIL_DISABLED from test.support import interpreters +from test.support import force_not_colorized from test.support.interpreters import ( InterpreterError, InterpreterNotFoundError, ExecutionFailed, ) @@ -735,6 +736,7 @@ def test_failure(self): with self.assertRaises(ExecutionFailed): interp.exec('raise Exception') + @force_not_colorized def test_display_preserved_exception(self): tempdir = self.temp_dir() modfile = self.make_module('spam', tempdir, text=""" diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index ab26bf56d9ced9b..14ec51eb757e006 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -16,6 +16,7 @@ from test.support.script_helper import assert_python_ok, assert_python_failure from test.support import threading_helper from test.support import import_helper +from test.support import force_not_colorized try: from test.support import interpreters except ImportError: @@ -145,6 +146,7 @@ def f(): class ExceptHookTest(unittest.TestCase): + @force_not_colorized def test_original_excepthook(self): try: raise ValueError(42) @@ -156,6 +158,7 @@ def test_original_excepthook(self): self.assertRaises(TypeError, sys.__excepthook__) + @force_not_colorized def test_excepthook_bytes_filename(self): # bpo-37467: sys.excepthook() must not crash if a filename # is a bytes string @@ -793,6 +796,7 @@ def test_sys_getwindowsversion_no_instantiation(self): def test_clear_type_cache(self): sys._clear_type_cache() + @force_not_colorized @support.requires_subprocess() def test_ioencoding(self): env = dict(os.environ) @@ -1108,6 +1112,7 @@ def test_getandroidapilevel(self): self.assertIsInstance(level, int) self.assertGreater(level, 0) + @force_not_colorized @support.requires_subprocess() def test_sys_tracebacklimit(self): code = """if 1: diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index a712ed10f022d67..362a3f9c4a01d12 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -7,6 +7,7 @@ from test.support import verbose, cpython_only, os_helper from test.support.import_helper import import_module from test.support.script_helper import assert_python_ok, assert_python_failure +from test.support import force_not_colorized import random import sys @@ -1793,6 +1794,7 @@ def setUp(self): restore_default_excepthook(self) super().setUp() + @force_not_colorized def test_excepthook(self): with support.captured_output("stderr") as stderr: thread = ThreadRunFail(name="excepthook thread") @@ -1806,6 +1808,7 @@ def test_excepthook(self): self.assertIn('ValueError: run failed', stderr) @support.cpython_only + @force_not_colorized def test_excepthook_thread_None(self): # threading.excepthook called with thread=None: log the thread # identifier in this case. diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index dd9b1850adf0860..19611937fc278b0 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -21,6 +21,7 @@ from test.support.os_helper import TESTFN, unlink from test.support.script_helper import assert_python_ok, assert_python_failure from test.support.import_helper import forget +from test.support import force_not_colorized import json import textwrap @@ -39,6 +40,13 @@ LEVENSHTEIN_DATA_FILE = Path(__file__).parent / 'levenshtein_examples.json' +ORIGINAL_CAN_COLORIZE = traceback._can_colorize + +def setUpModule(): + traceback._can_colorize = lambda: False + +def tearDownModule(): + traceback._can_colorize = ORIGINAL_CAN_COLORIZE class TracebackCases(unittest.TestCase): # For now, a very minimal set of tests. I want to be sure that @@ -124,6 +132,7 @@ def test_nocaret(self): self.assertEqual(len(err), 3) self.assertEqual(err[1].strip(), "bad syntax") + @force_not_colorized def test_no_caret_with_no_debug_ranges_flag(self): # Make sure that if `-X no_debug_ranges` is used, there are no carets # in the traceback. @@ -401,7 +410,7 @@ def do_test(firstlines, message, charset, lineno): """.format(firstlines, message)) process = subprocess.Popen([sys.executable, TESTFN], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env={}) stdout, stderr = process.communicate() stdout = stdout.decode(output_encoding).splitlines() finally: @@ -4354,13 +4363,18 @@ def foo(): f'{boldm}ZeroDivisionError{reset}: {magenta}division by zero{reset}'] self.assertEqual(actual, expected) + @force_not_colorized def test_colorized_detection_checks_for_environment_variables(self): if sys.platform == "win32": virtual_patching = unittest.mock.patch("nt._supports_virtual_terminal", return_value=True) else: virtual_patching = contextlib.nullcontext() with virtual_patching: - with unittest.mock.patch("os.isatty") as isatty_mock: + + flags = unittest.mock.MagicMock(ignore_environment=False) + with (unittest.mock.patch("os.isatty") as isatty_mock, + unittest.mock.patch("sys.flags", flags), + unittest.mock.patch("traceback._can_colorize", ORIGINAL_CAN_COLORIZE)): isatty_mock.return_value = True with unittest.mock.patch("os.environ", {'TERM': 'dumb'}): self.assertEqual(traceback._can_colorize(), False) @@ -4379,7 +4393,8 @@ def test_colorized_detection_checks_for_environment_variables(self): with unittest.mock.patch("os.environ", {'FORCE_COLOR': '1', "PYTHON_COLORS": '0'}): self.assertEqual(traceback._can_colorize(), False) isatty_mock.return_value = False - self.assertEqual(traceback._can_colorize(), False) + with unittest.mock.patch("os.environ", {}): + self.assertEqual(traceback._can_colorize(), False) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index bea124521032d14..f685430a7d36ade 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -942,7 +942,7 @@ def check_env_var_invalid(self, nframe): with support.SuppressCrashReport(): ok, stdout, stderr = assert_python_failure( '-c', 'pass', - PYTHONTRACEMALLOC=str(nframe)) + PYTHONTRACEMALLOC=str(nframe), __cleanenv=True) if b'ValueError: the number of frames must be in range' in stderr: return diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index b768631846e2408..4416ed0f3ed3ef9 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -12,6 +12,7 @@ from test.support import import_helper from test.support import os_helper from test.support import warnings_helper +from test.support import force_not_colorized from test.support.script_helper import assert_python_ok, assert_python_failure from test.test_warnings.data import package_helper @@ -1239,6 +1240,7 @@ def test_comma_separated_warnings(self): self.assertEqual(stdout, b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']") + @force_not_colorized def test_envvar_and_command_line(self): rc, stdout, stderr = assert_python_ok("-Wignore::UnicodeWarning", "-c", "import sys; sys.stdout.write(str(sys.warnoptions))", @@ -1247,6 +1249,7 @@ def test_envvar_and_command_line(self): self.assertEqual(stdout, b"['ignore::DeprecationWarning', 'ignore::UnicodeWarning']") + @force_not_colorized def test_conflicting_envvar_and_command_line(self): rc, stdout, stderr = assert_python_failure("-Werror::DeprecationWarning", "-c", "import sys, warnings; sys.stdout.write(str(sys.warnoptions)); " diff --git a/Lib/traceback.py b/Lib/traceback.py index 054def57c214827..fccec0c71c3695d 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -141,24 +141,30 @@ def _can_colorize(): return False except (ImportError, AttributeError): return False - - if os.environ.get("PYTHON_COLORS") == "0": - return False - if os.environ.get("PYTHON_COLORS") == "1": - return True - if "NO_COLOR" in os.environ: - return False + if not sys.flags.ignore_environment: + if os.environ.get("PYTHON_COLORS") == "0": + return False + if os.environ.get("PYTHON_COLORS") == "1": + return True + if "NO_COLOR" in os.environ: + return False if not _COLORIZE: return False - if "FORCE_COLOR" in os.environ: - return True - if os.environ.get("TERM") == "dumb": + if not sys.flags.ignore_environment: + if "FORCE_COLOR" in os.environ: + return True + if os.environ.get("TERM") == "dumb": + return False + + if not hasattr(sys.stderr, "fileno"): return False + try: return os.isatty(sys.stderr.fileno()) except io.UnsupportedOperation: return sys.stderr.isatty() + def _print_exception_bltin(exc, /): file = sys.stderr if sys.stderr is not None else sys.__stderr__ colorize = _can_colorize() From 85ec1c2dc67c2a506e847dbe2c3c740e81c3ab9b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 Apr 2024 15:23:45 -0600 Subject: [PATCH 123/127] gh-117953: Fix Refleaks Introduced by gh-118194 (gh-118250) A couple of refleaks slipped through in gh-118194. This takes care of them. (AKA _Py_ext_module_loader_info_init() does not steal references.) --- Python/importdl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Python/importdl.c b/Python/importdl.c index 65370249493325e..f2ad95fbbb507da 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -169,9 +169,13 @@ _Py_ext_module_loader_info_init_from_spec( } PyObject *filename = PyObject_GetAttrString(spec, "origin"); if (filename == NULL) { + Py_DECREF(name); return -1; } - return _Py_ext_module_loader_info_init(p_info, name, filename); + int err = _Py_ext_module_loader_info_init(p_info, name, filename); + Py_DECREF(name); + Py_DECREF(filename); + return err; } From 93b7ed7c6b1494f41818fa571b1843ca3dfe1bd1 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 25 Apr 2024 00:39:54 +0300 Subject: [PATCH 124/127] gh-108191: Add support of positional argument in SimpleNamespace constructor (GH-108195) SimpleNamespace({'a': 1, 'b': 2}) and SimpleNamespace([('a', 1), ('b', 2)]) are now the same as SimpleNamespace(a=1, b=2). --- Doc/library/types.rst | 22 ++++++-- Doc/whatsnew/3.13.rst | 8 +++ Lib/test/test_types.py | 55 ++++++++++++++----- ...-08-21-10-34-43.gh-issue-108191.GZM3mv.rst | 3 + Objects/namespaceobject.c | 24 +++++++- 5 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-08-21-10-34-43.gh-issue-108191.GZM3mv.rst diff --git a/Doc/library/types.rst b/Doc/library/types.rst index b856544e44207c5..89bc0a600c0af8f 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -481,14 +481,25 @@ Additional Utility Classes and Functions A simple :class:`object` subclass that provides attribute access to its namespace, as well as a meaningful repr. - Unlike :class:`object`, with ``SimpleNamespace`` you can add and remove - attributes. If a ``SimpleNamespace`` object is initialized with keyword - arguments, those are directly added to the underlying namespace. + Unlike :class:`object`, with :class:`!SimpleNamespace` you can add and remove + attributes. + + :py:class:`SimpleNamespace` objects may be initialized + in the same way as :class:`dict`: either with keyword arguments, + with a single positional argument, or with both. + When initialized with keyword arguments, + those are directly added to the underlying namespace. + Alternatively, when initialized with a positional argument, + the underlying namespace will be updated with key-value pairs + from that argument (either a mapping object or + an :term:`iterable` object producing key-value pairs). + All such keys must be strings. The type is roughly equivalent to the following code:: class SimpleNamespace: - def __init__(self, /, **kwargs): + def __init__(self, mapping_or_iterable=(), /, **kwargs): + self.__dict__.update(mapping_or_iterable) self.__dict__.update(kwargs) def __repr__(self): @@ -512,6 +523,9 @@ Additional Utility Classes and Functions Attribute order in the repr changed from alphabetical to insertion (like ``dict``). + .. versionchanged:: 3.13 + Added support for an optional positional argument. + .. function:: DynamicClassAttribute(fget=None, fset=None, fdel=None, doc=None) Route attribute access on a class to __getattr__. diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 89694afdfa3fece..ad107aad5db3bd7 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -804,6 +804,14 @@ traceback ``True``) to indicate whether ``exc_type`` should be saved. (Contributed by Irit Katriel in :gh:`112332`.) +types +----- + +* :class:`~types.SimpleNamespace` constructor now allows specifying initial + values of attributes as a positional argument which must be a mapping or + an iterable of key-value pairs. + (Contributed by Serhiy Storchaka in :gh:`108191`.) + typing ------ diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 16985122bc0219d..fbca198aab5180f 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -2,7 +2,7 @@ from test.support import run_with_locale, cpython_only, MISSING_C_DOCSTRINGS import collections.abc -from collections import namedtuple +from collections import namedtuple, UserDict import copy import _datetime import gc @@ -1755,21 +1755,50 @@ class Model(metaclass=ModelBase): class SimpleNamespaceTests(unittest.TestCase): def test_constructor(self): - ns1 = types.SimpleNamespace() - ns2 = types.SimpleNamespace(x=1, y=2) - ns3 = types.SimpleNamespace(**dict(x=1, y=2)) + def check(ns, expected): + self.assertEqual(len(ns.__dict__), len(expected)) + self.assertEqual(vars(ns), expected) + # check order + self.assertEqual(list(vars(ns).items()), list(expected.items())) + for name in expected: + self.assertEqual(getattr(ns, name), expected[name]) + + check(types.SimpleNamespace(), {}) + check(types.SimpleNamespace(x=1, y=2), {'x': 1, 'y': 2}) + check(types.SimpleNamespace(**dict(x=1, y=2)), {'x': 1, 'y': 2}) + check(types.SimpleNamespace({'x': 1, 'y': 2}, x=4, z=3), + {'x': 4, 'y': 2, 'z': 3}) + check(types.SimpleNamespace([['x', 1], ['y', 2]], x=4, z=3), + {'x': 4, 'y': 2, 'z': 3}) + check(types.SimpleNamespace(UserDict({'x': 1, 'y': 2}), x=4, z=3), + {'x': 4, 'y': 2, 'z': 3}) + check(types.SimpleNamespace({'x': 1, 'y': 2}), {'x': 1, 'y': 2}) + check(types.SimpleNamespace([['x', 1], ['y', 2]]), {'x': 1, 'y': 2}) + check(types.SimpleNamespace([], x=4, z=3), {'x': 4, 'z': 3}) + check(types.SimpleNamespace({}, x=4, z=3), {'x': 4, 'z': 3}) + check(types.SimpleNamespace([]), {}) + check(types.SimpleNamespace({}), {}) with self.assertRaises(TypeError): - types.SimpleNamespace(1, 2, 3) + types.SimpleNamespace([], []) # too many positional arguments with self.assertRaises(TypeError): - types.SimpleNamespace(**{1: 2}) - - self.assertEqual(len(ns1.__dict__), 0) - self.assertEqual(vars(ns1), {}) - self.assertEqual(len(ns2.__dict__), 2) - self.assertEqual(vars(ns2), {'y': 2, 'x': 1}) - self.assertEqual(len(ns3.__dict__), 2) - self.assertEqual(vars(ns3), {'y': 2, 'x': 1}) + types.SimpleNamespace(1) # not a mapping or iterable + with self.assertRaises(TypeError): + types.SimpleNamespace([1]) # non-iterable + with self.assertRaises(ValueError): + types.SimpleNamespace([['x']]) # not a pair + with self.assertRaises(ValueError): + types.SimpleNamespace([['x', 'y', 'z']]) + with self.assertRaises(TypeError): + types.SimpleNamespace(**{1: 2}) # non-string key + with self.assertRaises(TypeError): + types.SimpleNamespace({1: 2}) + with self.assertRaises(TypeError): + types.SimpleNamespace([[1, 2]]) + with self.assertRaises(TypeError): + types.SimpleNamespace(UserDict({1: 2})) + with self.assertRaises(TypeError): + types.SimpleNamespace([[[], 2]]) # non-hashable key def test_unbound(self): ns1 = vars(types.SimpleNamespace()) diff --git a/Misc/NEWS.d/next/Library/2023-08-21-10-34-43.gh-issue-108191.GZM3mv.rst b/Misc/NEWS.d/next/Library/2023-08-21-10-34-43.gh-issue-108191.GZM3mv.rst new file mode 100644 index 000000000000000..da4ce5742549e69 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-21-10-34-43.gh-issue-108191.GZM3mv.rst @@ -0,0 +1,3 @@ +The :class:`types.SimpleNamespace` now accepts an optional positional +argument which specifies initial values of attributes as a dict or an +iterable of key-value pairs. diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c index b2a224b9b2bda50..5b7547103a2b3fc 100644 --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -43,10 +43,28 @@ namespace_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static int namespace_init(_PyNamespaceObject *ns, PyObject *args, PyObject *kwds) { - if (PyTuple_GET_SIZE(args) != 0) { - PyErr_Format(PyExc_TypeError, "no positional arguments expected"); + PyObject *arg = NULL; + if (!PyArg_UnpackTuple(args, _PyType_Name(Py_TYPE(ns)), 0, 1, &arg)) { return -1; } + if (arg != NULL) { + PyObject *dict; + if (PyDict_CheckExact(arg)) { + dict = Py_NewRef(arg); + } + else { + dict = PyObject_CallOneArg((PyObject *)&PyDict_Type, arg); + if (dict == NULL) { + return -1; + } + } + int err = (!PyArg_ValidateKeywordArguments(dict) || + PyDict_Update(ns->ns_dict, dict) < 0); + Py_DECREF(dict); + if (err) { + return -1; + } + } if (kwds == NULL) { return 0; } @@ -227,7 +245,7 @@ static PyMethodDef namespace_methods[] = { PyDoc_STRVAR(namespace_doc, -"SimpleNamespace(**kwargs)\n\ +"SimpleNamespace(mapping_or_iterable=(), /, **kwargs)\n\ --\n\n\ A simple attribute-based namespace."); From 8942bf41dac49149a77f5396ab086d340de9c009 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Wed, 24 Apr 2024 14:43:50 -0700 Subject: [PATCH 125/127] GH-118246: Exclude test_pathlib and test_posixpath from emulated JIT CI (GH-118247) --- .github/workflows/jit.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 490005b7170e95b..b37eb7279559099 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -76,13 +76,13 @@ jobs: runner: ubuntu-latest compiler: gcc # These fail because of emulation, not because of the JIT: - exclude: test_unix_events test_init test_process_pool test_shutdown test_multiprocessing_fork test_cmd_line test_faulthandler test_os test_perf_profiler test_posix test_signal test_socket test_subprocess test_threading test_venv test_external_inspection + exclude: test_pathlib test_posixpath test_unix_events test_init test_process_pool test_shutdown test_multiprocessing_fork test_cmd_line test_faulthandler test_os test_perf_profiler test_posix test_signal test_socket test_subprocess test_threading test_venv test_external_inspection - target: aarch64-unknown-linux-gnu/clang architecture: aarch64 runner: ubuntu-latest compiler: clang # These fail because of emulation, not because of the JIT: - exclude: test_unix_events test_init test_process_pool test_shutdown test_multiprocessing_fork test_cmd_line test_faulthandler test_os test_perf_profiler test_posix test_signal test_socket test_subprocess test_threading test_venv test_external_inspection + exclude: test_pathlib test_posixpath test_unix_events test_init test_process_pool test_shutdown test_multiprocessing_fork test_cmd_line test_faulthandler test_os test_perf_profiler test_posix test_signal test_socket test_subprocess test_threading test_venv test_external_inspection env: CC: ${{ matrix.compiler }} steps: From 4b10e209c76f9f36f8ae2e4d713b3a01591c1856 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Wed, 24 Apr 2024 23:00:55 +0100 Subject: [PATCH 126/127] gh-117786: Fix venv created from Windows Store install by restoring __PYVENV_LAUNCHER__ smuggling (GH-117814) --- Lib/test/test_embed.py | 3 +++ ...-04-12-13-18-42.gh-issue-117786.LpI01s.rst | 2 ++ Modules/getpath.py | 24 +++++++++++-------- PC/venvlauncher.c | 4 ++-- 4 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index ec928f935655f90..d94c63a13b8ea40 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -747,6 +747,9 @@ def check_config(self, configs, expected): if value is self.IGNORE_CONFIG: config.pop(key, None) del expected[key] + # Resolve bool/int mismatches to reduce noise in diffs + if isinstance(value, (bool, int)) and isinstance(config.get(key), (bool, int)): + expected[key] = type(config[key])(expected[key]) self.assertEqual(config, expected) def check_global_config(self, configs): diff --git a/Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst b/Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst new file mode 100644 index 000000000000000..a4cd9a9adb3e594 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2024-04-12-13-18-42.gh-issue-117786.LpI01s.rst @@ -0,0 +1,2 @@ +Fixes virtual environments not correctly launching when created from a Store +install. diff --git a/Modules/getpath.py b/Modules/getpath.py index 1410ffdbed8c70c..bc7053224aaf161 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -310,7 +310,10 @@ def search_up(prefix, *landmarks, test=isfile): # and should not affect base_executable. base_executable = f"{dirname(library)}/bin/python{VERSION_MAJOR}.{VERSION_MINOR}" else: - base_executable = executable + # Use the real executable as our base, or argv[0] otherwise + # (on Windows, argv[0] is likely to be ENV___PYVENV_LAUNCHER__; on + # other platforms, real_executable is likely to be empty) + base_executable = real_executable or executable if not real_executable: real_executable = base_executable @@ -408,13 +411,14 @@ def search_up(prefix, *landmarks, test=isfile): if not real_executable: real_executable = base_executable -try: - real_executable = realpath(real_executable) -except OSError as ex: - # Only warn if the file actually exists and was unresolvable - # Otherwise users who specify a fake executable may get spurious warnings. - if isfile(real_executable): - warn(f'Failed to find real location of {base_executable}') +if real_executable: + try: + real_executable = realpath(real_executable) + except OSError as ex: + # Only warn if the file actually exists and was unresolvable + # Otherwise users who specify a fake executable may get spurious warnings. + if isfile(real_executable): + warn(f'Failed to find real location of {base_executable}') if not executable_dir and os_name == 'darwin' and library: # QUIRK: macOS checks adjacent to its library early @@ -427,12 +431,12 @@ def search_up(prefix, *landmarks, test=isfile): # If we do not have the executable's directory, we can calculate it. # This is the directory used to find prefix/exec_prefix if necessary. -if not executable_dir: +if not executable_dir and real_executable: executable_dir = real_executable_dir = dirname(real_executable) # If we do not have the real executable's directory, we calculate it. # This is the directory used to detect build layouts. -if not real_executable_dir: +if not real_executable_dir and real_executable: real_executable_dir = dirname(real_executable) # ****************************************************************************** diff --git a/PC/venvlauncher.c b/PC/venvlauncher.c index fe97d32e93b5f69..b1c8d0763d8c76a 100644 --- a/PC/venvlauncher.c +++ b/PC/venvlauncher.c @@ -484,8 +484,8 @@ process(int argc, wchar_t ** argv) // We do not update argv[0] to point at the target runtime, and so we do not // pass through our original argv[0] in an environment variable. - //exitCode = smuggle_path(); - //if (exitCode) return exitCode; + exitCode = smuggle_path(); + if (exitCode) return exitCode; exitCode = launch(home_path, GetCommandLineW()); return exitCode; From 546cbcfa0eeeb533950bd49e30423f3d3bbd5ebe Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 25 Apr 2024 08:00:42 +0300 Subject: [PATCH 127/127] gh-117968: Make the test for closed file more safe in the C API tests (GH-118230) The behavior of fileno() after fclose() is undefined, but it is the only practical way to check whether the file was closed. Only test this on the known platforms (Linux, Windows, macOS), where we already tested that it works. --- Modules/_testcapi/run.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/_testcapi/run.c b/Modules/_testcapi/run.c index fa3251c4b5b3100..4fd98b82d762ff4 100644 --- a/Modules/_testcapi/run.c +++ b/Modules/_testcapi/run.c @@ -74,8 +74,10 @@ run_fileexflags(PyObject *mod, PyObject *pos_args) result = PyRun_FileExFlags(fp, filename, start, globals, locals, closeit, pflags); -#if !defined(__wasi__) - /* The behavior of fileno() after fclose() is undefined. */ +#if defined(__linux__) || defined(MS_WINDOWS) || defined(__APPLE__) + /* The behavior of fileno() after fclose() is undefined, but it is + * the only practical way to check whether the file was closed. + * Only test this on the known platforms. */ if (closeit && result && fileno(fp) >= 0) { PyErr_SetString(PyExc_AssertionError, "File was not closed after excution"); Py_DECREF(result);