diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63417972ba6bec..a33e347996342a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -154,7 +154,7 @@ jobs: Windows ${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }} needs: build-context - if: fromJSON(needs.build-context.outputs.run-tests) + if: fromJSON(needs.build-context.outputs.run-windows-tests) strategy: fail-fast: false matrix: @@ -621,6 +621,7 @@ jobs: - build_wasi - build_windows - build_windows_msi + - cross-build-linux - test_hypothesis - build_asan - build_tsan @@ -654,10 +655,17 @@ jobs: build_ubuntu, build_ubuntu_ssltests, build_wasi, - build_windows, build_asan, build_tsan, test_hypothesis, + cross-build-linux, + ' + || '' + }} + ${{ + !fromJSON(needs.build-context.outputs.run-windows-tests) + && ' + build_windows, ' || '' }} diff --git a/.github/workflows/reusable-context.yml b/.github/workflows/reusable-context.yml index fa4df6f29711db..73e036a146f5d4 100644 --- a/.github/workflows/reusable-context.yml +++ b/.github/workflows/reusable-context.yml @@ -26,6 +26,9 @@ on: # yamllint disable-line rule:truthy run-tests: description: Whether to run the regular tests value: ${{ jobs.compute-changes.outputs.run-tests }} # bool + run-windows-tests: + description: Whether to run the Windows tests + value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool run-windows-msi: description: Whether to run the MSI installer smoke tests value: ${{ jobs.compute-changes.outputs.run-windows-msi }} # bool @@ -44,6 +47,7 @@ jobs: run-docs: ${{ steps.changes.outputs.run-docs }} run-tests: ${{ steps.changes.outputs.run-tests }} run-windows-msi: ${{ steps.changes.outputs.run-windows-msi }} + run-windows-tests: ${{ steps.changes.outputs.run-windows-tests }} steps: - name: Set up Python uses: actions/setup-python@v5 diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index 4c2516c517b3a9..119c60a15732bf 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -41,6 +41,7 @@ jobs: - aarch64-apple-darwin/clang - x86_64-unknown-linux-gnu/gcc - aarch64-unknown-linux-gnu/gcc + - free-threading llvm: - 19 include: @@ -65,6 +66,9 @@ jobs: - target: aarch64-unknown-linux-gnu/gcc architecture: aarch64 runner: ubuntu-22.04-arm + - target: free-threading + architecture: x86_64 + runner: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: @@ -105,7 +109,7 @@ jobs: ./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - name: Native Linux (release) - if: runner.os == 'Linux' + if: runner.os == 'Linux' && matrix.target != 'free-threading' run: | sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" @@ -113,3 +117,12 @@ jobs: make all --jobs 4 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 + - name: Native Linux with free-threading (release) + if: matrix.target == 'free-threading' + run: | + sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} + export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" + CC=clang-19 ./configure --with-tail-call-interp --disable-gil + make all --jobs 4 + ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 + diff --git a/Doc/c-api/bytearray.rst b/Doc/c-api/bytearray.rst index 15295096a710c8..e2b22ec3c794ae 100644 --- a/Doc/c-api/bytearray.rst +++ b/Doc/c-api/bytearray.rst @@ -76,7 +76,7 @@ Direct API functions Resize the internal buffer of *bytearray* to *len*. Failure is a ``-1`` return with an exception set. - .. versionchanged:: next + .. versionchanged:: 3.14 A negative *len* will now result in an exception being set and -1 returned. diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index f90af6a9ce7c26..9197f704fab344 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -604,7 +604,7 @@ Process-wide parameters 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. + :c:expr:`wchar_t*` string. .. deprecated-removed:: 3.11 3.15 @@ -852,7 +852,7 @@ Process-wide parameters directory (``"."``). Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_*` string. + :c:expr:`wchar_t*` string. See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` members of the :ref:`Python Initialization Configuration `. @@ -888,7 +888,7 @@ Process-wide parameters :option:`-I`. Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_*` string. + :c:expr:`wchar_t*` string. See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv` members of the :ref:`Python Initialization Configuration `. @@ -914,7 +914,7 @@ Process-wide parameters this storage. Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a - :c:expr:`wchar_*` string. + :c:expr:`wchar_t*` string. .. deprecated-removed:: 3.11 3.15 diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 1ba5942c63601d..bef3a79ccd0e21 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -623,7 +623,7 @@ Object Protocol Objects that are immortal in one CPython version are not guaranteed to be immortal in another. - .. versionadded:: next + .. versionadded:: 3.14 .. c:function:: int PyUnstable_TryIncRef(PyObject *obj) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 69c518d8e64cbc..b41e5767e59c5f 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1830,7 +1830,7 @@ and :c:data:`PyType_Type` effectively act as defaults.) dictionary, so it is may be more efficient to call :c:func:`PyObject_GetAttr` when accessing an attribute on the object. - It is an error to set both the :c:macro:`Py_TPFLAGS_MANAGED_WEAKREF` bit and + It is an error to set both the :c:macro:`Py_TPFLAGS_MANAGED_DICT` bit and :c:member:`~PyTypeObject.tp_dictoffset`. **Inheritance:** diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index 94110d48ed7d85..8f383cd6c4015f 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -256,13 +256,8 @@ the Python configuration. .. c:function:: int Py_UNICODE_ISPRINTABLE(Py_UCS4 ch) - Return ``1`` or ``0`` depending on whether *ch* is a printable character. - Nonprintable characters are those characters defined in the Unicode character - database as "Other" or "Separator", excepting the ASCII space (0x20) which is - considered printable. (Note that printable characters in this context are - those which should not be escaped when :func:`repr` is invoked on a string. - It has no bearing on the handling of strings written to :data:`sys.stdout` or - :data:`sys.stderr`.) + Return ``1`` or ``0`` depending on whether *ch* is a printable character, + in the sense of :meth:`str.isprintable`. These APIs can be used for fast direct character conversions: @@ -1352,6 +1347,13 @@ the user settings on the machine running the codec. in *consumed*. +.. c:function:: PyObject* PyUnicode_DecodeCodePageStateful(int code_page, const char *str, \ + Py_ssize_t size, const char *errors, Py_ssize_t *consumed) + + Similar to :c:func:`PyUnicode_DecodeMBCSStateful`, except uses the code page + specified by *code_page*. + + .. c:function:: PyObject* PyUnicode_AsMBCSString(PyObject *unicode) Encode a Unicode object using MBCS and return the result as Python bytes diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index d709d2d91b0eb0..a483c57cb2ce06 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -2636,6 +2636,13 @@ PyUnicode_DecodeMBCSStateful:Py_ssize_t:size:: PyUnicode_DecodeMBCSStateful:const char*:errors:: PyUnicode_DecodeMBCSStateful:Py_ssize_t*:consumed:: +PyUnicode_DecodeCodePageStateful:PyObject*::+1: +PyUnicode_DecodeCodePageStateful:int:code_page:: +PyUnicode_DecodeCodePageStateful:const char*:s:: +PyUnicode_DecodeCodePageStateful:Py_ssize_t:size:: +PyUnicode_DecodeCodePageStateful:const char*:errors:: +PyUnicode_DecodeCodePageStateful:Py_ssize_t*:consumed:: + PyUnicode_EncodeCodePage:PyObject*::+1: PyUnicode_EncodeCodePage:int:code_page:: PyUnicode_EncodeCodePage:PyObject*:unicode:0: diff --git a/Doc/deprecations/pending-removal-in-3.15.rst b/Doc/deprecations/pending-removal-in-3.15.rst index 390bbff2835cf8..92297e1518004d 100644 --- a/Doc/deprecations/pending-removal-in-3.15.rst +++ b/Doc/deprecations/pending-removal-in-3.15.rst @@ -29,6 +29,10 @@ Pending removal in Python 3.15 * The :option:`!--cgi` flag to the :program:`python -m http.server` command-line interface has been deprecated since Python 3.13. +* :mod:`importlib`: + + * ``load_module()`` method: use ``exec_module()`` instead. + * :class:`locale`: * The :func:`~locale.getdefaultlocale` function @@ -92,3 +96,9 @@ Pending removal in Python 3.15 and :meth:`~wave.Wave_read.getmarkers` methods of the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes have been deprecated since Python 3.13. + +* :mod:`zipimport`: + + * :meth:`~zipimport.zipimporter.load_module` has been deprecated since + Python 3.10. Use :meth:`~zipimport.zipimporter.exec_module` instead. + (Contributed by Jiahao Li in :gh:`125746`.) diff --git a/Doc/deprecations/pending-removal-in-future.rst b/Doc/deprecations/pending-removal-in-future.rst index ea7581bf16bd34..42dce518717a85 100644 --- a/Doc/deprecations/pending-removal-in-future.rst +++ b/Doc/deprecations/pending-removal-in-future.rst @@ -63,7 +63,6 @@ although there is currently no date scheduled for their removal. * :mod:`importlib`: - * ``load_module()`` method: use ``exec_module()`` instead. * :func:`~importlib.util.cache_from_source` *debug_override* parameter is deprecated: use the *optimization* parameter instead. @@ -152,6 +151,3 @@ although there is currently no date scheduled for their removal. :class:`~xml.etree.ElementTree.Element` is deprecated. In a future release it will always return ``True``. Prefer explicit ``len(elem)`` or ``elem is not None`` tests instead. - -* :meth:`zipimport.zipimporter.load_module` is deprecated: - use :meth:`~zipimport.zipimporter.exec_module` instead. diff --git a/Doc/library/asyncio-graph.rst b/Doc/library/asyncio-graph.rst index 814bfe6e269bf9..5f642a32bf75c2 100644 --- a/Doc/library/asyncio-graph.rst +++ b/Doc/library/asyncio-graph.rst @@ -17,7 +17,7 @@ a suspended *future*. These utilities and the underlying machinery can be used from within a Python program or by external profilers and debuggers. -.. versionadded:: next +.. versionadded:: 3.14 .. function:: print_call_graph(future=None, /, *, file=None, depth=1, limit=None) diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst index 2b1fb9fdd29cd8..3e3b30c724c631 100644 --- a/Doc/library/contextvars.rst +++ b/Doc/library/contextvars.rst @@ -101,6 +101,21 @@ Context Variables the value of the variable to what it was before the corresponding *set*. + The token supports :ref:`context manager protocol ` + to restore the corresponding context variable value at the exit from + :keyword:`with` block:: + + var = ContextVar('var', default='default value') + + with var.set('new value'): + assert var.get() == 'new value' + + assert var.get() == 'default value' + + .. versionadded:: next + + Added support for usage as a context manager. + .. attribute:: Token.var A read-only property. Points to the :class:`ContextVar` object diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index cb02fd33a6e741..0d9cc96ebc5e15 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -2117,7 +2117,7 @@ Utility functions executable file. It may be an empty string. .. availability:: Windows, macOS, iOS, glibc, BSD libc, musl - .. versionadded:: next + .. versionadded:: 3.14 .. function:: FormatError([code]) diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 6c659ea52ad821..36221c026d6d4b 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -455,7 +455,7 @@ The :mod:`!dbm.dumb` module defines the following: .. method:: dumbdbm.sync() Synchronize the on-disk directory and data files. This method is called - by the :meth:`Shelve.sync` method. + by the :meth:`shelve.Shelf.sync` method. .. method:: dumbdbm.close() diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst index 2c5a1f1fbc1213..9f198aebcb66b0 100644 --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -392,7 +392,7 @@ An :class:`IMAP4` instance has the following methods: iteration, and public method to remain stable, but should not subclass, instantiate, compare, or otherwise directly reference the class. - .. versionadded:: next + .. versionadded:: 3.14 .. method:: IMAP4.list([directory[, pattern]]) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 245807e55ec936..00f1217d668222 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -370,7 +370,7 @@ ABC hierarchy:: :exc:`NotImplementedError`. Functionality provided when :meth:`exec_module` is available. - .. deprecated:: 3.4 + .. deprecated-removed:: 3.4 3.15 The recommended API for loading a module is :meth:`exec_module` (and :meth:`create_module`). Loaders should implement it instead of :meth:`load_module`. The import machinery takes care of all the @@ -474,7 +474,7 @@ ABC hierarchy:: Implementation of :meth:`Loader.load_module`. - .. deprecated:: 3.4 + .. deprecated-removed:: 3.4 3.15 use :meth:`exec_module` instead. @@ -521,7 +521,7 @@ ABC hierarchy:: Calls super's ``load_module()``. - .. deprecated:: 3.4 + .. deprecated-removed:: 3.4 3.15 Use :meth:`Loader.exec_module` instead. .. abstractmethod:: get_filename(fullname) @@ -610,7 +610,7 @@ ABC hierarchy:: Concrete implementation of :meth:`Loader.load_module`. - .. deprecated:: 3.4 + .. deprecated-removed:: 3.4 3.15 Use :meth:`exec_module` instead. .. method:: get_source(fullname) @@ -1020,7 +1020,7 @@ find and load modules. Concrete implementation of :meth:`importlib.abc.Loader.load_module` where specifying the name of the module to load is optional. - .. deprecated:: 3.6 + .. deprecated-removed:: 3.6 3.15 Use :meth:`importlib.abc.Loader.exec_module` instead. @@ -1063,7 +1063,7 @@ find and load modules. Concrete implementation of :meth:`importlib.abc.Loader.load_module` where specifying the name of the module to load is optional. - .. deprecated:: 3.6 + .. deprecated-removed:: 3.6 3.15 Use :meth:`importlib.abc.Loader.exec_module` instead. diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 544efed1a76b96..e8d1176f477866 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -316,7 +316,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes): Add ``__builtins__`` attribute to functions. -.. versionchanged:: next +.. versionchanged:: 3.14 Add ``f_generator`` attribute to frames. diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 7d3596622862ea..8dd944d72d5c13 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1683,7 +1683,7 @@ or `the MSDN `_ on Windo :meth:`io.BufferedIOBase.readinto`, :meth:`io.BufferedIOBase.read`, or :meth:`io.TextIOBase.read` - .. versionadded:: next + .. versionadded:: 3.14 .. function:: sendfile(out_fd, in_fd, offset, count) diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst index 075b974501e3da..ad96be755b8158 100644 --- a/Doc/library/plistlib.rst +++ b/Doc/library/plistlib.rst @@ -99,7 +99,7 @@ This module defines the following functions: .. function:: dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False, aware_datetime=False) - Write *value* to a plist file. *Fp* should be a writable, binary + Write *value* to a plist file. *fp* should be a writable, binary file object. The *fmt* argument specifies the format of the plist file and can be diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst index 06800c4588b663..1819f708890c09 100644 --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -529,7 +529,7 @@ file then shutil will silently fallback on using less efficient .. versionchanged:: 3.14 Solaris now uses :func:`os.sendfile`. -.. versionchanged:: next +.. versionchanged:: 3.14 Copy-on-write or server-side copy may be used internally via :func:`os.copy_file_range` on supported Linux filesystems. diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 7cd530a5fd6438..c5f8516f768a68 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -524,7 +524,7 @@ An :class:`SMTP` instance has the following methods: :mailheader:`Bcc` or :mailheader:`Resent-Bcc` headers that may appear in *msg*. If any of the addresses in *from_addr* and *to_addrs* contain non-ASCII characters and the server does not advertise ``SMTPUTF8`` support, - an :exc:`SMTPNotSupported` error is raised. Otherwise the ``Message`` is + an :exc:`SMTPNotSupportedError` is raised. Otherwise the ``Message`` is serialized with a clone of its :mod:`~email.policy` with the :attr:`~email.policy.EmailPolicy.utf8` attribute set to ``True``, and ``SMTPUTF8`` and ``BODY=8BITMIME`` are added to *mail_options*. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 4a15e27f82a160..143fc6508ebc42 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2012,13 +2012,19 @@ expression support in the :mod:`re` module). .. method:: str.isprintable() - Return ``True`` if all characters in the string are printable or the string is - empty, ``False`` otherwise. Nonprintable characters are those characters defined - in the Unicode character database as "Other" or "Separator", excepting the - ASCII space (0x20) which is considered printable. (Note that printable - characters in this context are those which should not be escaped when - :func:`repr` is invoked on a string. It has no bearing on the handling of - strings written to :data:`sys.stdout` or :data:`sys.stderr`.) + Return true if all characters in the string are printable, false if it + contains at least one non-printable character. + + Here "printable" means the character is suitable for :func:`repr` to use in + its output; "non-printable" means that :func:`repr` on built-in types will + hex-escape the character. It has no bearing on the handling of strings + written to :data:`sys.stdout` or :data:`sys.stderr`. + + The printable characters are those which in the Unicode character database + (see :mod:`unicodedata`) have a general category in group Letter, Mark, + Number, Punctuation, or Symbol (L, M, N, P, or S); plus the ASCII space 0x20. + Nonprintable characters are those in group Separator or Other (Z or C), + except the ASCII space. .. method:: str.isspace() @@ -2871,7 +2877,7 @@ objects. >>> (grow, len(grow)) (bytearray(b'abc\x00\x00'), 5) - .. versionadded:: next + .. versionadded:: 3.14 Since bytearray objects are sequences of integers (akin to a list), for a bytearray object *b*, ``b[0]`` will be an integer, while ``b[0:1]`` will be diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 855237e0984972..eaa8aa711db173 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1280,7 +1280,7 @@ always available. Unless explicitly noted otherwise, all variables are read-only to this function) are not guaranteed to be immortal in future versions, and vice versa for mortal objects. - .. versionadded:: next + .. versionadded:: 3.14 .. impl-detail:: diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst index b0ee3fc56ad735..7e05144bfb34cb 100644 --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -257,6 +257,11 @@ Module-Level Functions .. versionadded:: 3.5 + .. versionchanged:: 3.14 + This function previously returned a generator that would walk the stack + when first iterated over. The generator returned now is the state of the + stack when ``walk_stack`` is called. + .. function:: walk_tb(tb) Walk a traceback following :attr:`~traceback.tb_next` yielding the frame and diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst index 98dfa0f53bc6a5..0bff970fa77dae 100644 --- a/Doc/library/turtle.rst +++ b/Doc/library/turtle.rst @@ -1325,7 +1325,7 @@ Filling >>> turtle.circle(80) >>> turtle.end_fill() - .. versionadded:: next + .. versionadded:: 3.14 .. function:: begin_fill() @@ -1713,7 +1713,7 @@ Special Turtle methods ... turtle.right(60) ... turtle.forward(100) - .. versionadded:: next + .. versionadded:: 3.14 .. function:: begin_poly() @@ -2008,7 +2008,7 @@ Animation control ... fd(dist) ... rt(90) - .. versionadded:: next + .. versionadded:: 3.14 .. function:: delay(delay=None) diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 09b4d4ac4ffd56..bff6b9dcdc57ca 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -297,7 +297,7 @@ The :mod:`uuid` module defines the special Nil and Max UUID values: A special form of UUID that is specified to have all 128 bits set to zero according to :rfc:`RFC 9562, §5.9 <9562#section-5.9>`. - .. versionadded:: next + .. versionadded:: 3.14 .. data:: MAX @@ -305,7 +305,7 @@ The :mod:`uuid` module defines the special Nil and Max UUID values: A special form of UUID that is specified to have all 128 bits set to one according to :rfc:`RFC 9562, §5.10 <9562#section-5.10>`. - .. versionadded:: next + .. versionadded:: 3.14 .. seealso:: diff --git a/Doc/library/zipimport.rst b/Doc/library/zipimport.rst index 9353a45bdcecba..cd76f29a556939 100644 --- a/Doc/library/zipimport.rst +++ b/Doc/library/zipimport.rst @@ -148,7 +148,7 @@ zipimporter Objects qualified (dotted) module name. Returns the imported module on success, raises :exc:`ZipImportError` on failure. - .. deprecated:: 3.10 + .. deprecated-removed:: 3.10 3.15 Use :meth:`exec_module` instead. diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index ad24fe82f754fc..9617de0d2f9f63 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -16,7 +16,6 @@ Doc/library/ast.rst Doc/library/asyncio-extending.rst Doc/library/asyncio-subprocess.rst Doc/library/collections.rst -Doc/library/dbm.rst Doc/library/decimal.rst Doc/library/email.charset.rst Doc/library/email.compat32-message.rst diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index 101c43576b0314..72912cea2f0c28 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -626,7 +626,7 @@ also be used to improve performance. `preserve_none `_ calling convention. For example, Clang 19 and newer supports this feature. - .. versionadded:: next + .. versionadded:: 3.14 .. option:: --without-mimalloc diff --git a/Doc/using/editors.rst b/Doc/using/editors.rst index f36f570125c119..10b1780bda58f4 100644 --- a/Doc/using/editors.rst +++ b/Doc/using/editors.rst @@ -9,6 +9,19 @@ There are a number of IDEs that support Python programming language. Many editors and IDEs provide syntax highlighting, debugging tools, and :pep:`8` checks. + +IDLE --- Python editor and shell +================================ + +IDLE is Python’s Integrated Development and Learning Environment and is generally bundled with Python installs. +If you are on Linux and do not have IDLE installed see :ref:`Installing IDLE on Linux `. +For more information see the :ref:`IDLE docs `. + + +Other Editors and IDEs +====================== + +Python's community wiki has information submitted by the community on Editors and IDEs. Please go to `Python Editors `_ and `Integrated Development Environments `_ for a comprehensive list. diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index a2bcdab09a9282..9ed97f6fe85939 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -35,6 +35,31 @@ look at the following links: https://slackbook.org/html/package-management-making-packages.html for Slackware users +.. _installing_idle_on_linux: + +Installing IDLE +~~~~~~~~~~~~~~~ + +In some cases, IDLE might not be included in your Python installation. + +* For Debian and Ubuntu users:: + + sudo apt update + sudo apt install idle + +* For Fedora, RHEL, and CentOS users:: + + sudo dnf install python3-idle + +* For SUSE and OpenSUSE users:: + + sudo zypper in python3-idle + +* For Alpine Linux users:: + + sudo apk add python3-idle + + On FreeBSD and OpenBSD ---------------------- diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 994ccc708e26f2..084512e8e94759 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -1819,7 +1819,7 @@ Build Changes * ``PYTHON_FOR_REGEN`` now require Python 3.10 or newer. * Autoconf 2.71 and aclocal 1.16.4 is now required to regenerate - :file:`!configure`. + :file:`configure`. (Contributed by Christian Heimes in :gh:`89886`.) * Windows builds and macOS installers from python.org now use OpenSSL 3.0. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index f8df4c52a36147..ece5afd4597ab8 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1,4 +1,3 @@ - **************************** What's new in Python 3.14 **************************** @@ -166,7 +165,7 @@ Improved error messages error message prints the received number of values in more cases than before. (Contributed by Tushar Sadhwani in :gh:`122239`.) - .. code-block:: pycon + .. code-block:: python >>> x, y, z = 1, 2, 3, 4 Traceback (most recent call last): @@ -176,6 +175,17 @@ Improved error messages ValueError: too many values to unpack (expected 3, got 4) +* When incorrectly closed strings are detected, the error message suggests + that the string may be intended to be part of the string. (Contributed by + Pablo Galindo in :gh:`88535`.) + + .. code-block:: python + + >>> "The interesting object "The important object" is very important" + Traceback (most recent call last): + SyntaxError: invalid syntax. Is this intended to be part of the string? + + .. _whatsnew314-pep741: PEP 741: Python Configuration C API @@ -218,7 +228,8 @@ A new type of interpreter based on tail calls has been added to CPython. For certain newer compilers, this interpreter provides significantly better performance. Preliminary numbers on our machines suggest anywhere from -3% to 30% faster Python code, and a geometric mean of 9-15% -faster on ``pyperformance`` depending on platform and architecture. +faster on ``pyperformance`` depending on platform and architecture. The +baseline is Python 3.14 built with Clang 19 without this new interpreter. This interpreter currently only works with Clang 19 and newer on x86-64 and AArch64 architectures. However, we expect @@ -361,12 +372,19 @@ concurrent.futures supplying a *mp_context* to :class:`concurrent.futures.ProcessPoolExecutor`. (Contributed by Gregory P. Smith in :gh:`84559`.) +contextvars +----------- + +* Support context manager protocol by :class:`contextvars.Token`. + (Contributed by Andrew Svetlov in :gh:`129889`.) + + ctypes ------ * The layout of :ref:`bit fields ` in :class:`~ctypes.Structure` and :class:`~ctypes.Union` - now matches platform defaults (GCC/Clang or MVSC) more closely. + now matches platform defaults (GCC/Clang or MSVC) more closely. In particular, fields no longer overlap. (Contributed by Matthias Görgens in :gh:`97702`.) @@ -410,6 +428,13 @@ decimal :meth:`Decimal.from_number() `. (Contributed by Serhiy Storchaka in :gh:`121798`.) +difflib +------- + +* Comparison pages with highlighted changes generated by the + :class:`difflib.HtmlDiff` class now support dark mode. + (Contributed by Jiahao Li in :gh:`129939`.) + dis --- @@ -480,6 +505,14 @@ http (Contributed by Yorik Hansen in :gh:`123430`.) +imaplib +------- + +* Add :meth:`IMAP4.idle() `, implementing the IMAP4 + ``IDLE`` command as defined in :rfc:`2177`. + (Contributed by Forest in :gh:`55454`.) + + inspect ------- @@ -495,13 +528,6 @@ inspect :term:`package` or not. (Contributed by Zhikang Yan in :gh:`125634`.) -imaplib -------- - -* Add :meth:`IMAP4.idle() `, implementing the IMAP4 - ``IDLE`` command as defined in :rfc:`2177`. - (Contributed by Forest in :gh:`55454`.) - io -- @@ -630,7 +656,6 @@ pathlib :func:`~os.stat` results. Path objects generated by :meth:`~pathlib.Path.iterdir` are initialized with file type information gleaned from scanning the parent directory. - (Contributed by Barney Gale in :gh:`125413`.) @@ -669,7 +694,6 @@ platform -------- * Add :func:`platform.invalidate_caches` to invalidate the cached results. - (Contributed by Bénédikt Tran in :gh:`122549`.) @@ -808,13 +832,11 @@ zipinfo * Added :func:`ZipInfo._for_archive ` to resolve suitable defaults for a :class:`~zipfile.ZipInfo` object as used by :func:`ZipFile.writestr `. - (Contributed by Bénédikt Tran in :gh:`123424`.) * :meth:`zipfile.ZipFile.writestr` now respect ``SOURCE_DATE_EPOCH`` that distributions can set centrally and have build tools consume this in order to produce reproducible output. - (Contributed by Jiahao Li in :gh:`91279`.) .. Add improved modules above alphabetically, not here at the end. @@ -1003,7 +1025,6 @@ ast * :attr:`!ast.Constant.s` Use :attr:`!ast.Constant.value` instead. - (Contributed by Alex Waygood in :gh:`119562`.) asyncio @@ -1212,7 +1233,6 @@ urllib :func:`~urllib.request.urlretrieve`. Customizations to the opener classes can be replaced by passing customized handlers to :func:`~urllib.request.build_opener`. - (Contributed by Barney Gale in :gh:`84850`.) Others @@ -1465,6 +1485,8 @@ Porting to Python 3.14 .. _pythoncapi-compat project: https://github.com/python/pythoncapi-compat/ +.. _whatsnew314-c-api-deprecated: + Deprecated ---------- @@ -1504,10 +1526,8 @@ Deprecated The `pythoncapi-compat project`_ can be used to get these new public functions on Python 3.13 and older. - (Contributed by Victor Stinner in :gh:`128863`.) - .. include:: ../deprecations/c-api-pending-removal-in-3.15.rst .. include:: ../deprecations/c-api-pending-removal-in-3.18.rst @@ -1515,6 +1535,8 @@ Deprecated .. include:: ../deprecations/c-api-pending-removal-in-future.rst +.. _whatsnew314-c-api-removed: + Removed ------- diff --git a/Grammar/python.gram b/Grammar/python.gram index b47028460b94f4..08e49d03382f64 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -207,7 +207,7 @@ import_name[stmt_ty]: 'import' a=dotted_as_names { _PyAST_Import(a, EXTRA) } # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS import_from[stmt_ty]: | 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets { - _PyAST_ImportFrom(b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) } + _PyPegen_checked_future_import(p, b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) } | 'from' a=('.' | '...')+ 'import' b=import_from_targets { _PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), EXTRA) } import_from_targets[asdl_alias_seq*]: @@ -1178,6 +1178,9 @@ invalid_type_param: } invalid_expression: + | STRING a=(!STRING expression_without_invalid)+ STRING { + RAISE_SYNTAX_ERROR_KNOWN_RANGE( PyPegen_first_item(a, expr_ty), PyPegen_last_item(a, expr_ty), + "invalid syntax. Is this intended to be part of the string?") } # !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf" # Soft keywords need to also be ignored because they can be parsed as NAME NAME | !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid { diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index fea8665ae39ab5..6265afba38be26 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -274,7 +274,7 @@ PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *, _PyInterpreterFrame * PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs); PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys); PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); -PyAPI_FUNC(int) _PyEval_UnpackIterableStackRef(PyThreadState *tstate, _PyStackRef v, int argcnt, int argcntafter, _PyStackRef *sp); +PyAPI_FUNC(int) _PyEval_UnpackIterableStackRef(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, _PyStackRef *sp); PyAPI_FUNC(void) _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame); PyAPI_FUNC(PyObject **) _PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_ssize_t nargs, PyObject **scratch); diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 49ddfd5b43b00c..ffd31bd4a27f49 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -74,6 +74,7 @@ PyAPI_FUNC(int) _PyObject_IsFreed(PyObject *); { \ .ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL, \ .ob_flags = _Py_STATICALLY_ALLOCATED_FLAG, \ + .ob_gc_bits = _PyGC_BITS_DEFERRED, \ .ob_type = (type) \ } #else @@ -612,7 +613,7 @@ _Py_TryIncrefCompare(PyObject **src, PyObject *op) static inline int _Py_TryIncrefCompareStackRef(PyObject **src, PyObject *op, _PyStackRef *out) { - if (_Py_IsImmortal(op) || _PyObject_HasDeferredRefcount(op)) { + if (_PyObject_HasDeferredRefcount(op)) { *out = (_PyStackRef){ .bits = (intptr_t)op | Py_TAG_DEFERRED }; return 1; } diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 24c698adb31562..a59150bb69b9eb 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -2001,21 +2001,21 @@ struct opcode_metadata { extern const struct opcode_metadata _PyOpcode_opcode_metadata[266]; #ifdef NEED_OPCODE_METADATA const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { - [BINARY_OP] = { true, INSTR_FMT_IBC0000, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP] = { true, INSTR_FMT_IBC0000, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, - [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, + [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, [BINARY_OP_EXTEND] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG }, + [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, - [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, + [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_SUBSCR_DICT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG }, [BINARY_OP_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC0000, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, - [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, + [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BUILD_LIST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [BUILD_MAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -2053,7 +2053,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [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 | HAS_ESCAPES_FLAG }, [CHECK_EG_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [CLEANUP_THROW] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [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 }, @@ -2075,7 +2075,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [DICT_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [END_ASYNC_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [END_FOR] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG }, - [END_SEND] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, + [END_SEND] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_PURE_FLAG }, [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [EXIT_INIT_CHECK] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, @@ -2132,8 +2132,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, - [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG }, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, + [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, @@ -2169,12 +2169,12 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [NOP] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, [NOT_TAKEN] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, [POP_EXCEPT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, - [POP_ITER] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, + [POP_ITER] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_PURE_FLAG }, [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, - [POP_TOP] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, + [POP_TOP] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_PURE_FLAG }, [PUSH_EXC_INFO] = { true, INSTR_FMT_IX, 0 }, [PUSH_NULL] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, [RAISE_VARARGS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, @@ -2183,7 +2183,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [RETURN_VALUE] = { true, INSTR_FMT_IX, 0 }, + [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_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 }, @@ -2206,12 +2206,12 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [STORE_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_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 }, + [TO_BOOL_ALWAYS_TRUE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [TO_BOOL_BOOL] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, - [TO_BOOL_INT] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, + [TO_BOOL_INT] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [TO_BOOL_LIST] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, [TO_BOOL_NONE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, - [TO_BOOL_STR] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, + [TO_BOOL_STR] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, [UNARY_INVERT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [UNARY_NEGATIVE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [UNARY_NOT] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, @@ -2219,7 +2219,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [UNPACK_SEQUENCE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [UNPACK_SEQUENCE_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, - [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, + [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, [WITH_EXCEPT_START] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [JUMP] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index f426ae0e103b9c..a5f9418ec05718 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -75,7 +75,7 @@ extern PyStatus _Py_PreInitializeFromConfig( extern wchar_t * _Py_GetStdlibDir(void); -extern int _Py_HandleSystemExit(int *exitcode_p); +extern int _Py_HandleSystemExitAndKeyboardInterrupt(int *exitcode_p); extern PyObject* _PyErr_WriteUnraisableDefaultHook(PyObject *unraisable); diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 1ae62cc69bb364..92b10d21100a25 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -219,7 +219,7 @@ PyStackRef_FromPyObjectNew(PyObject *obj) // Make sure we don't take an already tagged value. assert(((uintptr_t)obj & Py_TAG_BITS) == 0); assert(obj != NULL); - if (_Py_IsImmortal(obj) || _PyObject_HasDeferredRefcount(obj)) { + if (_PyObject_HasDeferredRefcount(obj)) { return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_DEFERRED }; } else { diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 86a4843ea05db9..1a1fd328195b46 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -53,26 +53,26 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ESCAPES_FLAG, [_STORE_FAST_LOAD_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ESCAPES_FLAG, [_STORE_FAST_STORE_FAST] = HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ESCAPES_FLAG, - [_POP_TOP] = HAS_PURE_FLAG, + [_POP_TOP] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, [_PUSH_NULL] = HAS_PURE_FLAG, [_END_FOR] = HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG, - [_END_SEND] = HAS_PURE_FLAG, + [_END_SEND] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, [_UNARY_NEGATIVE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_UNARY_NOT] = HAS_PURE_FLAG, [_TO_BOOL] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_TO_BOOL_BOOL] = HAS_EXIT_FLAG, - [_TO_BOOL_INT] = HAS_EXIT_FLAG, + [_TO_BOOL_INT] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, [_TO_BOOL_LIST] = HAS_EXIT_FLAG, [_TO_BOOL_NONE] = HAS_EXIT_FLAG, - [_TO_BOOL_STR] = HAS_EXIT_FLAG, - [_REPLACE_WITH_TRUE] = 0, + [_TO_BOOL_STR] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, + [_REPLACE_WITH_TRUE] = HAS_ESCAPES_FLAG, [_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, + [_BINARY_OP_MULTIPLY_INT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_PURE_FLAG, + [_BINARY_OP_ADD_INT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_PURE_FLAG, + [_BINARY_OP_SUBTRACT_INT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_PURE_FLAG, [_GUARD_BOTH_FLOAT] = HAS_EXIT_FLAG, [_GUARD_NOS_FLOAT] = HAS_EXIT_FLAG, [_GUARD_TOS_FLOAT] = HAS_EXIT_FLAG, @@ -81,7 +81,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_OP_SUBTRACT_FLOAT] = HAS_ERROR_FLAG | HAS_PURE_FLAG, [_GUARD_BOTH_UNICODE] = HAS_EXIT_FLAG, [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_PURE_FLAG, - [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG, + [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_BINARY_OP_EXTEND] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_BINARY_OP_EXTEND] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG, [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -100,7 +100,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_DELETE_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_1] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_INTRINSIC_2] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_RETURN_VALUE] = 0, + [_RETURN_VALUE] = HAS_ESCAPES_FLAG, [_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, @@ -112,7 +112,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DELETE_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_UNPACK_SEQUENCE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_UNPACK_SEQUENCE_TWO_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, + [_UNPACK_SEQUENCE_TWO_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_UNPACK_SEQUENCE_TUPLE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_UNPACK_SEQUENCE_LIST] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_UNPACK_EX] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -175,7 +175,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CONTAINS_OP_SET] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CONTAINS_OP_DICT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CHECK_EG_MATCH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CHECK_EXC_MATCH] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_EXC_MATCH] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_IMPORT_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_IMPORT_FROM] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_IS_NONE] = 0, @@ -204,8 +204,8 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GUARD_KEYS_VERSION] = HAS_DEOPT_FLAG, [_LOAD_ATTR_METHOD_WITH_VALUES] = HAS_ARG_FLAG, [_LOAD_ATTR_METHOD_NO_DICT] = HAS_ARG_FLAG, - [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = HAS_ARG_FLAG, - [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = HAS_ARG_FLAG, + [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, [_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG, [_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG, [_MAYBE_EXPAND_METHOD] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, @@ -261,7 +261,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_FORMAT_SIMPLE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_FORMAT_WITH_SPEC] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_COPY] = HAS_ARG_FLAG | HAS_PURE_FLAG, - [_BINARY_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_SWAP] = HAS_ARG_FLAG | HAS_PURE_FLAG, [_GUARD_IS_TRUE_POP] = HAS_EXIT_FLAG, [_GUARD_IS_FALSE_POP] = HAS_EXIT_FLAG, diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 40e7d73b7a6634..5929c3f96dc4e2 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -21,10 +21,10 @@ #define PY_MINOR_VERSION 14 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 4 +#define PY_RELEASE_SERIAL 5 /* Version as a string */ -#define PY_VERSION "3.14.0a4+" +#define PY_VERSION "3.14.0a5+" /*--end constants--*/ diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index be90c9b1315d53..600a7e08345a82 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -60,14 +60,14 @@ def _days_in_month(year, month): def _days_before_month(year, month): "year, month -> number of days in year preceding first day of month." - assert 1 <= month <= 12, 'month must be in 1..12' + assert 1 <= month <= 12, f"month must be in 1..12, not {month}" return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year)) def _ymd2ord(year, month, day): "year, month, day -> ordinal, considering 01-Jan-0001 as day 1." - assert 1 <= month <= 12, 'month must be in 1..12' + assert 1 <= month <= 12, f"month must be in 1..12, not {month}" dim = _days_in_month(year, month) - assert 1 <= day <= dim, ('day must be in 1..%d' % dim) + assert 1 <= day <= dim, f"day must be in 1..{dim}, not {day}" return (_days_before_year(year) + _days_before_month(year, month) + day) @@ -512,7 +512,7 @@ def _parse_isoformat_time(tstr): def _isoweek_to_gregorian(year, week, day): # Year is bounded this way because 9999-12-31 is (9999, 52, 5) if not MINYEAR <= year <= MAXYEAR: - raise ValueError(f"Year is out of range: {year}") + raise ValueError(f"year must be in {MINYEAR}..{MAXYEAR}, not {year}") if not 0 < week < 53: out_of_range = True @@ -545,7 +545,7 @@ def _isoweek_to_gregorian(year, week, day): def _check_tzname(name): if name is not None and not isinstance(name, str): raise TypeError("tzinfo.tzname() must return None or string, " - "not '%s'" % type(name)) + f"not {type(name).__name__!r}") # name is the offset-producing method, "utcoffset" or "dst". # offset is what it returned. @@ -558,24 +558,24 @@ def _check_utc_offset(name, offset): if offset is None: return if not isinstance(offset, timedelta): - raise TypeError("tzinfo.%s() must return None " - "or timedelta, not '%s'" % (name, type(offset))) + raise TypeError(f"tzinfo.{name}() must return None " + f"or timedelta, not {type(offset).__name__!r}") if not -timedelta(1) < offset < timedelta(1): - raise ValueError("%s()=%s, must be strictly between " - "-timedelta(hours=24) and timedelta(hours=24)" % - (name, offset)) + raise ValueError("offset must be a timedelta " + "strictly between -timedelta(hours=24) and " + f"timedelta(hours=24), not {offset!r}") def _check_date_fields(year, month, day): year = _index(year) month = _index(month) day = _index(day) if not MINYEAR <= year <= MAXYEAR: - raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year) + raise ValueError(f"year must be in {MINYEAR}..{MAXYEAR}, not {year}") if not 1 <= month <= 12: - raise ValueError('month must be in 1..12', month) + raise ValueError(f"month must be in 1..12, not {month}") dim = _days_in_month(year, month) if not 1 <= day <= dim: - raise ValueError('day must be in 1..%d' % dim, day) + raise ValueError(f"day must be in 1..{dim}, not {day}") return year, month, day def _check_time_fields(hour, minute, second, microsecond, fold): @@ -584,20 +584,23 @@ def _check_time_fields(hour, minute, second, microsecond, fold): second = _index(second) microsecond = _index(microsecond) if not 0 <= hour <= 23: - raise ValueError('hour must be in 0..23', hour) + raise ValueError(f"hour must be in 0..23, not {hour}") if not 0 <= minute <= 59: - raise ValueError('minute must be in 0..59', minute) + raise ValueError(f"minute must be in 0..59, not {minute}") if not 0 <= second <= 59: - raise ValueError('second must be in 0..59', second) + raise ValueError(f"second must be in 0..59, not {second}") if not 0 <= microsecond <= 999999: - raise ValueError('microsecond must be in 0..999999', microsecond) + raise ValueError(f"microsecond must be in 0..999999, not {microsecond}") if fold not in (0, 1): - raise ValueError('fold must be either 0 or 1', fold) + raise ValueError(f"fold must be either 0 or 1, not {fold}") return hour, minute, second, microsecond, fold def _check_tzinfo_arg(tz): if tz is not None and not isinstance(tz, tzinfo): - raise TypeError("tzinfo argument must be None or of a tzinfo subclass") + raise TypeError( + "tzinfo argument must be None or of a tzinfo subclass, " + f"not {type(tz).__name__!r}" + ) def _divide_and_round(a, b): """divide a by b and round result to the nearest integer @@ -2418,7 +2421,7 @@ def __new__(cls, offset, name=_Omitted): if not cls._minoffset <= offset <= cls._maxoffset: raise ValueError("offset must be a timedelta " "strictly between -timedelta(hours=24) and " - "timedelta(hours=24).") + f"timedelta(hours=24), not {offset!r}") return cls._create(offset, name) def __init_subclass__(cls): diff --git a/Lib/difflib.py b/Lib/difflib.py index 7f595b6c72e641..c124afdd039559 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1632,13 +1632,22 @@ def _line_pair_iterator(): """ _styles = """ + :root {color-scheme: light dark} table.diff {font-family:Courier; border:medium;} .diff_header {background-color:#e0e0e0} td.diff_header {text-align:right} .diff_next {background-color:#c0c0c0} - .diff_add {background-color:#aaffaa} + .diff_add {background-color:palegreen} .diff_chg {background-color:#ffff77} - .diff_sub {background-color:#ffaaaa}""" + .diff_sub {background-color:#ffaaaa} + + @media (prefers-color-scheme: dark) { + .diff_header {background-color:#666} + .diff_next {background-color:#393939} + .diff_add {background-color:darkgreen} + .diff_chg {background-color:#847415} + .diff_sub {background-color:darkred} + }""" _table_template = """ >=" | "<<=" | "&=" | "^=" | "|=" + **augmented_assignment_stmt**: "augtarget" "augop" ("expression_list" | "yield_expression") + **augtarget**: "identifier" | "attributeref" | "subscription" | "slicing" + **augop**: "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**=" + | ">>=" | "<<=" | "&=" | "^=" | "|=" (See section Primaries for the syntax definitions of the last three symbols.) @@ -239,8 +239,8 @@ class and instance attributes applies as for regular assignments. a variable or attribute annotation and an optional assignment statement: - annotated_assignment_stmt ::= augtarget ":" expression - ["=" (starred_expression | yield_expression)] + **annotated_assignment_stmt**: "augtarget" ":" "expression" + ["=" ("starred_expression" | "yield_expression")] The difference from normal Assignment statements is that only a single target is allowed. @@ -289,7 +289,7 @@ class and instance attributes applies as for regular assignments. 'assignment-expressions': r'''Assignment expressions ********************** - assignment_expression ::= [identifier ":="] expression + **assignment_expression**: ["identifier" ":="] "expression" An assignment expression (sometimes also called a “named expression” or “walrus”) assigns an "expression" to an "identifier", while also @@ -324,8 +324,8 @@ class and instance attributes applies as for regular assignments. Coroutine function definition ============================= - async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" - ["->" expression] ":" suite + **async_funcdef**: ["decorators"] "async" "def" "funcname" "(" ["parameter_list"] ")" + ["->" "expression"] ":" "suite" Execution of Python coroutines can be suspended and resumed at many points (see *coroutine*). "await" expressions, "async for" and "async @@ -351,7 +351,7 @@ async def func(param1, param2): The "async for" statement ========================= - async_for_stmt ::= "async" for_stmt + **async_for_stmt**: "async" "for_stmt" An *asynchronous iterable* provides an "__aiter__" method that directly returns an *asynchronous iterator*, which can call @@ -392,7 +392,7 @@ async def func(param1, param2): The "async with" statement ========================== - async_with_stmt ::= "async" with_stmt + **async_with_stmt**: "async" "with_stmt" An *asynchronous context manager* is a *context manager* that is able to suspend execution in its *enter* and *exit* methods. @@ -492,8 +492,8 @@ async def func(param1, param2): Python supports string and bytes literals and various numeric literals: - literal ::= stringliteral | bytesliteral - | integer | floatnumber | imagnumber + **literal**: "stringliteral" | "bytesliteral" + | "integer" | "floatnumber" | "imagnumber" Evaluation of a literal yields an object of the given type (string, bytes, integer, floating-point number, complex number) with the given @@ -842,7 +842,7 @@ class derived from a ""variable-length" built-in type" such as An attribute reference is a primary followed by a period and a name: - attributeref ::= primary "." identifier + **attributeref**: "primary" "." "identifier" The primary must evaluate to an object of a type that supports attribute references, which most objects do. This object is then @@ -864,10 +864,10 @@ class derived from a ""variable-length" built-in type" such as Augmented assignment is the combination, in a single statement, of a binary operation and an assignment statement: - augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression) - augtarget ::= identifier | attributeref | subscription | slicing - augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**=" - | ">>=" | "<<=" | "&=" | "^=" | "|=" + **augmented_assignment_stmt**: "augtarget" "augop" ("expression_list" | "yield_expression") + **augtarget**: "identifier" | "attributeref" | "subscription" | "slicing" + **augop**: "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**=" + | ">>=" | "<<=" | "&=" | "^=" | "|=" (See section Primaries for the syntax definitions of the last three symbols.) @@ -906,7 +906,7 @@ class and instance attributes applies as for regular assignments. Suspend the execution of *coroutine* on an *awaitable* object. Can only be used inside a *coroutine function*. - await_expr ::= "await" primary + **await_expr**: "await" "primary" Added in version 3.5. ''', @@ -919,10 +919,10 @@ class and instance attributes applies as for regular assignments. levels, one for multiplicative operators and one for additive operators: - m_expr ::= u_expr | m_expr "*" u_expr | m_expr "@" m_expr | - m_expr "//" u_expr | m_expr "/" u_expr | - m_expr "%" u_expr - a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr + **m_expr**: "u_expr" | "m_expr" "*" "u_expr" | "m_expr" "@" "m_expr" | + "m_expr" "//" "u_expr" | "m_expr" "/" "u_expr" | + "m_expr" "%" "u_expr" + **a_expr**: "m_expr" | "a_expr" "+" "m_expr" | "a_expr" "-" "m_expr" The "*" (multiplication) operator yields the product of its arguments. The arguments must either both be numbers, or one argument must be an @@ -1010,9 +1010,9 @@ class and instance attributes applies as for regular assignments. Each of the three bitwise operations has a different priority level: - and_expr ::= shift_expr | and_expr "&" shift_expr - xor_expr ::= and_expr | xor_expr "^" and_expr - or_expr ::= xor_expr | or_expr "|" xor_expr + **and_expr**: "shift_expr" | "and_expr" "&" "shift_expr" + **xor_expr**: "and_expr" | "xor_expr" "^" "and_expr" + **or_expr**: "xor_expr" | "or_expr" "|" "xor_expr" The "&" operator yields the bitwise AND of its arguments, which must be integers or one of them must be a custom object overriding @@ -1077,9 +1077,9 @@ class and instance attributes applies as for regular assignments. 'booleans': r'''Boolean operations ****************** - or_test ::= and_test | or_test "or" and_test - and_test ::= not_test | and_test "and" not_test - not_test ::= comparison | "not" not_test + **or_test**: "and_test" | "or_test" "or" "and_test" + **and_test**: "not_test" | "and_test" "and" "not_test" + **not_test**: "comparison" | "not" "not_test" In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted @@ -1111,7 +1111,7 @@ class and instance attributes applies as for regular assignments. 'break': r'''The "break" statement ********************* - break_stmt ::= "break" + **break_stmt**: "break" "break" may only occur syntactically nested in a "for" or "while" loop, but not nested in a function or class definition within that @@ -1143,18 +1143,18 @@ class and instance attributes applies as for regular assignments. A call calls a callable object (e.g., a *function*) with a possibly empty series of *arguments*: - call ::= primary "(" [argument_list [","] | comprehension] ")" - argument_list ::= positional_arguments ["," starred_and_keywords] - ["," keywords_arguments] - | starred_and_keywords ["," keywords_arguments] - | keywords_arguments - positional_arguments ::= positional_item ("," positional_item)* - positional_item ::= assignment_expression | "*" expression - starred_and_keywords ::= ("*" expression | keyword_item) - ("," "*" expression | "," keyword_item)* - keywords_arguments ::= (keyword_item | "**" expression) - ("," keyword_item | "," "**" expression)* - keyword_item ::= identifier "=" expression + **call**: "primary" "(" ["argument_list" [","] | "comprehension"] ")" + **argument_list**: "positional_arguments" ["," "starred_and_keywords"] + ["," "keywords_arguments"] + | "starred_and_keywords" ["," "keywords_arguments"] + | "keywords_arguments" + **positional_arguments**: positional_item ("," positional_item)* + **positional_item**: "assignment_expression" | "*" "expression" + **starred_and_keywords**: ("*" "expression" | "keyword_item") + ("," "*" "expression" | "," "keyword_item")* + **keywords_arguments**: ("keyword_item" | "**" "expression") + ("," "keyword_item" | "," "**" "expression")* + **keyword_item**: "identifier" "=" "expression" An optional trailing comma may be present after the positional and keyword arguments but does not affect the semantics. @@ -1296,9 +1296,9 @@ class and instance attributes applies as for regular assignments. A class definition defines a class object (see section The standard type hierarchy): - classdef ::= [decorators] "class" classname [type_params] [inheritance] ":" suite - inheritance ::= "(" [argument_list] ")" - classname ::= identifier + **classdef**: ["decorators"] "class" "classname" ["type_params"] ["inheritance"] ":" "suite" + **inheritance**: "(" ["argument_list"] ")" + **classname**: "identifier" A class definition is an executable statement. The inheritance list usually gives a list of base classes (see Metaclasses for more @@ -1386,9 +1386,9 @@ class attributes; they are shared by instances. Instance attributes operation. Also unlike C, expressions like "a < b < c" have the interpretation that is conventional in mathematics: - comparison ::= or_expr (comp_operator or_expr)* - comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!=" - | "is" ["not"] | ["not"] "in" + **comparison**: "or_expr" ("comp_operator" "or_expr")* + **comp_operator**: "<" | ">" | "==" | ">=" | "<=" | "!=" + | "is" ["not"] | ["not"] "in" Comparisons yield boolean values: "True" or "False". Custom *rich comparison methods* may return non-boolean values. In this case Python @@ -1656,20 +1656,20 @@ class attributes; they are shared by instances. Instance attributes Summarizing: - compound_stmt ::= if_stmt - | while_stmt - | for_stmt - | try_stmt - | with_stmt - | match_stmt - | funcdef - | classdef - | async_with_stmt - | async_for_stmt - | async_funcdef - suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT - statement ::= stmt_list NEWLINE | compound_stmt - stmt_list ::= simple_stmt (";" simple_stmt)* [";"] + **compound_stmt**: "if_stmt" + | "while_stmt" + | "for_stmt" + | "try_stmt" + | "with_stmt" + | "match_stmt" + | "funcdef" + | "classdef" + | "async_with_stmt" + | "async_for_stmt" + | "async_funcdef" + **suite**: "stmt_list" NEWLINE | NEWLINE INDENT "statement"+ DEDENT + **statement**: "stmt_list" NEWLINE | "compound_stmt" + **stmt_list**: "simple_stmt" (";" "simple_stmt")* [";"] Note that statements always end in a "NEWLINE" possibly followed by a "DEDENT". Also note that optional continuation clauses always begin @@ -1686,9 +1686,9 @@ class attributes; they are shared by instances. Instance attributes The "if" statement is used for conditional execution: - if_stmt ::= "if" assignment_expression ":" suite - ("elif" assignment_expression ":" suite)* - ["else" ":" suite] + **if_stmt**: "if" "assignment_expression" ":" "suite" + ("elif" "assignment_expression" ":" "suite")* + ["else" ":" "suite"] It selects exactly one of the suites by evaluating the expressions one by one until one is found to be true (see section Boolean operations @@ -1704,8 +1704,8 @@ class attributes; they are shared by instances. Instance attributes The "while" statement is used for repeated execution as long as an expression is true: - while_stmt ::= "while" assignment_expression ":" suite - ["else" ":" suite] + **while_stmt**: "while" "assignment_expression" ":" "suite" + ["else" ":" "suite"] This repeatedly tests the expression and, if it is true, executes the first suite; if the expression is false (which may be the first time @@ -1724,8 +1724,8 @@ class attributes; they are shared by instances. Instance attributes The "for" statement is used to iterate over the elements of a sequence (such as a string, tuple or list) or other iterable object: - for_stmt ::= "for" target_list "in" starred_list ":" suite - ["else" ":" suite] + **for_stmt**: "for" "target_list" "in" "starred_list" ":" "suite" + ["else" ":" "suite"] The "starred_list" expression is evaluated once; it should yield an *iterable* object. An *iterator* is created for that iterable. The @@ -1768,17 +1768,17 @@ class attributes; they are shared by instances. Instance attributes The "try" statement specifies exception handlers and/or cleanup code for a group of statements: - try_stmt ::= try1_stmt | try2_stmt | try3_stmt - try1_stmt ::= "try" ":" suite - ("except" [expression ["as" identifier]] ":" suite)+ - ["else" ":" suite] - ["finally" ":" suite] - try2_stmt ::= "try" ":" suite - ("except" "*" expression ["as" identifier] ":" suite)+ - ["else" ":" suite] - ["finally" ":" suite] - try3_stmt ::= "try" ":" suite - "finally" ":" suite + **try_stmt**: "try1_stmt" | "try2_stmt" | "try3_stmt" + **try1_stmt**: "try" ":" "suite" + ("except" ["expression" ["as" "identifier"]] ":" "suite")+ + ["else" ":" "suite"] + ["finally" ":" "suite"] + **try2_stmt**: "try" ":" "suite" + ("except" "*" "expression" ["as" "identifier"] ":" "suite")+ + ["else" ":" "suite"] + ["finally" ":" "suite"] + **try3_stmt**: "try" ":" "suite" + "finally" ":" "suite" Additional information on exceptions can be found in section Exceptions, and information on using the "raise" statement to generate @@ -1985,9 +1985,9 @@ class attributes; they are shared by instances. Instance attributes Context Managers). This allows common "try"…"except"…"finally" usage patterns to be encapsulated for convenient reuse. - with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite - with_stmt_contents ::= with_item ("," with_item)* - with_item ::= expression ["as" target] + **with_stmt**: "with" ( "(" "with_stmt_contents" ","? ")" | "with_stmt_contents" ) ":" "suite" + **with_stmt_contents**: "with_item" ("," "with_item")* + **with_item**: "expression" ["as" "target"] The execution of the "with" statement with one “item” proceeds as follows: @@ -2093,10 +2093,10 @@ class attributes; they are shared by instances. Instance attributes The match statement is used for pattern matching. Syntax: - match_stmt ::= 'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT - subject_expr ::= star_named_expression "," star_named_expressions? - | named_expression - case_block ::= 'case' patterns [guard] ":" block + **match_stmt**: 'match' "subject_expr" ":" NEWLINE INDENT "case_block"+ DEDENT + **subject_expr**: "star_named_expression" "," "star_named_expressions"? + | "named_expression" + **case_block**: 'case' "patterns" ["guard"] ":" "block" Note: @@ -2187,7 +2187,7 @@ class attributes; they are shared by instances. Instance attributes Guards ------ - guard ::= "if" named_expression + **guard**: "if" "named_expression" A "guard" (which is part of the "case") must succeed for code inside the "case" block to execute. It takes the form: "if" followed by an @@ -2254,16 +2254,16 @@ class attributes; they are shared by instances. Instance attributes The top-level syntax for "patterns" is: - patterns ::= open_sequence_pattern | pattern - pattern ::= as_pattern | or_pattern - closed_pattern ::= | literal_pattern - | capture_pattern - | wildcard_pattern - | value_pattern - | group_pattern - | sequence_pattern - | mapping_pattern - | class_pattern + **patterns**: "open_sequence_pattern" | "pattern" + **pattern**: "as_pattern" | "or_pattern" + **closed_pattern**: | "literal_pattern" + | "capture_pattern" + | "wildcard_pattern" + | "value_pattern" + | "group_pattern" + | "sequence_pattern" + | "mapping_pattern" + | "class_pattern" The descriptions below will include a description “in simple terms” of what a pattern does for illustration purposes (credits to Raymond @@ -2279,7 +2279,7 @@ class attributes; they are shared by instances. Instance attributes An OR pattern is two or more patterns separated by vertical bars "|". Syntax: - or_pattern ::= "|".closed_pattern+ + **or_pattern**: "|"."closed_pattern"+ Only the final subpattern may be irrefutable, and each subpattern must bind the same set of names to avoid ambiguity. @@ -2300,7 +2300,7 @@ class attributes; they are shared by instances. Instance attributes An AS pattern matches an OR pattern on the left of the "as" keyword against a subject. Syntax: - as_pattern ::= or_pattern "as" capture_pattern + **as_pattern**: "or_pattern" "as" "capture_pattern" If the OR pattern fails, the AS pattern fails. Otherwise, the AS pattern binds the subject to the name on the right of the as keyword @@ -2315,14 +2315,14 @@ class attributes; they are shared by instances. Instance attributes A literal pattern corresponds to most literals in Python. Syntax: - literal_pattern ::= signed_number - | signed_number "+" NUMBER - | signed_number "-" NUMBER - | strings - | "None" - | "True" - | "False" - signed_number ::= ["-"] NUMBER + **literal_pattern**: "signed_number" + | "signed_number" "+" NUMBER + | "signed_number" "-" NUMBER + | "strings" + | "None" + | "True" + | "False" + **signed_number**: ["-"] NUMBER The rule "strings" and the token "NUMBER" are defined in the standard Python grammar. Triple-quoted strings are supported. Raw strings and @@ -2342,7 +2342,7 @@ class attributes; they are shared by instances. Instance attributes A capture pattern binds the subject value to a name. Syntax: - capture_pattern ::= !'_' NAME + **capture_pattern**: !'_' NAME A single underscore "_" is not a capture pattern (this is what "!'_'" expresses). It is instead treated as a "wildcard_pattern". @@ -2365,7 +2365,7 @@ class attributes; they are shared by instances. Instance attributes A wildcard pattern always succeeds (matches anything) and binds no name. Syntax: - wildcard_pattern ::= '_' + **wildcard_pattern**: '_' "_" is a soft keyword within any pattern, but only within patterns. It is an identifier, as usual, even within "match" subject @@ -2379,9 +2379,9 @@ class attributes; they are shared by instances. Instance attributes A value pattern represents a named value in Python. Syntax: - value_pattern ::= attr - attr ::= name_or_attr "." NAME - name_or_attr ::= attr | NAME + **value_pattern**: "attr" + **attr**: "name_or_attr" "." NAME + **name_or_attr**: "attr" | NAME The dotted name in the pattern is looked up using standard Python name resolution rules. The pattern succeeds if the value found compares @@ -2405,7 +2405,7 @@ class attributes; they are shared by instances. Instance attributes emphasize the intended grouping. Otherwise, it has no additional syntax. Syntax: - group_pattern ::= "(" pattern ")" + **group_pattern**: "(" "pattern" ")" In simple terms "(P)" has the same effect as "P". @@ -2417,12 +2417,12 @@ class attributes; they are shared by instances. Instance attributes sequence elements. The syntax is similar to the unpacking of a list or tuple. - sequence_pattern ::= "[" [maybe_sequence_pattern] "]" - | "(" [open_sequence_pattern] ")" - open_sequence_pattern ::= maybe_star_pattern "," [maybe_sequence_pattern] - maybe_sequence_pattern ::= ",".maybe_star_pattern+ ","? - maybe_star_pattern ::= star_pattern | pattern - star_pattern ::= "*" (capture_pattern | wildcard_pattern) + **sequence_pattern**: "[" ["maybe_sequence_pattern"] "]" + | "(" ["open_sequence_pattern"] ")" + **open_sequence_pattern**: "maybe_star_pattern" "," ["maybe_sequence_pattern"] + **maybe_sequence_pattern**: ","."maybe_star_pattern"+ ","? + **maybe_star_pattern**: "star_pattern" | "pattern" + **star_pattern**: "*" ("capture_pattern" | "wildcard_pattern") There is no difference if parentheses or square brackets are used for sequence patterns (i.e. "(...)" vs "[...]" ). @@ -2505,11 +2505,11 @@ class attributes; they are shared by instances. Instance attributes A mapping pattern contains one or more key-value patterns. The syntax is similar to the construction of a dictionary. Syntax: - mapping_pattern ::= "{" [items_pattern] "}" - items_pattern ::= ",".key_value_pattern+ ","? - key_value_pattern ::= (literal_pattern | value_pattern) ":" pattern - | double_star_pattern - double_star_pattern ::= "**" capture_pattern + **mapping_pattern**: "{" ["items_pattern"] "}" + **items_pattern**: ","."key_value_pattern"+ ","? + **key_value_pattern**: ("literal_pattern" | "value_pattern") ":" "pattern" + | "double_star_pattern" + **double_star_pattern**: "**" "capture_pattern" At most one double star pattern may be in a mapping pattern. The double star pattern must be the last subpattern in the mapping @@ -2558,12 +2558,12 @@ class attributes; they are shared by instances. Instance attributes A class pattern represents a class and its positional and keyword arguments (if any). Syntax: - class_pattern ::= name_or_attr "(" [pattern_arguments ","?] ")" - pattern_arguments ::= positional_patterns ["," keyword_patterns] - | keyword_patterns - positional_patterns ::= ",".pattern+ - keyword_patterns ::= ",".keyword_pattern+ - keyword_pattern ::= NAME "=" pattern + **class_pattern**: "name_or_attr" "(" ["pattern_arguments" ","?] ")" + **pattern_arguments**: "positional_patterns" ["," "keyword_patterns"] + | "keyword_patterns" + **positional_patterns**: ","."pattern"+ + **keyword_patterns**: ","."keyword_pattern"+ + **keyword_pattern**: NAME "=" "pattern" The same keyword should not be repeated in class patterns. @@ -2690,20 +2690,22 @@ class attributes; they are shared by instances. Instance attributes A function definition defines a user-defined function object (see section The standard type hierarchy): - funcdef ::= [decorators] "def" funcname [type_params] "(" [parameter_list] ")" - ["->" expression] ":" suite - decorators ::= decorator+ - decorator ::= "@" assignment_expression NEWLINE - parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]] - | parameter_list_no_posonly - parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]] - | parameter_list_starargs - parameter_list_starargs ::= "*" [star_parameter] ("," defparameter)* ["," ["**" parameter [","]]] - | "**" parameter [","] - parameter ::= identifier [":" expression] - star_parameter ::= identifier [":" ["*"] expression] - defparameter ::= parameter ["=" expression] - funcname ::= identifier + **funcdef**: ["decorators"] "def" "funcname" ["type_params"] "(" ["parameter_list"] ")" + ["->" "expression"] ":" "suite" + **decorators**: "decorator"+ + **decorator**: "@" "assignment_expression" NEWLINE + **parameter_list**: "defparameter" ("," "defparameter")* "," "/" ["," ["parameter_list_no_posonly"]] + | "parameter_list_no_posonly" + **parameter_list_no_posonly**: "defparameter" ("," "defparameter")* ["," ["parameter_list_starargs"]] + | "parameter_list_starargs" + **parameter_list_starargs**: "*" ["star_parameter"] ("," "defparameter")* ["," ["parameter_star_kwargs"]] + "*" ("," "defparameter")+ ["," ["parameter_star_kwargs"]] + | "parameter_star_kwargs" + **parameter_star_kwargs**: "**" "parameter" [","] + **parameter**: "identifier" [":" "expression"] + **star_parameter**: "identifier" [":" ["*"] "expression"] + **defparameter**: "parameter" ["=" "expression"] + **funcname**: "identifier" A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object @@ -2843,9 +2845,9 @@ def whats_on_the_telly(penguin=None): A class definition defines a class object (see section The standard type hierarchy): - classdef ::= [decorators] "class" classname [type_params] [inheritance] ":" suite - inheritance ::= "(" [argument_list] ")" - classname ::= identifier + **classdef**: ["decorators"] "class" "classname" ["type_params"] ["inheritance"] ":" "suite" + **inheritance**: "(" ["argument_list"] ")" + **classname**: "identifier" A class definition is an executable statement. The inheritance list usually gives a list of base classes (see Metaclasses for more @@ -2935,8 +2937,8 @@ class attributes; they are shared by instances. Instance attributes Coroutine function definition ----------------------------- - async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" - ["->" expression] ":" suite + **async_funcdef**: ["decorators"] "async" "def" "funcname" "(" ["parameter_list"] ")" + ["->" "expression"] ":" "suite" Execution of Python coroutines can be suspended and resumed at many points (see *coroutine*). "await" expressions, "async for" and "async @@ -2962,7 +2964,7 @@ async def func(param1, param2): The "async for" statement ------------------------- - async_for_stmt ::= "async" for_stmt + **async_for_stmt**: "async" "for_stmt" An *asynchronous iterable* provides an "__aiter__" method that directly returns an *asynchronous iterator*, which can call @@ -3003,7 +3005,7 @@ async def func(param1, param2): The "async with" statement -------------------------- - async_with_stmt ::= "async" with_stmt + **async_with_stmt**: "async" "with_stmt" An *asynchronous context manager* is a *context manager* that is able to suspend execution in its *enter* and *exit* methods. @@ -3052,11 +3054,11 @@ async def func(param1, param2): Changed in version 3.13: Support for default values was added (see **PEP 696**). - type_params ::= "[" type_param ("," type_param)* "]" - type_param ::= typevar | typevartuple | paramspec - typevar ::= identifier (":" expression)? ("=" expression)? - typevartuple ::= "*" identifier ("=" expression)? - paramspec ::= "**" identifier ("=" expression)? + **type_params**: "[" "type_param" ("," "type_param")* "]" + **type_param**: "typevar" | "typevartuple" | "paramspec" + **typevar**: "identifier" (":" "expression")? ("=" "expression")? + **typevartuple**: "*" "identifier" ("=" "expression")? + **paramspec**: "**" "identifier" ("=" "expression")? Functions (including coroutines), classes and type aliases may contain a type parameter list: @@ -3422,7 +3424,7 @@ def f() -> annotation: ... 'continue': r'''The "continue" statement ************************ - continue_stmt ::= "continue" + **continue_stmt**: "continue" "continue" may only occur syntactically nested in a "for" or "while" loop, but not nested in a function or class definition within that @@ -3948,9 +3950,9 @@ class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None, nosigint=Fa originate in a module that matches one of these patterns. [1] By default, Pdb sets a handler for the SIGINT signal (which is sent - when the user presses "Ctrl"-"C" on the console) when you give a + when the user presses "Ctrl-C" on the console) when you give a "continue" command. This allows you to break into the debugger - again by pressing "Ctrl"-"C". If you want Pdb not to touch the + again by pressing "Ctrl-C". If you want Pdb not to touch the SIGINT handler, set *nosigint* to true. The *readrc* argument defaults to true and controls whether Pdb @@ -4418,7 +4420,17 @@ class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None, nosigint=Fa q(uit) - Quit from the debugger. The program being executed is aborted. + Quit from the debugger. The program being executed is aborted. An + end-of-file input is equivalent to "quit". + + A confirmation prompt will be shown if the debugger is invoked in + "'inline'" mode. Either "y", "Y", "" or "EOF" will confirm + the quit. + + Changed in version 3.14: A confirmation prompt will be shown if the + debugger is invoked in "'inline'" mode. After the confirmation, the + debugger will call "sys.exit()" immediately, instead of raising + "bdb.BdbQuit" in the next trace event. debug code @@ -4486,7 +4498,7 @@ def inner(x): 'del': r'''The "del" statement ******************* - del_stmt ::= "del" target_list + **del_stmt**: "del" "target_list" Deletion is recursively defined very similar to the way assignment is defined. Rather than spelling it out in full details, here are some @@ -4515,10 +4527,10 @@ def inner(x): A dictionary display is a possibly empty series of dict items (key/value pairs) enclosed in curly braces: - dict_display ::= "{" [dict_item_list | dict_comprehension] "}" - dict_item_list ::= dict_item ("," dict_item)* [","] - dict_item ::= expression ":" expression | "**" or_expr - dict_comprehension ::= expression ":" expression comp_for + **dict_display**: "{" ["dict_item_list" | "dict_comprehension"] "}" + **dict_item_list**: "dict_item" ("," "dict_item")* [","] + **dict_item**: "expression" ":" "expression" | "**" "or_expr" + **dict_comprehension**: "expression" ":" "expression" "comp_for" A dictionary display yields a new dictionary object. @@ -4579,9 +4591,9 @@ def f(): The "if" statement is used for conditional execution: - if_stmt ::= "if" assignment_expression ":" suite - ("elif" assignment_expression ":" suite)* - ["else" ":" suite] + **if_stmt**: "if" "assignment_expression" ":" "suite" + ("elif" "assignment_expression" ":" "suite")* + ["else" ":" "suite"] It selects exactly one of the suites by evaluating the expressions one by one until one is found to be true (see section Boolean operations @@ -5000,12 +5012,12 @@ class of the instance or a *non-virtual base class* thereof. The 'exprlists': r'''Expression lists **************** - starred_expression ::= ["*"] or_expr - flexible_expression ::= assignment_expression | starred_expression - flexible_expression_list ::= flexible_expression ("," flexible_expression)* [","] - starred_expression_list ::= starred_expression ("," starred_expression)* [","] - expression_list ::= expression ("," expression)* [","] - yield_list ::= expression_list | starred_expression "," [starred_expression_list] + **starred_expression**: ["*"] "or_expr" + **flexible_expression**: "assignment_expression" | "starred_expression" + **flexible_expression_list**: "flexible_expression" ("," "flexible_expression")* [","] + **starred_expression_list**: "starred_expression" ("," "starred_expression")* [","] + **expression_list**: "expression" ("," "expression")* [","] + **yield_list**: "expression_list" | "starred_expression" "," ["starred_expression_list"] Except when part of a list or set display, an expression list containing at least one comma yields a tuple. The length of the tuple @@ -5035,12 +5047,12 @@ class of the instance or a *non-virtual base class* thereof. The Floating-point literals are described by the following lexical definitions: - floatnumber ::= pointfloat | exponentfloat - pointfloat ::= [digitpart] fraction | digitpart "." - exponentfloat ::= (digitpart | pointfloat) exponent - digitpart ::= digit (["_"] digit)* - fraction ::= "." digitpart - exponent ::= ("e" | "E") ["+" | "-"] digitpart + **floatnumber**: "pointfloat" | "exponentfloat" + **pointfloat**: ["digitpart"] "fraction" | "digitpart" "." + **exponentfloat**: ("digitpart" | "pointfloat") "exponent" + **digitpart**: "digit" (["_"] "digit")* + **fraction**: "." "digitpart" + **exponent**: ("e" | "E") ["+" | "-"] "digitpart" Note that the integer and exponent parts are always interpreted using radix 10. For example, "077e010" is legal, and denotes the same number @@ -5061,8 +5073,8 @@ class of the instance or a *non-virtual base class* thereof. The The "for" statement is used to iterate over the elements of a sequence (such as a string, tuple or list) or other iterable object: - for_stmt ::= "for" target_list "in" starred_list ":" suite - ["else" ":" suite] + **for_stmt**: "for" "target_list" "in" "starred_list" ":" "suite" + ["else" ":" "suite"] The "starred_list" expression is evaluated once; it should yield an *iterable* object. An *iterator* is created for that iterable. The @@ -5116,14 +5128,14 @@ class of the instance or a *non-virtual base class* thereof. The The grammar for a replacement field is as follows: - replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}" - field_name ::= arg_name ("." attribute_name | "[" element_index "]")* - arg_name ::= [identifier | digit+] - attribute_name ::= identifier - element_index ::= digit+ | index_string - index_string ::= + - conversion ::= "r" | "s" | "a" - format_spec ::= format-spec:format_spec + **replacement_field**: "{" ["field_name"] ["!" "conversion"] [":" "format_spec"] "}" + **field_name**: "arg_name" ("." "attribute_name" | "[" "element_index" "]")* + **arg_name**: ["identifier" | "digit"+] + **attribute_name**: "identifier" + **element_index**: "digit"+ | "index_string" + **index_string**: + + **conversion**: "r" | "s" | "a" + **format_spec**: "format-spec:format_spec" In less formal terms, the replacement field can start with a *field_name* that specifies the object whose value is to be formatted @@ -5220,14 +5232,14 @@ class of the instance or a *non-virtual base class* thereof. The The general form of a *standard format specifier* is: - format_spec ::= [[fill]align][sign]["z"]["#"]["0"][width][grouping_option]["." precision][type] - fill ::= - align ::= "<" | ">" | "=" | "^" - sign ::= "+" | "-" | " " - width ::= digit+ - grouping_option ::= "_" | "," - precision ::= digit+ - type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" + **format_spec**: [["fill"]"align"]["sign"]["z"]["#"]["0"]["width"]["grouping_option"]["." "precision"]["type"] + **fill**: + **align**: "<" | ">" | "=" | "^" + **sign**: "+" | "-" | " " + **width**: "digit"+ + **grouping_option**: "_" | "," + **precision**: "digit"+ + **type**: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" If a valid *align* value is specified, it can be preceded by a *fill* character that can be any character and defaults to a space if @@ -5621,20 +5633,22 @@ class of the instance or a *non-virtual base class* thereof. The A function definition defines a user-defined function object (see section The standard type hierarchy): - funcdef ::= [decorators] "def" funcname [type_params] "(" [parameter_list] ")" - ["->" expression] ":" suite - decorators ::= decorator+ - decorator ::= "@" assignment_expression NEWLINE - parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]] - | parameter_list_no_posonly - parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]] - | parameter_list_starargs - parameter_list_starargs ::= "*" [star_parameter] ("," defparameter)* ["," ["**" parameter [","]]] - | "**" parameter [","] - parameter ::= identifier [":" expression] - star_parameter ::= identifier [":" ["*"] expression] - defparameter ::= parameter ["=" expression] - funcname ::= identifier + **funcdef**: ["decorators"] "def" "funcname" ["type_params"] "(" ["parameter_list"] ")" + ["->" "expression"] ":" "suite" + **decorators**: "decorator"+ + **decorator**: "@" "assignment_expression" NEWLINE + **parameter_list**: "defparameter" ("," "defparameter")* "," "/" ["," ["parameter_list_no_posonly"]] + | "parameter_list_no_posonly" + **parameter_list_no_posonly**: "defparameter" ("," "defparameter")* ["," ["parameter_list_starargs"]] + | "parameter_list_starargs" + **parameter_list_starargs**: "*" ["star_parameter"] ("," "defparameter")* ["," ["parameter_star_kwargs"]] + "*" ("," "defparameter")+ ["," ["parameter_star_kwargs"]] + | "parameter_star_kwargs" + **parameter_star_kwargs**: "**" "parameter" [","] + **parameter**: "identifier" [":" "expression"] + **star_parameter**: "identifier" [":" ["*"] "expression"] + **defparameter**: "parameter" ["=" "expression"] + **funcname**: "identifier" A function definition is an executable statement. Its execution binds the function name in the current local namespace to a function object @@ -5770,7 +5784,7 @@ def whats_on_the_telly(penguin=None): 'global': r'''The "global" statement ********************** - global_stmt ::= "global" identifier ("," identifier)* + **global_stmt**: "global" "identifier" ("," "identifier")* The "global" statement causes the listed identifiers to be interpreted as globals. It would be impossible to assign to a global variable @@ -5853,11 +5867,11 @@ class body. A "SyntaxError" is raised if a variable is used or Identifiers are unlimited in length. Case is significant. - identifier ::= xid_start xid_continue* - id_start ::= - id_continue ::= - xid_start ::= - xid_continue ::= + **identifier**: "xid_start" "xid_continue"* + **id_start**: + **id_continue**: + **xid_start**: + **xid_continue**: The Unicode category codes mentioned above stand for: @@ -5978,9 +5992,9 @@ class body. A "SyntaxError" is raised if a variable is used or The "if" statement is used for conditional execution: - if_stmt ::= "if" assignment_expression ":" suite - ("elif" assignment_expression ":" suite)* - ["else" ":" suite] + **if_stmt**: "if" "assignment_expression" ":" "suite" + ("elif" "assignment_expression" ":" "suite")* + ["else" ":" "suite"] It selects exactly one of the suites by evaluating the expressions one by one until one is found to be true (see section Boolean operations @@ -5994,7 +6008,7 @@ class body. A "SyntaxError" is raised if a variable is used or Imaginary literals are described by the following lexical definitions: - imagnumber ::= (floatnumber | digitpart) ("j" | "J") + **imagnumber**: ("floatnumber" | "digitpart") ("j" | "J") An imaginary literal yields a complex number with a real part of 0.0. Complex numbers are represented as a pair of floating-point numbers @@ -6007,14 +6021,14 @@ class body. A "SyntaxError" is raised if a variable is used or 'import': r'''The "import" statement ********************** - import_stmt ::= "import" module ["as" identifier] ("," module ["as" identifier])* - | "from" relative_module "import" identifier ["as" identifier] - ("," identifier ["as" identifier])* - | "from" relative_module "import" "(" identifier ["as" identifier] - ("," identifier ["as" identifier])* [","] ")" - | "from" relative_module "import" "*" - module ::= (identifier ".")* identifier - relative_module ::= "."* module | "."+ + **import_stmt**: "import" "module" ["as" "identifier"] ("," "module" ["as" "identifier"])* + | "from" "relative_module" "import" "identifier" ["as" "identifier"] + ("," "identifier" ["as" "identifier"])* + | "from" "relative_module" "import" "(" "identifier" ["as" "identifier"] + ("," "identifier" ["as" "identifier"])* [","] ")" + | "from" "relative_module" "import" "*" + **module**: ("identifier" ".")* "identifier" + **relative_module**: "."* "module" | "."+ The basic import statement (no "from" clause) is executed in two steps: @@ -6133,11 +6147,11 @@ class body. A "SyntaxError" is raised if a variable is used or allows use of the new features on a per-module basis before the release in which the feature becomes standard. - future_stmt ::= "from" "__future__" "import" feature ["as" identifier] - ("," feature ["as" identifier])* - | "from" "__future__" "import" "(" feature ["as" identifier] - ("," feature ["as" identifier])* [","] ")" - feature ::= identifier + **future_stmt**: "from" "__future__" "import" "feature" ["as" "identifier"] + ("," "feature" ["as" "identifier"])* + | "from" "__future__" "import" "(" "feature" ["as" "identifier"] + ("," "feature" ["as" "identifier"])* [","] ")" + **feature**: "identifier" A future statement must appear near the top of the module. The only lines that can appear before a future statement are: @@ -6246,16 +6260,16 @@ class body. A "SyntaxError" is raised if a variable is used or Integer literals are described by the following lexical definitions: - integer ::= decinteger | bininteger | octinteger | hexinteger - decinteger ::= nonzerodigit (["_"] digit)* | "0"+ (["_"] "0")* - bininteger ::= "0" ("b" | "B") (["_"] bindigit)+ - octinteger ::= "0" ("o" | "O") (["_"] octdigit)+ - hexinteger ::= "0" ("x" | "X") (["_"] hexdigit)+ - nonzerodigit ::= "1"..."9" - digit ::= "0"..."9" - bindigit ::= "0" | "1" - octdigit ::= "0"..."7" - hexdigit ::= digit | "a"..."f" | "A"..."F" + **integer**: "decinteger" | "bininteger" | "octinteger" | "hexinteger" + **decinteger**: "nonzerodigit" (["_"] "digit")* | "0"+ (["_"] "0")* + **bininteger**: "0" ("b" | "B") (["_"] "bindigit")+ + **octinteger**: "0" ("o" | "O") (["_"] "octdigit")+ + **hexinteger**: "0" ("x" | "X") (["_"] "hexdigit")+ + **nonzerodigit**: "1"..."9" + **digit**: "0"..."9" + **bindigit**: "0" | "1" + **octdigit**: "0"..."7" + **hexdigit**: "digit" | "a"..."f" | "A"..."F" There is no limit for the length of integer literals apart from what can be stored in available memory. @@ -6281,7 +6295,7 @@ class body. A "SyntaxError" is raised if a variable is used or 'lambda': r'''Lambdas ******* - lambda_expr ::= "lambda" [parameter_list] ":" expression + **lambda_expr**: "lambda" ["parameter_list"] ":" "expression" Lambda expressions (sometimes called lambda forms) are used to create anonymous functions. The expression "lambda parameters: expression" @@ -6301,7 +6315,7 @@ def (parameters): A list display is a possibly empty series of expressions enclosed in square brackets: - list_display ::= "[" [flexible_expression_list | comprehension] "]" + **list_display**: "[" ["flexible_expression_list" | "comprehension"] "]" A list display yields a new list object, the contents being specified by either a list of expressions or a comprehension. When a comma- @@ -6594,7 +6608,7 @@ def f(): 'nonlocal': r'''The "nonlocal" statement ************************ - nonlocal_stmt ::= "nonlocal" identifier ("," identifier)* + **nonlocal_stmt**: "nonlocal" "identifier" ("," "identifier")* When the definition of a function or class is nested (enclosed) within the definitions of other functions, its nonlocal scopes are the local @@ -6981,7 +6995,7 @@ class that has an "__rsub__()" method, "type(y).__rsub__(y, x)" is 'pass': r'''The "pass" statement ******************** - pass_stmt ::= "pass" + **pass_stmt**: "pass" "pass" is a null operation — when it is executed, nothing happens. It is useful as a placeholder when a statement is required syntactically, @@ -6998,7 +7012,7 @@ class C: pass # a class with no methods (yet) left; it binds less tightly than unary operators on its right. The syntax is: - power ::= (await_expr | primary) ["**" u_expr] + **power**: ("await_expr" | "primary") ["**" "u_expr"] Thus, in an unparenthesized sequence of power and unary operators, the operators are evaluated from right to left (this does not constrain @@ -7024,7 +7038,7 @@ class C: pass # a class with no methods (yet) 'raise': r'''The "raise" statement ********************* - raise_stmt ::= "raise" [expression ["from" expression]] + **raise_stmt**: "raise" ["expression" ["from" "expression"]] If no expressions are present, "raise" re-raises the exception that is currently being handled, which is also known as the *active @@ -7126,7 +7140,7 @@ class C: pass # a class with no methods (yet) 'return': r'''The "return" statement ********************** - return_stmt ::= "return" [expression_list] + **return_stmt**: "return" ["expression_list"] "return" may only occur syntactically nested in a function definition, not within a nested class definition. @@ -7311,7 +7325,7 @@ class C: pass # a class with no methods (yet) The shifting operations have lower priority than the arithmetic operations: - shift_expr ::= a_expr | shift_expr ("<<" | ">>") a_expr + **shift_expr**: "a_expr" | "shift_expr" ("<<" | ">>") "a_expr" These operators accept integers as arguments. They shift the first argument to the left or right by the number of bits given by the @@ -7332,13 +7346,13 @@ class C: pass # a class with no methods (yet) string, tuple or list). Slicings may be used as expressions or as targets in assignment or "del" statements. The syntax for a slicing: - slicing ::= primary "[" slice_list "]" - slice_list ::= slice_item ("," slice_item)* [","] - slice_item ::= expression | proper_slice - proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ] - lower_bound ::= expression - upper_bound ::= expression - stride ::= expression + **slicing**: "primary" "[" "slice_list" "]" + **slice_list**: "slice_item" ("," "slice_item")* [","] + **slice_item**: "expression" | "proper_slice" + **proper_slice**: ["lower_bound"] ":" ["upper_bound"] [ ":" ["stride"] ] + **lower_bound**: "expression" + **upper_bound**: "expression" + **stride**: "expression" There is ambiguity in the formal syntax here: anything that looks like an expression list also looks like a slice list, so any subscription @@ -9725,26 +9739,26 @@ class is used in a class pattern with positional arguments, each String literals are described by the following lexical definitions: - stringliteral ::= [stringprefix](shortstring | longstring) - stringprefix ::= "r" | "u" | "R" | "U" | "f" | "F" + **stringliteral**: ["stringprefix"]("shortstring" | "longstring") + **stringprefix**: "r" | "u" | "R" | "U" | "f" | "F" | "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF" - shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"' - longstring ::= "\'\'\'" longstringitem* "\'\'\'" | '"""' longstringitem* '"""' - shortstringitem ::= shortstringchar | stringescapeseq - longstringitem ::= longstringchar | stringescapeseq - shortstringchar ::= - longstringchar ::= - stringescapeseq ::= "\\" - - bytesliteral ::= bytesprefix(shortbytes | longbytes) - bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB" - shortbytes ::= "'" shortbytesitem* "'" | '"' shortbytesitem* '"' - longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | '"""' longbytesitem* '"""' - shortbytesitem ::= shortbyteschar | bytesescapeseq - longbytesitem ::= longbyteschar | bytesescapeseq - shortbyteschar ::= - longbyteschar ::= - bytesescapeseq ::= "\\" + **shortstring**: "'" "shortstringitem"* "'" | '"' "shortstringitem"* '"' + **longstring**: "\'\'\'" "longstringitem"* "\'\'\'" | '"""' "longstringitem"* '"""' + **shortstringitem**: "shortstringchar" | "stringescapeseq" + **longstringitem**: "longstringchar" | "stringescapeseq" + **shortstringchar**: + **longstringchar**: + **stringescapeseq**: "\\" + + **bytesliteral**: "bytesprefix"("shortbytes" | "longbytes") + **bytesprefix**: "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB" + **shortbytes**: "'" "shortbytesitem"* "'" | '"' "shortbytesitem"* '"' + **longbytes**: "\'\'\'" "longbytesitem"* "\'\'\'" | '"""' "longbytesitem"* '"""' + **shortbytesitem**: "shortbyteschar" | "bytesescapeseq" + **longbytesitem**: "longbyteschar" | "bytesescapeseq" + **shortbyteschar**: + **longbyteschar**: + **bytesescapeseq**: "\\" One syntactic restriction not indicated by these productions is that whitespace is not allowed between the "stringprefix" or "bytesprefix" @@ -9908,7 +9922,7 @@ class is used in a class pattern with positional arguments, each select an element from the container. The subscription of a *generic class* will generally return a GenericAlias object. - subscription ::= primary "[" flexible_expression_list "]" + **subscription**: "primary" "[" "flexible_expression_list" "]" When an object is subscripted, the interpreter will evaluate the primary and the expression list. @@ -9988,17 +10002,17 @@ class is used in a class pattern with positional arguments, each The "try" statement specifies exception handlers and/or cleanup code for a group of statements: - try_stmt ::= try1_stmt | try2_stmt | try3_stmt - try1_stmt ::= "try" ":" suite - ("except" [expression ["as" identifier]] ":" suite)+ - ["else" ":" suite] - ["finally" ":" suite] - try2_stmt ::= "try" ":" suite - ("except" "*" expression ["as" identifier] ":" suite)+ - ["else" ":" suite] - ["finally" ":" suite] - try3_stmt ::= "try" ":" suite - "finally" ":" suite + **try_stmt**: "try1_stmt" | "try2_stmt" | "try3_stmt" + **try1_stmt**: "try" ":" "suite" + ("except" ["expression" ["as" "identifier"]] ":" "suite")+ + ["else" ":" "suite"] + ["finally" ":" "suite"] + **try2_stmt**: "try" ":" "suite" + ("except" "*" "expression" ["as" "identifier"] ":" "suite")+ + ["else" ":" "suite"] + ["finally" ":" "suite"] + **try3_stmt**: "try" ":" "suite" + "finally" ":" "suite" Additional information on exceptions can be found in section Exceptions, and information on using the "raise" statement to generate @@ -12607,7 +12621,7 @@ class range(start, stop[, step]) All unary arithmetic and bitwise operations have the same priority: - u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr + **u_expr**: "power" | "-" "u_expr" | "+" "u_expr" | "~" "u_expr" The unary "-" (minus) operator yields the negation of its numeric argument; the operation can be overridden with the "__neg__()" special @@ -12630,8 +12644,8 @@ class range(start, stop[, step]) The "while" statement is used for repeated execution as long as an expression is true: - while_stmt ::= "while" assignment_expression ":" suite - ["else" ":" suite] + **while_stmt**: "while" "assignment_expression" ":" "suite" + ["else" ":" "suite"] This repeatedly tests the expression and, if it is true, executes the first suite; if the expression is false (which may be the first time @@ -12651,9 +12665,9 @@ class range(start, stop[, step]) Context Managers). This allows common "try"…"except"…"finally" usage patterns to be encapsulated for convenient reuse. - with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite - with_stmt_contents ::= with_item ("," with_item)* - with_item ::= expression ["as" target] + **with_stmt**: "with" ( "(" "with_stmt_contents" ","? ")" | "with_stmt_contents" ) ":" "suite" + **with_stmt_contents**: "with_item" ("," "with_item")* + **with_item**: "expression" ["as" "target"] The execution of the "with" statement with one “item” proceeds as follows: @@ -12754,7 +12768,7 @@ class range(start, stop[, step]) 'yield': r'''The "yield" statement ********************* - yield_stmt ::= yield_expression + **yield_stmt**: "yield_expression" A "yield" statement is semantically equivalent to a yield expression. The "yield" statement can be used to omit the parentheses that would diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 69f72452c4069a..18e6b8d25e5b56 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -666,34 +666,34 @@ def get_platform(): # Set for cross builds explicitly if "_PYTHON_HOST_PLATFORM" in os.environ: - return os.environ["_PYTHON_HOST_PLATFORM"] - - # Try to distinguish various flavours of Unix - osname, host, release, version, machine = os.uname() - - # Convert the OS name to lowercase, remove '/' characters, and translate - # spaces (for "Power Macintosh") - osname = osname.lower().replace('/', '') - machine = machine.replace(' ', '_') - machine = machine.replace('/', '-') - - if osname[:5] == "linux": - if sys.platform == "android": - osname = "android" - release = get_config_var("ANDROID_API_LEVEL") - - # Wheel tags use the ABI names from Android's own tools. - machine = { - "x86_64": "x86_64", - "i686": "x86", - "aarch64": "arm64_v8a", - "armv7l": "armeabi_v7a", - }[machine] - else: - # At least on Linux/Intel, 'machine' is the processor -- - # i386, etc. - # XXX what about Alpha, SPARC, etc? - return f"{osname}-{machine}" + osname, _, machine = os.environ["_PYTHON_HOST_PLATFORM"].partition('-') + release = None + else: + # Try to distinguish various flavours of Unix + osname, host, release, version, machine = os.uname() + + # Convert the OS name to lowercase, remove '/' characters, and translate + # spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_') + machine = machine.replace('/', '-') + + if osname == "android" or sys.platform == "android": + osname = "android" + release = get_config_var("ANDROID_API_LEVEL") + + # Wheel tags use the ABI names from Android's own tools. + machine = { + "x86_64": "x86_64", + "i686": "x86", + "aarch64": "arm64_v8a", + "armv7l": "armeabi_v7a", + }[machine] + elif osname == "linux": + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return f"{osname}-{machine}" elif osname[:5] == "sunos": if release[0] >= "5": # SunOS 5 == Solaris 2 osname = "solaris" @@ -725,7 +725,7 @@ def get_platform(): get_config_vars(), osname, release, machine) - return f"{osname}-{release}-{machine}" + return '-'.join(map(str, filter(None, (osname, release, machine)))) def get_python_version(): diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 25a3015c4e19ce..d1ef6339789d20 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1962,6 +1962,23 @@ def test_backdoor_resistance(self): # blow up because other fields are insane. self.theclass(base[:2] + bytes([ord_byte]) + base[3:]) + def test_valuerror_messages(self): + pattern = re.compile( + r"(year|month|day) must be in \d+\.\.\d+, not \d+" + ) + test_cases = [ + (2009, 1, 32), # Day out of range + (2009, 2, 31), # Day out of range + (2009, 13, 1), # Month out of range + (2009, 0, 1), # Month out of range + (10000, 12, 31), # Year out of range + (0, 12, 31), # Year out of range + ] + for case in test_cases: + with self.subTest(case): + with self.assertRaisesRegex(ValueError, pattern): + self.theclass(*case) + def test_fromisoformat(self): # Test that isoformat() is reversible base_dates = [ @@ -3212,6 +3229,24 @@ class DateTimeSubclass(self.theclass): self.assertEqual(res.year, 2013) self.assertEqual(res.fold, fold) + def test_valuerror_messages(self): + pattern = re.compile( + r"(year|month|day|hour|minute|second) must " + r"be in \d+\.\.\d+, not \d+" + ) + test_cases = [ + (2009, 4, 1, 12, 30, 90), # Second out of range + (2009, 4, 1, 12, 90, 45), # Minute out of range + (2009, 4, 1, 25, 30, 45), # Hour out of range + (2009, 4, 32, 24, 0, 0), # Day out of range + (2009, 13, 1, 24, 0, 0), # Month out of range + (9999, 12, 31, 24, 0, 0), # Year out of range + ] + for case in test_cases: + with self.subTest(case): + with self.assertRaisesRegex(ValueError, pattern): + self.theclass(*case) + def test_fromisoformat_datetime(self): # Test that isoformat() is reversible base_dates = [ @@ -3505,6 +3540,25 @@ def test_fromisoformat_fails_datetime(self): with self.assertRaises(ValueError): self.theclass.fromisoformat(bad_str) + def test_fromisoformat_fails_datetime_valueerror(self): + pattern = re.compile( + r"(year|month|day|hour|minute|second) must " + r"be in \d+\.\.\d+, not \d+" + ) + bad_strs = [ + "2009-04-01T12:30:90", # Second out of range + "2009-04-01T12:90:45", # Minute out of range + "2009-04-01T25:30:45", # Hour out of range + "2009-04-32T24:00:00", # Day out of range + "2009-13-01T24:00:00", # Month out of range + "9999-12-31T24:00:00", # Year out of range + ] + + for bad_str in bad_strs: + with self.subTest(bad_str=bad_str): + with self.assertRaisesRegex(ValueError, pattern): + self.theclass.fromisoformat(bad_str) + def test_fromisoformat_fails_surrogate(self): # Test that when fromisoformat() fails with a surrogate character as # the separator, the error message contains the original string @@ -4481,6 +4535,21 @@ def utcoffset(self, t): t2 = t2.replace(tzinfo=Varies()) self.assertTrue(t1 < t2) # t1's offset counter still going up + def test_valuerror_messages(self): + pattern = re.compile( + r"(hour|minute|second|microsecond) must be in \d+\.\.\d+, not \d+" + ) + test_cases = [ + (12, 30, 90, 9999991), # Microsecond out of range + (12, 30, 90, 000000), # Second out of range + (25, 30, 45, 000000), # Hour out of range + (12, 90, 45, 000000), # Minute out of range + ] + for case in test_cases: + with self.subTest(case): + with self.assertRaisesRegex(ValueError, pattern): + self.theclass(*case) + def test_fromisoformat(self): time_examples = [ (0, 0, 0, 0), diff --git a/Lib/test/libregrtest/tsan.py b/Lib/test/libregrtest/tsan.py index 10b12cce165931..2a656705d7b508 100644 --- a/Lib/test/libregrtest/tsan.py +++ b/Lib/test/libregrtest/tsan.py @@ -13,6 +13,7 @@ 'test_importlib', 'test_io', 'test_logging', + 'test_opcache', 'test_queue', 'test_signal', 'test_socket', @@ -20,6 +21,7 @@ 'test_ssl', 'test_syslog', 'test_thread', + 'test_thread_local_bytecode', 'test_threadedtempfile', 'test_threading', 'test_threading_local', diff --git a/Lib/test/libregrtest/worker.py b/Lib/test/libregrtest/worker.py index 0c9f5bd6e42f11..5d75bf7ae787ed 100644 --- a/Lib/test/libregrtest/worker.py +++ b/Lib/test/libregrtest/worker.py @@ -56,6 +56,15 @@ def create_worker_process(runtests: WorkerRunTests, output_fd: int, if USE_PROCESS_GROUP and test_name not in NEED_TTY: kwargs['start_new_session'] = True + # Include the test name in the TSAN log file name + if 'TSAN_OPTIONS' in env: + parts = env['TSAN_OPTIONS'].split(' ') + for i, part in enumerate(parts): + if part.startswith('log_path='): + parts[i] = f'{part}.{test_name}' + break + env['TSAN_OPTIONS'] = ' '.join(parts) + # Pass json_file to the worker process json_file = runtests.json_file json_file.configure_subprocess(kwargs) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index a438c8e81e4fd1..434f291eebe51b 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3239,46 +3239,6 @@ def test_folding_tuple(self): self.assert_ast(code, non_optimized_target, optimized_target) - def test_folding_comparator(self): - code = "1 %s %s1%s" - operators = [("in", ast.In()), ("not in", ast.NotIn())] - braces = [ - ("[", "]", ast.List, (1,)), - ("{", "}", ast.Set, frozenset({1})), - ] - for left, right, non_optimized_comparator, optimized_comparator in braces: - for op, node in operators: - non_optimized_target = self.wrap_expr(ast.Compare( - left=ast.Constant(1), ops=[node], - comparators=[non_optimized_comparator(elts=[ast.Constant(1)])] - )) - optimized_target = self.wrap_expr(ast.Compare( - left=ast.Constant(1), ops=[node], - comparators=[ast.Constant(value=optimized_comparator)] - )) - self.assert_ast(code % (op, left, right), non_optimized_target, optimized_target) - - def test_folding_iter(self): - code = "for _ in %s1%s: pass" - braces = [ - ("[", "]", ast.List, (1,)), - ("{", "}", ast.Set, frozenset({1})), - ] - - for left, right, ast_cls, optimized_iter in braces: - non_optimized_target = self.wrap_statement(ast.For( - target=ast.Name(id="_", ctx=ast.Store()), - iter=ast_cls(elts=[ast.Constant(1)]), - body=[ast.Pass()] - )) - optimized_target = self.wrap_statement(ast.For( - target=ast.Name(id="_", ctx=ast.Store()), - iter=ast.Constant(value=optimized_iter), - body=[ast.Pass()] - )) - - self.assert_ast(code % (left, right), non_optimized_target, optimized_target) - def test_folding_type_param_in_function_def(self): code = "def foo[%s = 1 + 1](): pass" diff --git a/Lib/test/test_build_details.py b/Lib/test/test_build_details.py new file mode 100644 index 00000000000000..05ce163a337881 --- /dev/null +++ b/Lib/test/test_build_details.py @@ -0,0 +1,128 @@ +import json +import os +import sys +import sysconfig +import string +import unittest + +from test.support import is_android, is_apple_mobile, is_emscripten, is_wasi + + +class FormatTestsBase: + @property + def contents(self): + """Install details file contents. Should be overriden by subclasses.""" + raise NotImplementedError + + @property + def data(self): + """Parsed install details file data, as a Python object.""" + return json.loads(self.contents) + + def key(self, name): + """Helper to fetch subsection entries. + + It takes the entry name, allowing the usage of a dot to separate the + different subsection names (eg. specifying 'a.b.c' as the key will + return the value of self.data['a']['b']['c']). + """ + value = self.data + for part in name.split('.'): + value = value[part] + return value + + def test_parse(self): + self.data + + def test_top_level_container(self): + self.assertIsInstance(self.data, dict) + for key, value in self.data.items(): + with self.subTest(key=key): + if key in ('schema_version', 'base_prefix', 'base_interpreter', 'platform'): + self.assertIsInstance(value, str) + elif key in ('language', 'implementation', 'abi', 'suffixes', 'libpython', 'c_api', 'arbitrary_data'): + self.assertIsInstance(value, dict) + + def test_base_prefix(self): + self.assertIsInstance(self.key('base_prefix'), str) + + def test_base_interpreter(self): + """Test the base_interpreter entry. + + The generic test wants the key to be missing. If your implementation + provides a value for it, you should override this test. + """ + with self.assertRaises(KeyError): + self.key('base_interpreter') + + def test_platform(self): + self.assertEqual(self.key('platform'), sysconfig.get_platform()) + + def test_language_version(self): + allowed_characters = string.digits + string.ascii_letters + '.' + value = self.key('language.version') + + self.assertLessEqual(set(value), set(allowed_characters)) + self.assertTrue(sys.version.startswith(value)) + + def test_language_version_info(self): + value = self.key('language.version_info') + + self.assertEqual(len(value), sys.version_info.n_fields) + for part_name, part_value in value.items(): + with self.subTest(part=part_name): + self.assertEqual(part_value, getattr(sys.version_info, part_name)) + + def test_implementation(self): + for key, value in self.key('implementation').items(): + with self.subTest(part=key): + if key == 'version': + self.assertEqual(len(value), len(sys.implementation.version)) + for part_name, part_value in value.items(): + self.assertEqual(getattr(sys.implementation.version, part_name), part_value) + else: + self.assertEqual(getattr(sys.implementation, key), value) + + +needs_installed_python = unittest.skipIf( + sysconfig.is_python_build(), + 'This test can only run in an installed Python', +) + + +@unittest.skipIf(os.name != 'posix', 'Feature only implemented on POSIX right now') +@unittest.skipIf(is_wasi or is_emscripten, 'Feature not available on WebAssembly builds') +class CPythonBuildDetailsTests(unittest.TestCase, FormatTestsBase): + """Test CPython's install details file implementation.""" + + @property + def location(self): + if sysconfig.is_python_build(): + projectdir = sysconfig.get_config_var('projectbase') + with open(os.path.join(projectdir, 'pybuilddir.txt')) as f: + dirname = os.path.join(projectdir, f.read()) + else: + dirname = sysconfig.get_path('stdlib') + return os.path.join(dirname, 'build-details.json') + + @property + def contents(self): + with open(self.location, 'r') as f: + return f.read() + + @needs_installed_python + def test_location(self): + self.assertTrue(os.path.isfile(self.location)) + + # Override generic format tests with tests for our specific implemenation. + + @needs_installed_python + @unittest.skipIf(is_android or is_apple_mobile, 'Android and iOS run tests via a custom testbed method that changes sys.executable') + def test_base_interpreter(self): + value = self.key('base_interpreter') + + self.assertEqual(os.path.realpath(value), os.path.realpath(sys.executable)) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index e7f3e46c1868f7..53dc9b1a7effb5 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -660,7 +660,7 @@ def test_syntaxerror_invalid_escape_sequence_multi_line(self): self.assertEqual( stderr.splitlines()[-3:], [ b' foo = """\\q"""', - b' ^^^^^^^^', + b' ^^', b'SyntaxError: "\\q" is an invalid escape sequence. ' b'Did you mean "\\\\q"? A raw string is also an option.' ], diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 6c3de2091c451d..8163b483d9603d 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -798,7 +798,7 @@ def check_same_constant(const): f3 = lambda x: x in {("not a name",)} self.assertIs(f1.__code__.co_consts[0], f2.__code__.co_consts[0][0]) - self.assertIs(next(iter(f3.__code__.co_consts[0])), + self.assertIs(next(iter(f3.__code__.co_consts[1])), f2.__code__.co_consts[0]) # {0} is converted to a constant frozenset({0}) by the peephole diff --git a/Lib/test/test_context.py b/Lib/test/test_context.py index 82d1797ab3b79e..f9cdcc3561e9d6 100644 --- a/Lib/test/test_context.py +++ b/Lib/test/test_context.py @@ -383,6 +383,115 @@ def sub(num): tp.shutdown() self.assertEqual(results, list(range(10))) + def test_token_contextmanager_with_default(self): + ctx = contextvars.Context() + c = contextvars.ContextVar('c', default=42) + + def fun(): + with c.set(36): + self.assertEqual(c.get(), 36) + + self.assertEqual(c.get(), 42) + + ctx.run(fun) + + def test_token_contextmanager_without_default(self): + ctx = contextvars.Context() + c = contextvars.ContextVar('c') + + def fun(): + with c.set(36): + self.assertEqual(c.get(), 36) + + with self.assertRaisesRegex(LookupError, " diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 3838eb5b27c9e6..7aa200ad8bee6c 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -2303,7 +2303,7 @@ def test_encodings(self): ) err = run_script(source.encode('cp437')) self.assertEqual(err[-3], ' "┬ó┬ó┬ó┬ó┬ó┬ó" + f(4, x for x in range(1))') - self.assertEqual(err[-2], ' ^^^^^^^^^^^^^^^^^^^') + self.assertEqual(err[-2], ' ^^^') # Check backwards tokenizer errors source = '# -*- coding: ascii -*-\n\n(\n' diff --git a/Lib/test/test_flufl.py b/Lib/test/test_flufl.py index fd264c926bd575..d77e481c81d598 100644 --- a/Lib/test/test_flufl.py +++ b/Lib/test/test_flufl.py @@ -34,6 +34,32 @@ def test_guido_as_bdfl(self): # parser reports the start of the token self.assertEqual(cm.exception.offset, 3) + def test_barry_as_bdfl_look_ma_with_no_compiler_flags(self): + # Check that the future import is handled by the parser + # even if the compiler flags are not passed. + code = "from __future__ import barry_as_FLUFL;2 {0} 3" + compile(code.format('<>'), '', 'exec') + with self.assertRaises(SyntaxError) as cm: + compile(code.format('!='), '', 'exec') + self.assertRegex(str(cm.exception), "with Barry as BDFL, use '<>' instead of '!='") + self.assertIn('2 != 3', cm.exception.text) + self.assertEqual(cm.exception.filename, '') + self.assertEqual(cm.exception.lineno, 1) + self.assertEqual(cm.exception.offset, len(code) - 4) + + def test_barry_as_bdfl_relative_import(self): + code = "from .__future__ import barry_as_FLUFL;2 {0} 3" + compile(code.format('!='), '', 'exec') + with self.assertRaises(SyntaxError) as cm: + compile(code.format('<>'), '', 'exec') + self.assertRegex(str(cm.exception), "") + self.assertIn('2 <> 3', cm.exception.text) + self.assertEqual(cm.exception.filename, '') + self.assertEqual(cm.exception.lineno, 1) + self.assertEqual(cm.exception.offset, len(code) - 4) + + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_free_threading/test_set.py b/Lib/test/test_free_threading/test_set.py new file mode 100644 index 00000000000000..a66e03bcc4c9d1 --- /dev/null +++ b/Lib/test/test_free_threading/test_set.py @@ -0,0 +1,41 @@ +import unittest + +from threading import Thread, Barrier +from unittest import TestCase + +from test.support import threading_helper + + +@threading_helper.requires_working_threading() +class TestSet(TestCase): + def test_repr_clear(self): + """Test repr() of a set while another thread is calling clear()""" + NUM_ITERS = 10 + NUM_REPR_THREADS = 10 + barrier = Barrier(NUM_REPR_THREADS + 1) + s = {1, 2, 3, 4, 5, 6, 7, 8} + + def clear_set(): + barrier.wait() + s.clear() + + def repr_set(): + barrier.wait() + set_reprs.append(repr(s)) + + for _ in range(NUM_ITERS): + set_reprs = [] + threads = [Thread(target=clear_set)] + for _ in range(NUM_REPR_THREADS): + threads.append(Thread(target=repr_set)) + for t in threads: + t.start() + for t in threads: + t.join() + + for set_repr in set_reprs: + self.assertIn(set_repr, ("set()", "{1, 2, 3, 4, 5, 6, 7, 8}")) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 1d96b7a2c2459b..f5111b38a45707 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -15,6 +15,7 @@ import types import decimal import unittest +import warnings from test import support from test.support.os_helper import temp_cwd from test.support.script_helper import assert_python_failure, assert_python_ok @@ -1650,8 +1651,9 @@ def __repr__(self): #self.assertEqual(f'X{x = }Y', 'Xx\t=\t'+repr(x)+'Y') def test_debug_expressions_are_raw_strings(self): - - self.assertEqual(f'{b"\N{OX}"=}', 'b"\\N{OX}"=b\'\\\\N{OX}\'') + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SyntaxWarning) + self.assertEqual(eval("""f'{b"\\N{OX}"=}'"""), 'b"\\N{OX}"=b\'\\\\N{OX}\'') self.assertEqual(f'{r"\xff"=}', 'r"\\xff"=\'\\\\xff\'') self.assertEqual(f'{r"\n"=}', 'r"\\n"=\'\\\\n\'') self.assertEqual(f"{'\''=}", "'\\''=\"'\"") diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 0e0f28be6b2af0..f9a54f3b412b4a 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -1723,6 +1723,7 @@ def test_stack_save_reload(self): input = """ inst(BALANCED, ( -- )) { SAVE_STACK(); + code(); RELOAD_STACK(); } """ @@ -1737,12 +1738,36 @@ def test_stack_save_reload(self): next_instr += 1; INSTRUCTION_STATS(BALANCED); _PyFrame_SetStackPointer(frame, stack_pointer); + code(); stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } """ self.run_cases_test(input, output) + def test_stack_save_reload_paired(self): + + input = """ + inst(BALANCED, ( -- )) { + SAVE_STACK(); + RELOAD_STACK(); + } + """ + + output = """ + TARGET(BALANCED) { + #if defined(Py_TAIL_CALL_INTERP) + int opcode = BALANCED; + (void)(opcode); + #endif + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BALANCED); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + def test_stack_reload_only(self): input = """ diff --git a/Lib/test/test_gettext.py b/Lib/test/test_gettext.py index b2fe3e28c3bec7..e517c9d5c2a53f 100644 --- a/Lib/test/test_gettext.py +++ b/Lib/test/test_gettext.py @@ -10,8 +10,6 @@ # TODO: # - Add new tests, for example for "dgettext" -# - Remove dummy tests, for example testing for single and double quotes -# has no sense, it would have if we were testing a parser (i.e. pygettext) # - Tests should have only one assert. GNU_MO_DATA = b'''\ @@ -175,30 +173,6 @@ def test_some_translations_with_context(self): eq(pgettext('my other context', 'nudge nudge'), 'wink wink (in "my other context")') - def test_double_quotes(self): - eq = self.assertEqual - # double quotes - eq(_("albatross"), 'albatross') - eq(_("mullusk"), 'bacon') - eq(_(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove') - eq(_(r"nudge nudge"), 'wink wink') - - def test_triple_single_quotes(self): - eq = self.assertEqual - # triple single quotes - eq(_('''albatross'''), 'albatross') - eq(_('''mullusk'''), 'bacon') - eq(_(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove') - eq(_(r'''nudge nudge'''), 'wink wink') - - def test_triple_double_quotes(self): - eq = self.assertEqual - # triple double quotes - eq(_("""albatross"""), 'albatross') - eq(_("""mullusk"""), 'bacon') - eq(_(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove') - eq(_(r"""nudge nudge"""), 'wink wink') - def test_multiline_strings(self): eq = self.assertEqual # multiline strings @@ -285,30 +259,6 @@ def test_some_translations_with_context_and_domain(self): eq(gettext.dpgettext('gettext', 'my other context', 'nudge nudge'), 'wink wink (in "my other context")') - def test_double_quotes(self): - eq = self.assertEqual - # double quotes - eq(self._("albatross"), 'albatross') - eq(self._("mullusk"), 'bacon') - eq(self._(r"Raymond Luxury Yach-t"), 'Throatwobbler Mangrove') - eq(self._(r"nudge nudge"), 'wink wink') - - def test_triple_single_quotes(self): - eq = self.assertEqual - # triple single quotes - eq(self._('''albatross'''), 'albatross') - eq(self._('''mullusk'''), 'bacon') - eq(self._(r'''Raymond Luxury Yach-t'''), 'Throatwobbler Mangrove') - eq(self._(r'''nudge nudge'''), 'wink wink') - - def test_triple_double_quotes(self): - eq = self.assertEqual - # triple double quotes - eq(self._("""albatross"""), 'albatross') - eq(self._("""mullusk"""), 'bacon') - eq(self._(r"""Raymond Luxury Yach-t"""), 'Throatwobbler Mangrove') - eq(self._(r"""nudge nudge"""), 'wink wink') - def test_multiline_strings(self): eq = self.assertEqual # multiline strings diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index d1b04128bf6df3..0c1680cfbce36b 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -253,6 +253,7 @@ def test_unknown_hash(self): def test_new_upper_to_lower(self): self.assertEqual(hashlib.new("SHA256").name, "sha256") + @support.thread_unsafe("modifies sys.modules") def test_get_builtin_constructor(self): get_builtin_constructor = getattr(hashlib, '__get_builtin_constructor') diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index ed92e5257df39e..4471c5129b96df 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -535,6 +535,83 @@ def test_folding_subscript(self): self.assertInBytecode(code, 'BINARY_OP', argval=subscr_argval) self.check_lnotab(code) + def test_constant_folding_remove_nop_location(self): + sources = [ + """ + (- + - + - + 1) + """, + + """ + (1 + + + 2 + + + 3) + """, + + """ + (1, + 2, + 3)[0] + """, + + """ + [1, + 2, + 3] + """, + + """ + {1, + 2, + 3} + """, + + """ + 1 in [ + 1, + 2, + 3 + ] + """, + + """ + 1 in { + 1, + 2, + 3 + } + """, + + """ + for _ in [1, + 2, + 3]: + pass + """, + + """ + for _ in [1, + 2, + x]: + pass + """, + + """ + for _ in {1, + 2, + 3}: + pass + """ + ] + + for source in sources: + code = compile(textwrap.dedent(source), '', 'single') + self.assertNotInBytecode(code, 'NOP') + def test_in_literal_list(self): def containtest(): return x in [a, b] @@ -1261,6 +1338,202 @@ def test_optimize_if_const_set(self): ] self.cfg_optimization_test(same, same, consts=[]) + def test_optimize_literal_list_for_iter(self): + # for _ in [1, 2]: pass ==> for _ in (1, 2): pass + before = [ + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_SMALL_INT', 2, 0), + ('BUILD_LIST', 2, 0), + ('GET_ITER', None, 0), + start := self.Label(), + ('FOR_ITER', end := self.Label(), 0), + ('STORE_FAST', 0, 0), + ('JUMP', start, 0), + end, + ('END_FOR', None, 0), + ('POP_ITER', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + after = [ + ('LOAD_CONST', 1, 0), + ('GET_ITER', None, 0), + start := self.Label(), + ('FOR_ITER', end := self.Label(), 0), + ('STORE_FAST', 0, 0), + ('JUMP', start, 0), + end, + ('END_FOR', None, 0), + ('POP_ITER', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(before, after, consts=[None], expected_consts=[None, (1, 2)]) + + # for _ in [1, x]: pass ==> for _ in (1, x): pass + before = [ + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_NAME', 0, 0), + ('BUILD_LIST', 2, 0), + ('GET_ITER', None, 0), + start := self.Label(), + ('FOR_ITER', end := self.Label(), 0), + ('STORE_FAST', 0, 0), + ('JUMP', start, 0), + end, + ('END_FOR', None, 0), + ('POP_ITER', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + after = [ + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_NAME', 0, 0), + ('BUILD_TUPLE', 2, 0), + ('GET_ITER', None, 0), + start := self.Label(), + ('FOR_ITER', end := self.Label(), 0), + ('STORE_FAST', 0, 0), + ('JUMP', start, 0), + end, + ('END_FOR', None, 0), + ('POP_ITER', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(before, after, consts=[None], expected_consts=[None]) + + def test_optimize_literal_set_for_iter(self): + # for _ in {1, 2}: pass ==> for _ in (1, 2): pass + before = [ + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_SMALL_INT', 2, 0), + ('BUILD_SET', 2, 0), + ('GET_ITER', None, 0), + start := self.Label(), + ('FOR_ITER', end := self.Label(), 0), + ('STORE_FAST', 0, 0), + ('JUMP', start, 0), + end, + ('END_FOR', None, 0), + ('POP_ITER', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + after = [ + ('LOAD_CONST', 1, 0), + ('GET_ITER', None, 0), + start := self.Label(), + ('FOR_ITER', end := self.Label(), 0), + ('STORE_FAST', 0, 0), + ('JUMP', start, 0), + end, + ('END_FOR', None, 0), + ('POP_ITER', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(before, after, consts=[None], expected_consts=[None, frozenset({1, 2})]) + + # non constant literal set is not changed + # for _ in {1, x}: pass ==> for _ in {1, x}: pass + same = [ + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_NAME', 0, 0), + ('BUILD_SET', 2, 0), + ('GET_ITER', None, 0), + start := self.Label(), + ('FOR_ITER', end := self.Label(), 0), + ('STORE_FAST', 0, 0), + ('JUMP', start, 0), + end, + ('END_FOR', None, 0), + ('POP_ITER', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(same, same, consts=[None], expected_consts=[None]) + + def test_optimize_literal_list_contains(self): + # x in [1, 2] ==> x in (1, 2) + before = [ + ('LOAD_NAME', 0, 0), + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_SMALL_INT', 2, 0), + ('BUILD_LIST', 2, 0), + ('CONTAINS_OP', 0, 0), + ('POP_TOP', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + after = [ + ('LOAD_NAME', 0, 0), + ('LOAD_CONST', 1, 0), + ('CONTAINS_OP', 0, 0), + ('POP_TOP', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(before, after, consts=[None], expected_consts=[None, (1, 2)]) + + # x in [1, y] ==> x in (1, y) + before = [ + ('LOAD_NAME', 0, 0), + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_NAME', 1, 0), + ('BUILD_LIST', 2, 0), + ('CONTAINS_OP', 0, 0), + ('POP_TOP', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + after = [ + ('LOAD_NAME', 0, 0), + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_NAME', 1, 0), + ('BUILD_TUPLE', 2, 0), + ('CONTAINS_OP', 0, 0), + ('POP_TOP', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(before, after, consts=[None], expected_consts=[None]) + + def test_optimize_literal_set_contains(self): + # x in {1, 2} ==> x in (1, 2) + before = [ + ('LOAD_NAME', 0, 0), + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_SMALL_INT', 2, 0), + ('BUILD_SET', 2, 0), + ('CONTAINS_OP', 0, 0), + ('POP_TOP', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + after = [ + ('LOAD_NAME', 0, 0), + ('LOAD_CONST', 1, 0), + ('CONTAINS_OP', 0, 0), + ('POP_TOP', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(before, after, consts=[None], expected_consts=[None, frozenset({1, 2})]) + + # non constant literal set is not changed + # x in {1, y} ==> x in {1, y} + same = [ + ('LOAD_NAME', 0, 0), + ('LOAD_SMALL_INT', 1, 0), + ('LOAD_NAME', 1, 0), + ('BUILD_SET', 2, 0), + ('CONTAINS_OP', 0, 0), + ('POP_TOP', None, 0), + ('LOAD_CONST', 0, 0), + ('RETURN_VALUE', None, 0), + ] + self.cfg_optimization_test(same, same, consts=[None], expected_consts=[None]) def test_conditional_jump_forward_const_condition(self): # The unreachable branch of the jump is removed, the jump diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py index 5bb2eff55ebc8f..3abc43a3b1afde 100644 --- a/Lib/test/test_sqlite3/test_userfunctions.py +++ b/Lib/test/test_sqlite3/test_userfunctions.py @@ -171,7 +171,7 @@ def tearDown(self): self.con.close() def test_func_error_on_create(self): - with self.assertRaises(sqlite.OperationalError): + with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"): self.con.create_function("bla", -100, lambda x: 2*x) def test_func_too_many_args(self): @@ -507,9 +507,8 @@ def test_win_sum_int(self): self.assertEqual(self.cur.fetchall(), self.expected) def test_win_error_on_create(self): - self.assertRaises(sqlite.ProgrammingError, - self.con.create_window_function, - "shouldfail", -100, WindowSumInt) + with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"): + self.con.create_window_function("shouldfail", -100, WindowSumInt) @with_tracebacks(BadWindow) def test_win_exception_in_method(self): @@ -638,7 +637,7 @@ def tearDown(self): self.con.close() def test_aggr_error_on_create(self): - with self.assertRaises(sqlite.OperationalError): + with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"): self.con.create_function("bla", -100, AggrSum) @with_tracebacks(AttributeError, msg_regex="AggrNoStep") diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py index d1c9542c7d1317..2694f5d45c7ebf 100644 --- a/Lib/test/test_str.py +++ b/Lib/test/test_str.py @@ -853,6 +853,15 @@ def test_isprintable(self): self.assertTrue('\U0001F46F'.isprintable()) self.assertFalse('\U000E0020'.isprintable()) + @support.requires_resource('cpu') + def test_isprintable_invariant(self): + for codepoint in range(sys.maxunicode + 1): + char = chr(codepoint) + category = unicodedata.category(char) + self.assertEqual(char.isprintable(), + category[0] not in ('C', 'Z') + or char == ' ') + def test_surrogates(self): for s in ('a\uD800b\uDFFF', 'a\uDFFFb\uD800', 'a\uD800b\uDFFFa', 'a\uDFFFb\uD800a'): diff --git a/Lib/test/test_string_literals.py b/Lib/test/test_string_literals.py index f56195ca27672c..9d57233eb0882a 100644 --- a/Lib/test/test_string_literals.py +++ b/Lib/test/test_string_literals.py @@ -120,7 +120,7 @@ def test_eval_str_invalid_escape(self): r'Such sequences will not work in the future. ' r'Did you mean "\\z"? A raw string is also an option.') self.assertEqual(w[0].filename, '') - self.assertEqual(w[0].lineno, 1) + self.assertEqual(w[0].lineno, 2) with warnings.catch_warnings(record=True) as w: warnings.simplefilter('error', category=SyntaxWarning) @@ -131,7 +131,7 @@ def test_eval_str_invalid_escape(self): self.assertEqual(exc.msg, r'"\z" is an invalid escape sequence. ' r'Did you mean "\\z"? A raw string is also an option.') self.assertEqual(exc.filename, '') - self.assertEqual(exc.lineno, 1) + self.assertEqual(exc.lineno, 2) self.assertEqual(exc.offset, 1) # Check that the warning is raised only once if there are syntax errors @@ -160,7 +160,7 @@ def test_eval_str_invalid_octal_escape(self): r'Such sequences will not work in the future. ' r'Did you mean "\\407"? A raw string is also an option.') self.assertEqual(w[0].filename, '') - self.assertEqual(w[0].lineno, 1) + self.assertEqual(w[0].lineno, 2) with warnings.catch_warnings(record=True) as w: warnings.simplefilter('error', category=SyntaxWarning) @@ -171,9 +171,32 @@ def test_eval_str_invalid_octal_escape(self): self.assertEqual(exc.msg, r'"\407" is an invalid octal escape sequence. ' r'Did you mean "\\407"? A raw string is also an option.') self.assertEqual(exc.filename, '') - self.assertEqual(exc.lineno, 1) + self.assertEqual(exc.lineno, 2) self.assertEqual(exc.offset, 1) + def test_invalid_escape_locations_with_offset(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', category=SyntaxWarning) + eval("\"'''''''''''''''''''''invalid\ Escape\"") + self.assertEqual(len(w), 1) + self.assertEqual(str(w[0].message), + r'"\ " is an invalid escape sequence. Such sequences ' + r'will not work in the future. Did you mean "\\ "? ' + r'A raw string is also an option.') + self.assertEqual(w[0].filename, '') + self.assertEqual(w[0].lineno, 1) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always', category=SyntaxWarning) + eval("\"''Incorrect \ logic?\"") + self.assertEqual(len(w), 1) + self.assertEqual(str(w[0].message), + r'"\ " is an invalid escape sequence. Such sequences ' + r'will not work in the future. Did you mean "\\ "? ' + r'A raw string is also an option.') + self.assertEqual(w[0].filename, '') + self.assertEqual(w[0].lineno, 1) + def test_eval_str_raw(self): self.assertEqual(eval(""" r'x' """), 'x') self.assertEqual(eval(r""" r'\x01' """), '\\' + 'x01') @@ -215,7 +238,7 @@ def test_eval_bytes_invalid_escape(self): r'Such sequences will not work in the future. ' r'Did you mean "\\z"? A raw string is also an option.') self.assertEqual(w[0].filename, '') - self.assertEqual(w[0].lineno, 1) + self.assertEqual(w[0].lineno, 2) with warnings.catch_warnings(record=True) as w: warnings.simplefilter('error', category=SyntaxWarning) @@ -226,7 +249,7 @@ def test_eval_bytes_invalid_escape(self): self.assertEqual(exc.msg, r'"\z" is an invalid escape sequence. ' r'Did you mean "\\z"? A raw string is also an option.') self.assertEqual(exc.filename, '') - self.assertEqual(exc.lineno, 1) + self.assertEqual(exc.lineno, 2) def test_eval_bytes_invalid_octal_escape(self): for i in range(0o400, 0o1000): @@ -241,7 +264,7 @@ def test_eval_bytes_invalid_octal_escape(self): r'Such sequences will not work in the future. ' r'Did you mean "\\407"? A raw string is also an option.') self.assertEqual(w[0].filename, '') - self.assertEqual(w[0].lineno, 1) + self.assertEqual(w[0].lineno, 2) with warnings.catch_warnings(record=True) as w: warnings.simplefilter('error', category=SyntaxWarning) @@ -252,7 +275,7 @@ def test_eval_bytes_invalid_octal_escape(self): self.assertEqual(exc.msg, r'"\407" is an invalid octal escape sequence. ' r'Did you mean "\\407"? A raw string is also an option.') self.assertEqual(exc.filename, '') - self.assertEqual(exc.lineno, 1) + self.assertEqual(exc.lineno, 2) def test_eval_bytes_raw(self): self.assertEqual(eval(""" br'x' """), b'x') diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 132e2b839627bc..6d06e6f6dcb566 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -312,6 +312,12 @@ Traceback (most recent call last): SyntaxError: did you forget parentheses around the comprehension target? +# Incorrectly closed strings + +>>> "The interesting object "The important object" is very important" +Traceback (most recent call last): +SyntaxError: invalid syntax. Is this intended to be part of the string? + # Missing commas in literals collections should not # produce special error messages regarding missing # parentheses, but about missing commas instead diff --git a/Lib/test/test_thread_local_bytecode.py b/Lib/test/test_thread_local_bytecode.py index 7a8809c5ae7697..ea52fb888ce25d 100644 --- a/Lib/test/test_thread_local_bytecode.py +++ b/Lib/test/test_thread_local_bytecode.py @@ -109,6 +109,7 @@ def f(a, b, q=None): """) assert_python_ok("-X", "tlbc=1", "-c", code) + @support.skip_if_sanitizer("gh-129752: data race on adaptive counter", thread=True) def test_no_copies_if_tlbc_disabled(self): code = textwrap.dedent(""" import queue diff --git a/Lib/test/test_tools/i18n_data/docstrings.pot b/Lib/test/test_tools/i18n_data/docstrings.pot index 5af1d41422ff62..387db2413a575f 100644 --- a/Lib/test/test_tools/i18n_data/docstrings.pot +++ b/Lib/test/test_tools/i18n_data/docstrings.pot @@ -15,26 +15,40 @@ msgstr "" "Generated-By: pygettext.py 1.5\n" -#: docstrings.py:7 +#: docstrings.py:1 +#, docstring +msgid "Module docstring" +msgstr "" + +#: docstrings.py:9 #, docstring msgid "" msgstr "" -#: docstrings.py:18 +#: docstrings.py:15 +#, docstring +msgid "docstring" +msgstr "" + +#: docstrings.py:20 #, docstring msgid "" "multiline\n" -" docstring\n" -" " +"docstring" msgstr "" -#: docstrings.py:25 +#: docstrings.py:27 #, docstring msgid "docstring1" msgstr "" -#: docstrings.py:30 +#: docstrings.py:38 +#, docstring +msgid "nested docstring" +msgstr "" + +#: docstrings.py:43 #, docstring -msgid "Hello, {}!" +msgid "nested class docstring" msgstr "" diff --git a/Lib/test/test_tools/i18n_data/docstrings.py b/Lib/test/test_tools/i18n_data/docstrings.py index 85d7f159d37775..151a55a4b56ba6 100644 --- a/Lib/test/test_tools/i18n_data/docstrings.py +++ b/Lib/test/test_tools/i18n_data/docstrings.py @@ -1,3 +1,5 @@ +"""Module docstring""" + # Test docstring extraction from gettext import gettext as _ @@ -10,10 +12,10 @@ def test(x): # Leading empty line def test2(x): - """docstring""" # XXX This should be extracted but isn't. + """docstring""" -# XXX Multiline docstrings should be cleaned with `inspect.cleandoc`. +# Multiline docstrings are cleaned with `inspect.cleandoc`. def test3(x): """multiline docstring @@ -27,15 +29,15 @@ def test4(x): def test5(x): - """Hello, {}!""".format("world!") # XXX This should not be extracted. + """Hello, {}!""".format("world!") # This should not be extracted. # Nested docstrings def test6(x): def inner(y): - """nested docstring""" # XXX This should be extracted but isn't. + """nested docstring""" class Outer: class Inner: - "nested class docstring" # XXX This should be extracted but isn't. + "nested class docstring" diff --git a/Lib/test/test_tools/i18n_data/messages.pot b/Lib/test/test_tools/i18n_data/messages.pot index 8d66fbc4f3a937..e8167acfc0742b 100644 --- a/Lib/test/test_tools/i18n_data/messages.pot +++ b/Lib/test/test_tools/i18n_data/messages.pot @@ -19,22 +19,22 @@ msgstr "" msgid "" msgstr "" -#: messages.py:19 messages.py:20 +#: messages.py:19 messages.py:20 messages.py:21 msgid "parentheses" msgstr "" -#: messages.py:23 +#: messages.py:24 msgid "Hello, world!" msgstr "" -#: messages.py:26 +#: messages.py:27 msgid "" "Hello,\n" " multiline!\n" msgstr "" #: messages.py:46 messages.py:89 messages.py:90 messages.py:93 messages.py:94 -#: messages.py:99 +#: messages.py:99 messages.py:100 messages.py:101 msgid "foo" msgid_plural "foos" msgstr[0] "" @@ -68,7 +68,7 @@ msgstr "" msgid "set" msgstr "" -#: messages.py:63 +#: messages.py:62 messages.py:63 msgid "nested string" msgstr "" @@ -76,6 +76,10 @@ msgstr "" msgid "baz" msgstr "" +#: messages.py:71 messages.py:75 +msgid "default value" +msgstr "" + #: messages.py:91 messages.py:92 messages.py:95 messages.py:96 msgctxt "context" msgid "foo" @@ -83,7 +87,13 @@ msgid_plural "foos" msgstr[0] "" msgstr[1] "" -#: messages.py:100 +#: messages.py:102 msgid "domain foo" msgstr "" +#: messages.py:118 messages.py:119 +msgid "world" +msgid_plural "worlds" +msgstr[0] "" +msgstr[1] "" + diff --git a/Lib/test/test_tools/i18n_data/messages.py b/Lib/test/test_tools/i18n_data/messages.py index 1e03f4e556830d..9457bcb8611020 100644 --- a/Lib/test/test_tools/i18n_data/messages.py +++ b/Lib/test/test_tools/i18n_data/messages.py @@ -18,6 +18,7 @@ # Extra parentheses (_("parentheses")) ((_("parentheses"))) +_(("parentheses")) # Multiline strings _("Hello, " @@ -32,7 +33,6 @@ _(None) _(1) _(False) -_(("invalid")) _(["invalid"]) _({"invalid"}) _("string"[3]) @@ -40,7 +40,7 @@ _({"string": "foo"}) # pygettext does not allow keyword arguments, but both xgettext and pybabel do -_(x="kwargs work!") +_(x="kwargs are not allowed!") # Unusual, but valid arguments _("foo", "bar") @@ -48,7 +48,7 @@ # .format() _("Hello, {}!").format("world") # valid -_("Hello, {}!".format("world")) # invalid, but xgettext and pybabel extract the first string +_("Hello, {}!".format("world")) # invalid, but xgettext extracts the first string # Nested structures _("1"), _("2") @@ -59,7 +59,7 @@ # Nested functions and classes def test(): - _("nested string") # XXX This should be extracted but isn't. + _("nested string") [_("nested string")] @@ -68,11 +68,11 @@ def bar(self): return _("baz") -def bar(x=_('default value')): # XXX This should be extracted but isn't. +def bar(x=_('default value')): pass -def baz(x=[_('default value')]): # XXX This should be extracted but isn't. +def baz(x=[_('default value')]): pass @@ -97,6 +97,8 @@ def _(x="don't extract me"): # Complex arguments ngettext("foo", "foos", 42 + (10 - 20)) +ngettext("foo", "foos", *args) +ngettext("foo", "foos", **kwargs) dgettext(["some", {"complex"}, ("argument",)], "domain foo") # Invalid calls which are not extracted @@ -108,3 +110,10 @@ def _(x="don't extract me"): dngettext('domain', 'foo') dpgettext('domain', 'context') dnpgettext('domain', 'context', 'foo') +dgettext(*args, 'foo') +dpgettext(*args, 'context', 'foo') +dnpgettext(*args, 'context', 'foo', 'foos') + +# f-strings +f"Hello, {_('world')}!" +f"Hello, {ngettext('world', 'worlds', 3)}!" diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 29c3423e234d20..f5aba31ed42c10 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -87,7 +87,7 @@ def assert_POT_equal(self, expected, actual): self.maxDiff = None self.assertEqual(normalize_POT_file(expected), normalize_POT_file(actual)) - def extract_from_str(self, module_content, *, args=(), strict=True): + def extract_from_str(self, module_content, *, args=(), strict=True, with_stderr=False): """Return all msgids extracted from module_content.""" filename = 'test.py' with temp_cwd(None): @@ -98,12 +98,18 @@ def extract_from_str(self, module_content, *, args=(), strict=True): self.assertEqual(res.err, b'') with open('messages.pot', encoding='utf-8') as fp: data = fp.read() - return self.get_msgids(data) + msgids = self.get_msgids(data) + if not with_stderr: + return msgids + return msgids, res.err def extract_docstrings_from_str(self, module_content): """Return all docstrings extracted from module_content.""" return self.extract_from_str(module_content, args=('--docstrings',), strict=False) + def get_stderr(self, module_content): + return self.extract_from_str(module_content, strict=False, with_stderr=True)[1] + def test_header(self): """Make sure the required fields are in the header, according to: http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry @@ -407,6 +413,30 @@ def test_files_list(self): self.assertIn(f'msgid "{text2}"', data) self.assertNotIn(text3, data) + def test_help_text(self): + """Test that the help text is displayed.""" + res = assert_python_ok(self.script, '--help') + self.assertEqual(res.out, b'') + self.assertIn(b'pygettext -- Python equivalent of xgettext(1)', res.err) + + def test_error_messages(self): + """Test that pygettext outputs error messages to stderr.""" + stderr = self.get_stderr(dedent('''\ + _(1+2) + ngettext('foo') + dgettext(*args, 'foo') + ''')) + + # Normalize line endings on Windows + stderr = stderr.decode('utf-8').replace('\r', '') + + self.assertEqual( + stderr, + "*** test.py:1: Expected a string constant for argument 1, got 1 + 2\n" + "*** test.py:2: Expected at least 2 positional argument(s) in gettext call, got 1\n" + "*** test.py:3: Variable positional arguments are not allowed in gettext calls\n" + ) + def update_POT_snapshots(): for input_file in DATA_DIR.glob('*.py'): diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 89980ae6f8573a..c2b115b53889d3 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -3229,11 +3229,17 @@ class TestStack(unittest.TestCase): def test_walk_stack(self): def deeper(): return list(traceback.walk_stack(None)) - s1 = list(traceback.walk_stack(None)) - s2 = deeper() + s1, s2 = list(traceback.walk_stack(None)), deeper() self.assertEqual(len(s2) - len(s1), 1) self.assertEqual(s2[1:], s1) + def test_walk_innermost_frame(self): + def inner(): + return list(traceback.walk_stack(None)) + frames = inner() + innermost_frame, _ = frames[0] + self.assertEqual(innermost_frame.f_code.co_name, "inner") + def test_walk_tb(self): try: 1/0 diff --git a/Lib/traceback.py b/Lib/traceback.py index 31c73efcef5a52..2b402dd4cc2401 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -380,10 +380,14 @@ def walk_stack(f): current stack is used. Usually used with StackSummary.extract. """ if f is None: - f = sys._getframe().f_back.f_back.f_back.f_back - while f is not None: - yield f, f.f_lineno - f = f.f_back + f = sys._getframe().f_back + + def walk_stack_generator(frame): + while frame is not None: + yield frame, frame.f_lineno + frame = frame.f_back + + return walk_stack_generator(f) def walk_tb(tb): diff --git a/Lib/zipimport.py b/Lib/zipimport.py index e5192c4d074c4b..444c9dd11d8672 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -20,7 +20,6 @@ import marshal # for loads import sys # for modules import time # for mktime -import _warnings # For warn() __all__ = ['ZipImportError', 'zipimporter'] @@ -221,9 +220,11 @@ def load_module(self, fullname): Deprecated since Python 3.10. Use exec_module() instead. """ - msg = ("zipimport.zipimporter.load_module() is deprecated and slated for " - "removal in Python 3.12; use exec_module() instead") - _warnings.warn(msg, DeprecationWarning) + import warnings + warnings._deprecated("zipimport.zipimporter.load_module", + f"{warnings._DEPRECATED_MSG}; " + "use zipimport.zipimporter.exec_module() instead", + remove=(3, 15)) code, ispackage, modpath = _get_module_code(self, fullname) mod = sys.modules.get(fullname) if mod is None or not isinstance(mod, _module_type): diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index f5f0ed44884142..cb2484767e6449 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -325,32 +325,32 @@ def library_recipes(): result.extend([ dict( - name="NCurses 5.9", - url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz", - checksum='8cb9c412e5f2d96bc6f459aa8c6282a1', + name="NCurses 6.5", + url="https://ftp.gnu.org/gnu/ncurses/ncurses-6.5.tar.gz", + checksum="136d91bc269a9a5785e5f9e980bc76ab57428f604ce3e5a5a90cebc767971cc6", configure_pre=[ + "--datadir=/usr/share", + "--disable-lib-suffixes", + "--disable-db-install", + "--disable-mixed-case", + "--enable-overwrite", "--enable-widec", + f"--libdir=/Library/Frameworks/Python.framework/Versions/{getVersion()}/lib", + "--sharedstatedir=/usr/com", + "--sysconfdir=/etc", + "--with-default-terminfo-dir=/usr/share/terminfo", + "--with-shared", + "--with-terminfo-dirs=/usr/share/terminfo", + "--without-ada", "--without-cxx", "--without-cxx-binding", - "--without-ada", - "--without-curses-h", - "--enable-shared", - "--with-shared", + "--without-cxx-shared", "--without-debug", + "--without-manpages", "--without-normal", + "--without-progs", "--without-tests", - "--without-manpages", - "--datadir=/usr/share", - "--sysconfdir=/etc", - "--sharedstatedir=/usr/com", - "--with-terminfo-dirs=/usr/share/terminfo", - "--with-default-terminfo-dir=/usr/share/terminfo", - "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),), ], - patchscripts=[ - ("ftp://ftp.invisible-island.net/ncurses//5.9/ncurses-5.9-20120616-patch.sh.bz2", - "f54bf02a349f96a7c4f0d00922f3a0d4"), - ], useLDFlags=False, install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%( shellQuote(os.path.join(WORKDIR, 'libraries')), diff --git a/Makefile.pre.in b/Makefile.pre.in index 67acf0fc520087..43355e2e7191ee 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -728,7 +728,7 @@ list-targets: .PHONY: build_all build_all: check-clean-src check-app-store-compliance $(BUILDPYTHON) platform sharedmods \ - gdbhooks Programs/_testembed scripts checksharedmods rundsymutil + gdbhooks Programs/_testembed scripts checksharedmods rundsymutil build-details.json .PHONY: build_wasm build_wasm: check-clean-src $(BUILDPYTHON) platform sharedmods \ @@ -934,6 +934,9 @@ pybuilddir.txt: $(PYTHON_FOR_BUILD_DEPS) exit 1 ; \ fi +build-details.json: pybuilddir.txt + $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/build/generate-build-details.py `cat pybuilddir.txt`/build-details.json + # Build static library $(LIBRARY): $(LIBRARY_OBJS) -rm -f $@ @@ -2644,6 +2647,7 @@ libinstall: all $(srcdir)/Modules/xxmodule.c done $(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py $(DESTDIR)$(LIBDEST); \ $(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfig_vars_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).json $(DESTDIR)$(LIBDEST); \ + $(INSTALL_DATA) `cat pybuilddir.txt`/build-details.json $(DESTDIR)$(LIBDEST); \ $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt @ # If app store compliance has been configured, apply the patch to the @ # installed library code. The patch has been previously validated against diff --git a/Misc/NEWS.d/3.13.0a1.rst b/Misc/NEWS.d/3.13.0a1.rst index c32c9a537d7b53..91e9fee7e37437 100644 --- a/Misc/NEWS.d/3.13.0a1.rst +++ b/Misc/NEWS.d/3.13.0a1.rst @@ -5716,7 +5716,7 @@ Tools/wasm/build_wasi.sh as a reference implementation of the docs. .. section: Build Autoconf 2.71 and aclocal 1.16.4 is now required to regenerate -:file:`!configure`. +:file:`configure`. .. diff --git a/Misc/NEWS.d/3.14.0a4.rst b/Misc/NEWS.d/3.14.0a4.rst index 1e08b36020386c..0937a0c6125e0a 100644 --- a/Misc/NEWS.d/3.14.0a4.rst +++ b/Misc/NEWS.d/3.14.0a4.rst @@ -765,7 +765,7 @@ build with LLVM 19. .. nonce: jko7Fg .. section: Build -GNU Autoconf 2.72 is now required to generate :file:`!configure`. Patch by +GNU Autoconf 2.72 is now required to generate :file:`configure`. Patch by Erlend Aasland. .. diff --git a/Misc/NEWS.d/3.14.0a5.rst b/Misc/NEWS.d/3.14.0a5.rst new file mode 100644 index 00000000000000..a3548d0a7b0357 --- /dev/null +++ b/Misc/NEWS.d/3.14.0a5.rst @@ -0,0 +1,1378 @@ +.. date: 2025-02-10-22-08-37 +.. gh-issue: 91132 +.. nonce: 00x1MI +.. release date: 2025-02-11 +.. section: macOS + +Update macOS installer to use ncurses 6.5. + +.. + +.. date: 2025-01-24-14-49-40 +.. gh-issue: 129248 +.. nonce: JAapG2 +.. section: Tools/Demos + +The iOS test runner now strips the log prefix from each line output by the +test suite. + +.. + +.. date: 2023-05-11-23-32-25 +.. gh-issue: 104400 +.. nonce: 23vxm7 +.. section: Tools/Demos + +Fix several bugs in extraction by switching to an AST parser in +:program:`pygettext`. + +.. + +.. date: 2025-01-30-13-09-27 +.. gh-issue: 129386 +.. nonce: iNtbEi +.. section: Tests + +Add ``test.support.reset_code``, which can be used to reset various +bytecode-level optimizations and local instrumentation for a function. + +.. + +.. date: 2025-01-04-02-41-41 +.. gh-issue: 128474 +.. nonce: 0b-tl4 +.. section: Tests + +Disable ``test_embed`` test cases that segfault on BOLT instrument binaries. +The tests are only disabled when BOLT is enabled. + +.. + +.. date: 2024-12-16-19-15-10 +.. gh-issue: 128003 +.. nonce: GVBrfa +.. section: Tests + +Add an option ``--parallel-threads=N`` to the regression test runner that +runs individual tests in multiple threads in parallel in order to find +concurrency bugs. Note that most of the test suite is not yet reviewed for +thread-safety or annotated with ``@thread_unsafe`` when necessary. + +.. + +.. date: 2025-01-28-14-08-03 +.. gh-issue: 105704 +.. nonce: EnhHxu +.. section: Security + +When using :func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` +host parsing would not reject domain names containing square brackets (``[`` +and ``]``). Square brackets are only valid for IPv6 and IPvFuture hosts +according to `RFC 3986 Section 3.2.2 +`__. + +.. + +.. date: 2024-10-29-09-15-10 +.. gh-issue: 126108 +.. nonce: eTIjHY +.. section: Security + +Fix a possible ``NULL`` pointer dereference in +:c:func:`!PySys_AddWarnOptionUnicode`. + +.. + +.. date: 2024-08-06-11-43-08 +.. gh-issue: 80222 +.. nonce: wfR4BU +.. section: Security + +Fix bug in the folding of quoted strings when flattening an email message +using a modern email policy. Previously when a quoted string was folded so +that it spanned more than one line, the surrounding quotes and internal +escapes would be omitted. This could theoretically be used to spoof header +lines using a carefully constructed quoted string if the resulting rendered +email was transmitted or re-parsed. + +.. + +.. date: 2024-05-24-21-00-52 +.. gh-issue: 119511 +.. nonce: jKrXQ8 +.. section: Security + +Fix a potential denial of service in the :mod:`imaplib` module. When +connecting to a malicious server, it could cause an arbitrary amount of +memory to be allocated. On many systems this is harmless as unused virtual +memory is only a mapping, but if this hit a virtual address size limit it +could lead to a :exc:`MemoryError` or other process crash. On unusual +systems or builds where all allocated memory is touched and backed by actual +ram or storage it could've consumed resources doing so until similarly +crashing. + +.. + +.. date: 2025-02-10-14-34-34 +.. gh-issue: 129939 +.. nonce: B08L4e +.. section: Library + +Comparison pages with highlighted changes generated by the +:class:`difflib.HtmlDiff` class now support dark mode. + +.. + +.. date: 2025-02-10-08-44-11 +.. gh-issue: 129928 +.. nonce: QuiZEz +.. section: Library + +Raise :exc:`sqlite3.ProgrammingError` if a user-defined SQL function with +invalid number of parameters is created. Patch by Erlend Aasland. + +.. + +.. date: 2025-02-09-17-47-01 +.. gh-issue: 129583 +.. nonce: -130Ys +.. section: Library + +Update bundled pip to 25.0.1 + +.. + +.. date: 2025-02-07-10-34-09 +.. gh-issue: 129766 +.. nonce: 6n5fQZ +.. section: Library + +Fix crash in :mod:`warnings`, when calling ``_release_lock()`` with no +existing lock. + +.. + +.. date: 2025-02-05-13-19-15 +.. gh-issue: 129005 +.. nonce: Sb69L_ +.. section: Library + +``_pyio.FileIO.readall()`` now allocates, resizes, and fills a data buffer +using the same algorithm ``_io.FileIO.readall()`` uses. + +.. + +.. date: 2025-02-04-15-16-33 +.. gh-issue: 129646 +.. nonce: sapk1F +.. section: Library + +Update the locale alias mapping in the :mod:`locale` module to match the +latest X Org locale alias mapping and support new locales in Glibc 2.41. + +.. + +.. date: 2025-02-03-22-31-43 +.. gh-issue: 128317 +.. nonce: n2Swnh +.. section: Library + +Put CLI calendar highlighting in private class, removing ``highlight_day`` +from public :class:`calendar.TextCalendar` API. Patch by Hugo van Kemenade. + +.. + +.. date: 2025-02-03-01-43-16 +.. gh-issue: 129603 +.. nonce: xge9Tx +.. section: Library + +Fix bugs where :class:`sqlite3.Row` objects could segfault if their +inherited :attr:`~sqlite3.Cursor.description` was set to ``None``. Patch by +Erlend Aasland. + +.. + +.. date: 2025-02-01-14-55-33 +.. gh-issue: 129559 +.. nonce: hQCeAz +.. section: Library + +Add :meth:`bytearray.resize` method so :class:`bytearray` can be efficiently +resized in place. + +.. + +.. date: 2025-01-31-11-14-05 +.. gh-issue: 129502 +.. nonce: j_ArNo +.. section: Library + +Unlikely errors in preparing arguments for :mod:`ctypes` callback are now +handled in the same way as errors raised in the callback of in converting +the result of the callback -- using :func:`sys.unraisablehook` instead of +:func:`sys.excepthook` and not setting :data:`sys.last_exc` and other +variables. + +.. + +.. date: 2025-01-29-17-10-00 +.. gh-issue: 129403 +.. nonce: 314159 +.. section: Library + +Corrected :exc:`ValueError` message for :class:`asyncio.Barrier` and +:class:`threading.Barrier`. + +.. + +.. date: 2025-01-29-14-30-54 +.. gh-issue: 129409 +.. nonce: JZbOE6 +.. section: Library + +Fix an integer overflow in the :mod:`csv` module when writing a data field +larger than 2GB. + +.. + +.. date: 2025-01-29-13-37-18 +.. gh-issue: 126400 +.. nonce: DaBaR3 +.. section: Library + +Add a socket *timeout* keyword argument to +:class:`logging.handlers.SysLogHandler`. + +.. + +.. date: 2025-01-29-11-14-20 +.. gh-issue: 118761 +.. nonce: gMZwE1 +.. section: Library + +Always lazy import ``warnings`` in :mod:`threading`. Patch by Taneli +Hukkinen. + +.. + +.. date: 2025-01-29-10-53-32 +.. gh-issue: 118761 +.. nonce: i8wjpV +.. section: Library + +Improve import time of :mod:`subprocess` by lazy importing ``locale`` and +``signal``. Patch by Taneli Hukkinen. + +.. + +.. date: 2025-01-27-14-05-19 +.. gh-issue: 129346 +.. nonce: gZRd3g +.. section: Library + +In :mod:`sqlite3`, handle out-of-memory when creating user-defined SQL +functions. + +.. + +.. date: 2025-01-26-10-01-21 +.. gh-issue: 129005 +.. nonce: ncpLvw +.. section: Library + +Optimize ``_pyio.FileIO.readinto`` by avoiding unnecessary objects and +copies using :func:`os.readinto`. + +.. + +.. date: 2025-01-24-10-48-32 +.. gh-issue: 129195 +.. nonce: 89d5NU +.. section: Library + +Support reporting call graph information from +:func:`!asyncio.staggered.staggered_race`. + +.. + +.. date: 2025-01-22-16-54-25 +.. gh-issue: 129205 +.. nonce: FMqrUt +.. section: Library + +Add :func:`os.readinto` to read into a :ref:`buffer object ` +from a file descriptor. + +.. + +.. date: 2025-01-22-13-29-06 +.. gh-issue: 128772 +.. nonce: 6YrxYM +.. section: Library + +Fix :mod:`pydoc` for methods with the ``__module__`` attribute equal to +``None``. + +.. + +.. date: 2025-01-21-18-52-32 +.. gh-issue: 129061 +.. nonce: 4idD_B +.. section: Library + +Fix FORCE_COLOR and NO_COLOR when empty strings. Patch by Hugo van Kemenade. + +.. + +.. date: 2025-01-20-20-59-26 +.. gh-issue: 92897 +.. nonce: G0xH8o +.. section: Library + +Scheduled the deprecation of the ``check_home`` argument of +:func:`sysconfig.is_python_build` to Python 3.15. + +.. + +.. date: 2025-01-20-16-02-38 +.. gh-issue: 129064 +.. nonce: JXasgJ +.. section: Library + +Deprecate :func:`!sysconfig.expand_makefile_vars`, in favor of using +:func:`sysconfig.get_paths` with the ``vars`` argument. + +.. + +.. date: 2025-01-20-13-12-39 +.. gh-issue: 128550 +.. nonce: AJ5TOL +.. section: Library + +Removed an incorrect optimization relating to eager tasks in +:class:`asyncio.TaskGroup` that resulted in cancellations being missed. + +.. + +.. date: 2025-01-18-16-58-10 +.. gh-issue: 128991 +.. nonce: EzJit9 +.. section: Library + +Release the enter frame reference within :mod:`bdb` callback + +.. + +.. date: 2025-01-18-11-24-02 +.. gh-issue: 118761 +.. nonce: G8MmxY +.. section: Library + +Reduce import time of :mod:`pstats` and :mod:`zipfile` by up to 20%, by +removing unnecessary imports to :mod:`typing`. Patch by Bénédikt Tran. + +.. + +.. date: 2025-01-18-11-04-44 +.. gh-issue: 128978 +.. nonce: hwg7-w +.. section: Library + +Fix a :exc:`NameError` in :func:`!sysconfig.expand_makefile_vars`. Patch by +Bénédikt Tran. + +.. + +.. date: 2025-01-17-21-33-11 +.. gh-issue: 128961 +.. nonce: XwvyIZ +.. section: Library + +Fix a crash when setting state on an exhausted :class:`array.array` +iterator. + +.. + +.. date: 2025-01-17-17-20-51 +.. gh-issue: 128894 +.. nonce: gX1-8J +.. section: Library + +Fix ``traceback.TracebackException._format_syntax_error`` not to fail on +exceptions with custom metadata. + +.. + +.. date: 2025-01-17-11-46-16 +.. gh-issue: 128916 +.. nonce: GEePbO +.. section: Library + +Do not attempt to set ``SO_REUSEPORT`` on sockets of address families other +than ``AF_INET`` and ``AF_INET6``, as it is meaningless with these address +families, and the call with fail with Linux kernel 6.12.9 and newer. + +.. + +.. date: 2025-01-16-10-06-40 +.. gh-issue: 118761 +.. nonce: z100LC +.. section: Library + +Improve import time of :mod:`tomllib` by removing ``typing``, ``string``, +and ``tomllib._types`` imports. Patch by Taneli Hukkinen. + +.. + +.. date: 2025-01-15-21-41-51 +.. gh-issue: 128679 +.. nonce: tq10F2 +.. section: Library + +:mod:`tracemalloc`: Fix race conditions when :func:`tracemalloc.stop` is +called by a thread, while other threads are tracing memory allocations. +Patch by Victor Stinner. + +.. + +.. date: 2025-01-15-19-32-23 +.. gh-issue: 128891 +.. nonce: ojUxKo +.. section: Library + +Add specialized opcodes to ``opcode.opname``. + +.. + +.. date: 2025-01-15-19-16-50 +.. gh-issue: 118761 +.. nonce: cbW2ZL +.. section: Library + +Reduce import time of :mod:`gettext` by up to ten times, by importing +:mod:`re` on demand. In particular, ``re`` is no longer implicitly exposed +as ``gettext.re``. Patch by Eli Schwartz. + +.. + +.. date: 2025-01-15-18-54-48 +.. gh-issue: 118761 +.. nonce: G1dv6E +.. section: Library + +Reduce the import time of :mod:`optparse` when no help text is printed. +Patch by Eli Schwartz. + +.. + +.. date: 2025-01-15-15-45-21 +.. gh-issue: 128657 +.. nonce: P5LNQA +.. section: Library + +Fix possible extra reference when using objects returned by +:func:`hashlib.sha256` under :term:`free threading`. + +.. + +.. date: 2025-01-15-09-45-43 +.. gh-issue: 118761 +.. nonce: TvAC8E +.. section: Library + +Reduce the import time of :mod:`csv` by up to five times, by importing +:mod:`re` on demand. In particular, ``re`` is no more implicitly exposed as +``csv.re``. Patch by Bénédikt Tran. + +.. + +.. date: 2025-01-13-07-54-32 +.. gh-issue: 128308 +.. nonce: kYSDRF +.. section: Library + +Support the *name* keyword argument for eager tasks in +:func:`asyncio.loop.create_task`, :func:`asyncio.create_task` and +:func:`asyncio.TaskGroup.create_task`, by passing on all *kwargs* to the +task factory set by :func:`asyncio.loop.set_task_factory`. + +.. + +.. date: 2025-01-10-13-06-54 +.. gh-issue: 118761 +.. nonce: f8oADD +.. section: Library + +Improve the performance of :func:`base64.b16decode` by up to ten times by +more efficiently checking the byte-string for hexadecimal digits. Reduce the +import time of :mod:`base64` by up to six times, by no longer importing +:mod:`re`. Patch by Bénédikt Tran, Chris Markiewicz, and Adam Turner. + +.. + +.. date: 2025-01-09-16-20-34 +.. gh-issue: 128156 +.. nonce: GfObBq +.. section: Library + +When using macOS system ``libffi``, support for complex types in +:mod:`ctypes` is now checked at runtime (macOS 10.15 or newer). The types +must also be available at build time. + +.. + +.. date: 2025-01-08-22-30-38 +.. gh-issue: 128636 +.. nonce: jQfWXj +.. section: Library + +Fix PyREPL failure when :data:`os.environ` is overwritten with an invalid +value. + +.. + +.. date: 2025-01-07-21-48-32 +.. gh-issue: 128498 +.. nonce: n6jtlW +.. section: Library + +Default to stdout isatty for color detection instead of stderr. Patch by +Hugo van Kemenade. + +.. + +.. date: 2025-01-06-10-37-27 +.. gh-issue: 128384 +.. nonce: V0xzwH +.. section: Library + +Add locking to :mod:`warnings` to avoid some data races when free-threading +is used. Change ``_warnings_runtime_state.mutex`` to be a recursive mutex +and expose it to :mod:`warnings`, via the :func:`!_acquire_lock` and +:func:`!_release_lock` functions. The lock is held when ``filters`` and +``_filters_version`` are updated. + +.. + +.. date: 2025-01-04-20-51-48 +.. gh-issue: 128509 +.. nonce: 3gr_-O +.. section: Library + +Add :func:`sys._is_immortal` for identifying :term:`immortal` objects at +runtime. + +.. + +.. date: 2025-01-04-11-10-04 +.. gh-issue: 128479 +.. nonce: jvOrF- +.. section: Library + +Fix :func:`!asyncio.staggered.staggered_race` leaking tasks and issuing an +unhandled exception. + +.. + +.. date: 2025-01-02-20-34-04 +.. gh-issue: 128427 +.. nonce: onPoQZ +.. section: Library + +:const:`uuid.NIL` and :const:`uuid.MAX` are now available to represent the +Nil and Max UUID formats as defined by :rfc:`9562`. + +.. + +.. date: 2024-12-30-19-53-14 +.. gh-issue: 91279 +.. nonce: EeOJk1 +.. section: Library + +:meth:`zipfile.ZipFile.writestr` now respect ``SOURCE_DATE_EPOCH`` that +distributions can set centrally and have build tools consume this in order +to produce reproducible output. + +.. + +.. date: 2024-12-26-11-00-03 +.. gh-issue: 112064 +.. nonce: mCcw3B +.. section: Library + +Fix incorrect handling of negative read sizes in :meth:`HTTPResponse.read +`. Patch by Yury Manushkin. + +.. + +.. date: 2024-12-23-02-09-44 +.. gh-issue: 58956 +.. nonce: 4OdMdT +.. section: Library + +Fixed a frame reference leak in :mod:`bdb`. + +.. + +.. date: 2024-12-21-03-20-12 +.. gh-issue: 128131 +.. nonce: QpPmNt +.. section: Library + +Completely support random access of uncompressed unencrypted read-only zip +files obtained by :meth:`ZipFile.open `. + +.. + +.. date: 2024-12-20-08-44-12 +.. gh-issue: 127975 +.. nonce: 8HJwu9 +.. section: Library + +Avoid reusing quote types in :func:`ast.unparse` if not needed. + +.. + +.. date: 2024-12-17-16-48-02 +.. gh-issue: 115514 +.. nonce: 1yOJ7T +.. section: Library + +Fix exceptions and incomplete writes after +:class:`!asyncio._SelectorTransport` is closed before writes are completed. + +.. + +.. date: 2024-12-16-22-20-38 +.. gh-issue: 121604 +.. nonce: m3Xn4G +.. section: Library + +Add missing Deprecation warnings for +:const:`importlib.machinery.DEBUG_BYTECODE_SUFFIXES`, +:const:`importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES`, +:class:`importlib.machinery.WindowsRegistryFinder`, +:class:`importlib.abc.ResourceLoader`, +:meth:`importlib.abc.SourceLoader.path_mtime`. + +.. + +.. date: 2024-12-12-18-25-50 +.. gh-issue: 127873 +.. nonce: WJRwfz +.. section: Library + +When ``-E`` is set, only ignore ``PYTHON_COLORS`` and not +``FORCE_COLOR``/``NO_COLOR``/``TERM`` when colourising output. Patch by Hugo +van Kemenade. + +.. + +.. date: 2024-12-10-19-39-35 +.. gh-issue: 125413 +.. nonce: wOb4yr +.. section: Library + +Add :attr:`pathlib.Path.info` attribute, which stores an object implementing +the :class:`pathlib.types.PathInfo` protocol (also new). The object supports +querying the file type and internally caching :func:`~os.stat` results. Path +objects generated by :meth:`~pathlib.Path.iterdir` are initialized with file +type information gleaned from scanning the parent directory. + +.. + +.. date: 2024-12-07-20-33-43 +.. gh-issue: 127712 +.. nonce: Uzsij4 +.. section: Library + +Fix handling of the ``secure`` argument of +:class:`logging.handlers.SMTPHandler`. + +.. + +.. date: 2024-11-24-22-06-42 +.. gh-issue: 127096 +.. nonce: R7LLpQ +.. section: Library + +Do not recreate unnamed section on every read in +:class:`configparser.ConfigParser`. Patch by Andrey Efremov. + +.. + +.. date: 2024-11-23-21-17-28 +.. gh-issue: 124369 +.. nonce: Z0hQFQ +.. section: Library + +Deprecate ``pdb.Pdb.curframe_locals`` + +.. + +.. date: 2024-11-10-19-45-01 +.. gh-issue: 126332 +.. nonce: WCCKoH +.. section: Library + +Fix _pyrepl crash when entering a double CTRL-Z on an overflowing line. + +.. + +.. date: 2024-10-26-16-59-02 +.. gh-issue: 125553 +.. nonce: 4pDLzt +.. section: Library + +Fix round-trip invariance for backslash continuations in +:func:`tokenize.untokenize`. + +.. + +.. date: 2024-10-02-11-17-23 +.. gh-issue: 91048 +.. nonce: QWY-b1 +.. section: Library + +Add :func:`asyncio.capture_call_graph` and :func:`asyncio.print_call_graph` +functions. + +.. + +.. date: 2024-09-27-19-21-53 +.. gh-issue: 124703 +.. nonce: lYTLEv +.. section: Library + +Quitting :mod:`pdb` in ``inline`` mode will emit a confirmation prompt and +exit gracefully now, instead of printing an exception traceback. + +.. + +.. date: 2024-09-12-14-24-25 +.. gh-issue: 123987 +.. nonce: 7_OD1p +.. section: Library + +Fixed issue in NamespaceReader where a non-path item in a namespace path, +such as a sentinel added by an editable installer, would break resource +loading. + +.. + +.. date: 2024-08-12-11-58-15 +.. gh-issue: 119349 +.. nonce: -xTnHl +.. section: Library + +Add the :func:`ctypes.util.dllist` function to list the loaded shared +libraries for the current process. + +.. + +.. date: 2024-08-01-01-00-00 +.. gh-issue: 55454 +.. nonce: wy0vGw +.. section: Library + +Add IMAP4 ``IDLE`` support to the :mod:`imaplib` module. Patch by Forest. + +.. + +.. date: 2024-07-14-23-19-20 +.. gh-issue: 119257 +.. nonce: 9OEzcN +.. section: Library + +Show tab completions menu below the current line, which results in less +janky behaviour, and fixes a cursor movement bug. Patch by Daniel Hollas + +.. + +.. date: 2023-02-01-16-41-31 +.. gh-issue: 101410 +.. nonce: Dt2aQE +.. section: Library + +Support custom messages for domain errors in the :mod:`math` module +(:func:`math.sqrt`, :func:`math.log` and :func:`math.atanh` were modified as +examples). Patch by Charlie Zhao and Sergey B Kirpichev. + +.. + +.. date: 2022-05-23-21-23-29 +.. gh-issue: 81340 +.. nonce: D11RkZ +.. section: Library + +Use :func:`os.copy_file_range` in :func:`shutil.copy`, :func:`shutil.copy2`, +and :func:`shutil.copyfile` functions by default. An underlying Linux system +call gives filesystems an opportunity to implement the use of copy-on-write +(in case of btrfs and XFS) or server-side copy (in the case of NFS.) Patch +by Illia Volochii. + +.. + +.. bpo: 27307 +.. date: 2020-08-07-16-55-57 +.. nonce: Xqzzda +.. section: Library + +Add attribute and item access support to :class:`string.Formatter` in +auto-numbering mode, which allows format strings like '{.name}' and '{[1]}'. + +.. + +.. date: 2025-02-08-23-42-24 +.. gh-issue: 129873 +.. nonce: -gofkd +.. section: IDLE + +Simplify displaying the IDLE doc by only copying the text section of +idle.html to idlelib/help.html. Patch by Stan Ulbrych. + +.. + +.. date: 2025-01-16-18-59-11 +.. gh-issue: 125722 +.. nonce: eHHRga +.. section: Documentation + +Require Sphinx 8.1.3 or later to build the Python documentation. Patch by +Adam Turner. + +.. + +.. date: 2025-01-14-11-06-41 +.. gh-issue: 67206 +.. nonce: LYKmi5 +.. section: Documentation + +Document that :const:`string.printable` is not printable in the POSIX sense. +In particular, :meth:`string.printable.isprintable() ` +returns :const:`False`. Patch by Bénédikt Tran. + +.. + +.. date: 2025-02-07-17-06-39 +.. gh-issue: 100239 +.. nonce: WvBTPL +.. section: Core and Builtins + +Replace the opcode BINARY_SUBSCR and its family by BINARY_OP with oparg +NB_SUBSCR. + +.. + +.. date: 2025-02-06-17-57-33 +.. gh-issue: 129732 +.. nonce: yl97oq +.. section: Core and Builtins + +Fixed a race in ``_Py_qsbr_reserve`` in the free threading build. + +.. + +.. date: 2025-02-06-17-05-09 +.. gh-issue: 129763 +.. nonce: 6ZxQ8W +.. section: Core and Builtins + +Remove the internal ``LLTRACE`` macro (use :c:macro:`Py_DEBUG` instead). + +.. + +.. date: 2025-02-05-22-58-18 +.. gh-issue: 129715 +.. nonce: mLlpIO +.. section: Core and Builtins + +Improve JIT performance for generators. + +.. + +.. date: 2025-02-05-11-29-52 +.. gh-issue: 129643 +.. nonce: 4mGzvg +.. section: Core and Builtins + +Fix thread safety of :c:func:`PyList_Insert` in free-threading builds. + +.. + +.. date: 2025-02-04-21-26-05 +.. gh-issue: 129668 +.. nonce: zDanyM +.. section: Core and Builtins + +Fix race condition when raising :exc:`MemoryError` in the free threaded +build. + +.. + +.. date: 2025-02-04-12-42-40 +.. gh-issue: 129643 +.. nonce: K24Zow +.. section: Core and Builtins + +Fix thread safety of :c:func:`PyList_SetItem` in free-threading builds. +Patch by Kumar Aditya. + +.. + +.. date: 2025-01-28-11-13-41 +.. gh-issue: 128563 +.. nonce: xElppE +.. section: Core and Builtins + +Fix an issue where the "lltrace" debug feature could have been incorrectly +enabled for some frames. + +.. + +.. date: 2025-01-28-10-26-04 +.. gh-issue: 129393 +.. nonce: 0eICq6 +.. section: Core and Builtins + +On FreeBSD, :data:`sys.platform` doesn't contain the major version anymore. +It is always ``'freebsd'``, instead of ``'freebsd13'`` or ``'freebsd14'``. + +.. + +.. date: 2025-01-28-06-23-59 +.. gh-issue: 129345 +.. nonce: uOjkML +.. section: Core and Builtins + +Fix null pointer dereference in :func:`syslog.openlog` when an audit hook +raises an exception. + +.. + +.. date: 2025-01-24-11-37-22 +.. gh-issue: 129231 +.. nonce: ZsAP9v +.. section: Core and Builtins + +Improve memory layout of JIT traces. Patch by Diego Russo + +.. + +.. date: 2025-01-22-14-24-44 +.. gh-issue: 129149 +.. nonce: wAYu43 +.. section: Core and Builtins + +Add fast path for medium-size integers in :c:func:`PyLong_FromUnsignedLong`, +:c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t`. + +.. + +.. date: 2025-01-22-14-22-34 +.. gh-issue: 129201 +.. nonce: wiZzEb +.. section: Core and Builtins + +The free-threaded version of the cyclic garbage collector has been optimized +to conditionally use CPU prefetch instructions during the collection. This +can reduce collection times by making it more likely that data is in the CPU +cache when it is needed. The prefetch instructions are enabled if the +number of long-lived objects (objects surviving a full collection) exceeds a +threshold. + +.. + +.. date: 2025-01-21-23-35-41 +.. gh-issue: 129093 +.. nonce: 0rvETC +.. section: Core and Builtins + +Fix f-strings such as ``f'{expr=}'`` sometimes not displaying the full +expression when the expression contains ``!=``. + +.. + +.. date: 2025-01-21-19-48-30 +.. gh-issue: 124363 +.. nonce: vOFhHW +.. section: Core and Builtins + +Treat debug expressions in f-string as raw strings. Patch by Pablo Galindo + +.. + +.. date: 2025-01-19-09-07-44 +.. gh-issue: 128714 +.. nonce: m1fyCB +.. section: Core and Builtins + +Fix the potential races in get/set dunder methods ``__annotations__``, +``__annotate__`` and ``__type_params__`` for function object, and add +related tests. + +.. + +.. date: 2025-01-18-01-06-58 +.. gh-issue: 128799 +.. nonce: vSNagk +.. section: Core and Builtins + +Add frame of ``except*`` to traceback when it wraps a naked exception. + +.. + +.. date: 2025-01-17-13-16-14 +.. gh-issue: 128842 +.. nonce: OMs5X6 +.. section: Core and Builtins + +Collect JIT memory stats using pystats. Patch by Diego Russo. + +.. + +.. date: 2025-01-16-22-54-12 +.. gh-issue: 100239 +.. nonce: 7_HpBU +.. section: Core and Builtins + +Specialize ``BINARY_OP`` for bitwise logical operations on compact ints. + +.. + +.. date: 2025-01-16-18-16-18 +.. gh-issue: 128910 +.. nonce: 9pqfab +.. section: Core and Builtins + +Undocumented and unused private C-API functions ``_PyTrash_begin`` and +``_PyTrash_end`` are removed. + +.. + +.. date: 2025-01-13-17-03-49 +.. gh-issue: 128807 +.. nonce: BGGBxD +.. section: Core and Builtins + +Add a marking phase to the free-threaded GC. This is similar to what was +done in GH-126491. Since the free-threaded GC does not have generations and +is not incremental, the marking phase looks for all objects reachable from +known roots. The roots are objects known to not be garbage, like the module +dictionary for :mod:`sys`. For most programs, this marking phase should +make the GC a bit faster since typically less work is done per object. + +.. + +.. date: 2025-01-10-23-54-16 +.. gh-issue: 100239 +.. nonce: ijOOUs +.. section: Core and Builtins + +Add opcode ``BINARY_OP_EXTEND`` which executes a pair of functions (guard +and specialization functions) accessed from the inline cache. + +.. + +.. date: 2025-01-10-18-56-20 +.. gh-issue: 128563 +.. nonce: baDvls +.. section: Core and Builtins + +A new type of interpreter has been added to CPython. This interpreter uses +tail calls for its instruction handlers. Preliminary benchmark results +suggest 7-11% geometric mean faster on pyperformance (depending on +platform), and up to 30% faster on Python-intensive workloads. This +interpreter currently only works on newer compilers, such as ``clang-19``. +Other compilers will continue using the old interpreter. Patch by Ken Jin, +with ideas on how to implement this in CPython by Mark Shannon, Garret Gu, +Haoran Xu, and Josh Haberman. + +.. + +.. date: 2025-01-07-19-26-40 +.. gh-issue: 126703 +.. nonce: 9i-S5t +.. section: Core and Builtins + +Improve performance of iterating over lists and tuples by using a freelist +for the iterator objects. + +.. + +.. date: 2024-12-30-15-49-31 +.. gh-issue: 127953 +.. nonce: B4_6L9 +.. section: Core and Builtins + +The time to handle a ``LINE`` event in sys.monitoring (and sys.settrace) is +now independent of the number of lines in the code object. + +.. + +.. date: 2024-12-29-15-09-21 +.. gh-issue: 128330 +.. nonce: IaYL7G +.. section: Core and Builtins + +Restore terminal control characters on REPL exit. + +.. + +.. date: 2024-12-17-09-28-17 +.. gh-issue: 128016 +.. nonce: DPqhah +.. section: Core and Builtins + +Improved the ``SyntaxWarning`` message for invalid escape sequences to +clarify that such sequences will raise a ``SyntaxError`` in future Python +releases. The new message also suggests a potential fix, i.e., ``Did you +mean "\\e"?``. + +.. + +.. date: 2024-12-06-11-32-58 +.. gh-issue: 126004 +.. nonce: CYAwTB +.. section: Core and Builtins + +Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end` +values in the :func:`codecs.replace_errors` error handler. Patch by Bénédikt +Tran. + +.. + +.. date: 2024-12-06-11-30-58 +.. gh-issue: 126004 +.. nonce: -p8MAS +.. section: Core and Builtins + +Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end` +values in the :func:`codecs.backslashreplace_errors` error handler. Patch by +Bénédikt Tran. + +.. + +.. date: 2024-12-06-11-17-46 +.. gh-issue: 126004 +.. nonce: -p8MAS +.. section: Core and Builtins + +Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end` +values in the :func:`codecs.xmlcharrefreplace_errors` error handler. Patch +by Bénédikt Tran. + +.. + +.. date: 2024-12-04-22-14-40 +.. gh-issue: 127119 +.. nonce: _hpyFE +.. section: Core and Builtins + +Slightly optimize the :class:`int` deallocator. + +.. + +.. date: 2024-11-30-16-13-31 +.. gh-issue: 127349 +.. nonce: ssYd6n +.. section: Core and Builtins + +Fixed the error when resizing terminal in Python REPL. Patch by Semyon +Moroz. + +.. + +.. date: 2024-11-18-12-17-45 +.. gh-issue: 125723 +.. nonce: tW_hFG +.. section: Core and Builtins + +Fix crash with ``gi_frame.f_locals`` when generator frames outlive their +generator. Patch by Mikhail Efimov. + +.. + +.. date: 2024-11-03-06-05-16 +.. gh-issue: 126349 +.. nonce: 7YwWsI +.. section: Core and Builtins + +Add :func:`turtle.fill`, :func:`turtle.poly` and :func:`turtle.no_animation` +context managers. Patch by Marie Roald and Yngve Mardal Moe. + +.. + +.. date: 2024-02-29-16-55-52 +.. gh-issue: 115911 +.. nonce: Vnkue_ +.. section: Core and Builtins + +If the current working directory cannot be determined due to permissions, +then import will no longer raise :exc:`PermissionError`. Patch by Alex +Willmer. + +.. + +.. date: 2023-12-04-15-53-25 +.. gh-issue: 112713 +.. nonce: Zrhv77 +.. section: Core and Builtins + +Added support for the ``Partitioned`` cookie flag in :mod:`http.cookies`. + +.. + +.. date: 2025-02-02-12-58-21 +.. gh-issue: 129533 +.. nonce: dFfqkT +.. section: C API + +Update :c:func:`PyGC_Enable()`, :c:func:`PyGC_Disable()`, +:c:func:`PyGC_IsEnabled()` to use atomic operation for thread-safety at +free-threading build. Patch by Donghee Na. + +.. + +.. date: 2025-01-29-11-58-38 +.. gh-issue: 89188 +.. nonce: BsfLr3 +.. section: C API + +Implement :c:func:`PyUnicode_KIND` and :c:func:`PyUnicode_DATA` as function, +in addition to the macros with the same names. The macros rely on C bit +fields which have compiler-specific layout. Patch by Victor Stinner. + +.. + +.. date: 2025-01-28-13-21-17 +.. gh-issue: 91417 +.. nonce: AfiR0t +.. section: C API + +Remove :c:func:`PySequence_Fast` from the limited C API, since this function +has to be used with :c:macro:`PySequence_Fast_GET_ITEM` which never worked +in the limited C API. Patch by Victor Stinner. + +.. + +.. date: 2025-01-22-09-28-04 +.. gh-issue: 128509 +.. nonce: gqQ36L +.. section: C API + +Add :c:func:`PyUnstable_IsImmortal` for determining whether an object is +:term:`immortal`. + +.. + +.. date: 2025-01-20-10-40-11 +.. gh-issue: 129033 +.. nonce: d1jltB +.. section: C API + +Remove ``_PyInterpreterState_GetConfigCopy()`` and +``_PyInterpreterState_SetConfig()`` private functions. Use instead +:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set`, public C API added by +:pep:`741` "Python Configuration C API". Patch by Victor Stinner. + +.. + +.. date: 2025-01-19-23-17-58 +.. gh-issue: 129033 +.. nonce: cpRivP +.. section: C API + +Remove the private ``_Py_InitializeMain()`` function. It was a +:term:`provisional API` added to Python 3.8 by :pep:`587`. Patch by Victor +Stinner. + +.. + +.. date: 2025-01-16-21-56-49 +.. gh-issue: 128844 +.. nonce: ZPiJuo +.. section: C API + +Add :c:func:`PyUnstable_TryIncRef` and :c:func:`PyUnstable_EnableTryIncRef` +unstable APIs. These are helpers for dealing with unowned references in a +thread-safe way, particularly in the free threading build. + +.. + +.. date: 2025-01-16-12-47-01 +.. gh-issue: 128911 +.. nonce: mHVJ4x +.. section: C API + +Add :c:func:`PyImport_ImportModuleAttr` and +:c:func:`PyImport_ImportModuleAttrString` helper functions to import a +module and get an attribute of the module. Patch by Victor Stinner. + +.. + +.. date: 2025-01-15-11-42-07 +.. gh-issue: 128863 +.. nonce: C9MkB_ +.. section: C API + +The following private functions are deprecated and planned for removal in +Python 3.18: + +* :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`. +* :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`. +* :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`. +* :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`. +* :c:func:`!_PyLong_FromDigits` and :c:func:`!_PyLong_New`: + use :c:func:`PyLongWriter_Create`. +* :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`. +* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`. +* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`. +* :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`. + +The `pythoncapi-compat project +`__ can be used to get these +new public functions on Python 3.13 and older. + +Patch by Victor Stinner. + +.. + +.. date: 2025-01-01-03-25-38 +.. gh-issue: 126599 +.. nonce: MRCYlH +.. section: C API + +Remove some internal test APIs for the experimental JIT compiler. + +.. + +.. date: 2024-12-14-03-40-15 +.. gh-issue: 127925 +.. nonce: FF7aov +.. section: C API + +Convert the :mod:`decimal` module to use :pep:`757` C API (export-import +integers), offering some speed-up if the integer part of the +:class:`~decimal.Decimal` instance is small. Patch by Sergey B Kirpichev. + +.. + +.. date: 2025-02-04-12-30-43 +.. gh-issue: 129660 +.. nonce: SitXa7 +.. section: Build + +Drop ``test_embed`` from PGO training, whose contribution in recent versions +is considered to be ignorable. + +.. + +.. date: 2025-01-16-03-35-37 +.. gh-issue: 128902 +.. nonce: Dt7xtV +.. section: Build + +Fix compile errors with Clang 9 and older due to lack of +``__attribute__((fallthrough))`` support. diff --git a/Misc/NEWS.d/next/Build/2025-01-16-03-35-37.gh-issue-128902.Dt7xtV.rst b/Misc/NEWS.d/next/Build/2025-01-16-03-35-37.gh-issue-128902.Dt7xtV.rst deleted file mode 100644 index 42ac492498e029..00000000000000 --- a/Misc/NEWS.d/next/Build/2025-01-16-03-35-37.gh-issue-128902.Dt7xtV.rst +++ /dev/null @@ -1 +0,0 @@ -Fix compile errors with Clang 9 and older due to lack of ``__attribute__((fallthrough))`` support. diff --git a/Misc/NEWS.d/next/Build/2025-02-04-12-30-43.gh-issue-129660.SitXa7.rst b/Misc/NEWS.d/next/Build/2025-02-04-12-30-43.gh-issue-129660.SitXa7.rst deleted file mode 100644 index 945f91be63809a..00000000000000 --- a/Misc/NEWS.d/next/Build/2025-02-04-12-30-43.gh-issue-129660.SitXa7.rst +++ /dev/null @@ -1,2 +0,0 @@ -Drop ``test_embed`` from PGO training, whose contribution in recent -versions is considered to be ignorable. diff --git a/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst new file mode 100644 index 00000000000000..2463e4dba24ae9 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst @@ -0,0 +1 @@ +Allow building the JIT with the tailcall interpreter. diff --git a/Misc/NEWS.d/next/C_API/2024-12-14-03-40-15.gh-issue-127925.FF7aov.rst b/Misc/NEWS.d/next/C_API/2024-12-14-03-40-15.gh-issue-127925.FF7aov.rst deleted file mode 100644 index 6cf5fd2872cd43..00000000000000 --- a/Misc/NEWS.d/next/C_API/2024-12-14-03-40-15.gh-issue-127925.FF7aov.rst +++ /dev/null @@ -1,3 +0,0 @@ -Convert the :mod:`decimal` module to use :pep:`757` C API (export-import -integers), offering some speed-up if the integer part of the -:class:`~decimal.Decimal` instance is small. Patch by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/C_API/2025-01-01-03-25-38.gh-issue-126599.MRCYlH.rst b/Misc/NEWS.d/next/C_API/2025-01-01-03-25-38.gh-issue-126599.MRCYlH.rst deleted file mode 100644 index 8362ee3a2b1760..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-01-03-25-38.gh-issue-126599.MRCYlH.rst +++ /dev/null @@ -1 +0,0 @@ -Remove some internal test APIs for the experimental JIT compiler. diff --git a/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst b/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst deleted file mode 100644 index b2e5664138fba2..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-15-11-42-07.gh-issue-128863.C9MkB_.rst +++ /dev/null @@ -1,19 +0,0 @@ -The following private functions are deprecated and planned for removal in -Python 3.18: - -* :c:func:`!_PyBytes_Join`: use :c:func:`PyBytes_Join`. -* :c:func:`!_PyDict_GetItemStringWithError`: use :c:func:`PyDict_GetItemStringRef`. -* :c:func:`!_PyDict_Pop()`: use :c:func:`PyDict_Pop`. -* :c:func:`!_PyLong_Sign()`: use :c:func:`PyLong_GetSign`. -* :c:func:`!_PyLong_FromDigits` and :c:func:`!_PyLong_New`: - use :c:func:`PyLongWriter_Create`. -* :c:func:`!_PyThreadState_UncheckedGet`: use :c:func:`PyThreadState_GetUnchecked`. -* :c:func:`!_PyUnicode_AsString`: use :c:func:`PyUnicode_AsUTF8`. -* :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`. -* :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`. - -The `pythoncapi-compat project -`__ can be used to get these new -public functions on Python 3.13 and older. - -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2025-01-16-12-47-01.gh-issue-128911.mHVJ4x.rst b/Misc/NEWS.d/next/C_API/2025-01-16-12-47-01.gh-issue-128911.mHVJ4x.rst deleted file mode 100644 index d32cd00cd5d605..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-16-12-47-01.gh-issue-128911.mHVJ4x.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :c:func:`PyImport_ImportModuleAttr` and :c:func:`PyImport_ImportModuleAttrString` -helper functions to import a module and get an attribute of the module. Patch -by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2025-01-16-21-56-49.gh-issue-128844.ZPiJuo.rst b/Misc/NEWS.d/next/C_API/2025-01-16-21-56-49.gh-issue-128844.ZPiJuo.rst deleted file mode 100644 index d9e1962631026a..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-16-21-56-49.gh-issue-128844.ZPiJuo.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add :c:func:`PyUnstable_TryIncRef` and :c:func:`PyUnstable_EnableTryIncRef` -unstable APIs. These are helpers for dealing with unowned references in -a thread-safe way, particularly in the free threading build. diff --git a/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst b/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst deleted file mode 100644 index 3cd19cc48e3416..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-19-23-17-58.gh-issue-129033.cpRivP.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove the private ``_Py_InitializeMain()`` function. It was a -:term:`provisional API` added to Python 3.8 by :pep:`587`. Patch by Victor -Stinner. diff --git a/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst b/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst deleted file mode 100644 index c0c109d5ce1ca2..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst +++ /dev/null @@ -1,4 +0,0 @@ -Remove ``_PyInterpreterState_GetConfigCopy()`` and -``_PyInterpreterState_SetConfig()`` private functions. Use instead -:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set`, public C API added by -:pep:`741` "Python Configuration C API". Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2025-01-22-09-28-04.gh-issue-128509.gqQ36L.rst b/Misc/NEWS.d/next/C_API/2025-01-22-09-28-04.gh-issue-128509.gqQ36L.rst deleted file mode 100644 index c4a048fe3195d1..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-22-09-28-04.gh-issue-128509.gqQ36L.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :c:func:`PyUnstable_IsImmortal` for determining whether an object is -:term:`immortal`. diff --git a/Misc/NEWS.d/next/C_API/2025-01-28-13-21-17.gh-issue-91417.AfiR0t.rst b/Misc/NEWS.d/next/C_API/2025-01-28-13-21-17.gh-issue-91417.AfiR0t.rst deleted file mode 100644 index e1017188b8d0ce..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-28-13-21-17.gh-issue-91417.AfiR0t.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove :c:func:`PySequence_Fast` from the limited C API, since this function -has to be used with :c:macro:`PySequence_Fast_GET_ITEM` which never worked -in the limited C API. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2025-01-29-11-58-38.gh-issue-89188.BsfLr3.rst b/Misc/NEWS.d/next/C_API/2025-01-29-11-58-38.gh-issue-89188.BsfLr3.rst deleted file mode 100644 index 7ff225a7dc60c7..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-01-29-11-58-38.gh-issue-89188.BsfLr3.rst +++ /dev/null @@ -1,3 +0,0 @@ -Implement :c:func:`PyUnicode_KIND` and :c:func:`PyUnicode_DATA` as function, -in addition to the macros with the same names. The macros rely on C bit -fields which have compiler-specific layout. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst b/Misc/NEWS.d/next/C_API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst deleted file mode 100644 index 20e93e2bcc1f47..00000000000000 --- a/Misc/NEWS.d/next/C_API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst +++ /dev/null @@ -1,3 +0,0 @@ -Update :c:func:`PyGC_Enable()`, :c:func:`PyGC_Disable()`, -:c:func:`PyGC_IsEnabled()` to use atomic operation for thread-safety -at free-threading build. Patch by Donghee Na. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2021-06-09-23-04-58.bpo-44369.R7QkFv.rst b/Misc/NEWS.d/next/Core_and_Builtins/2021-06-09-23-04-58.bpo-44369.R7QkFv.rst new file mode 100644 index 00000000000000..234dfb21f1ea16 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2021-06-09-23-04-58.bpo-44369.R7QkFv.rst @@ -0,0 +1 @@ +Improve syntax errors for incorrectly closed strings. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst b/Misc/NEWS.d/next/Core_and_Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst deleted file mode 100644 index ee1f33f95647bd..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2023-12-04-15-53-25.gh-issue-112713.Zrhv77.rst +++ /dev/null @@ -1 +0,0 @@ -Added support for the ``Partitioned`` cookie flag in :mod:`http.cookies`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-02-29-16-55-52.gh-issue-115911.Vnkue_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-02-29-16-55-52.gh-issue-115911.Vnkue_.rst deleted file mode 100644 index 717804be95b18b..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-02-29-16-55-52.gh-issue-115911.Vnkue_.rst +++ /dev/null @@ -1,3 +0,0 @@ -If the current working directory cannot be determined due to permissions, -then import will no longer raise :exc:`PermissionError`. Patch by Alex -Willmer. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-23-30-35.gh-issue-125331.quKQ7V.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-23-30-35.gh-issue-125331.quKQ7V.rst new file mode 100644 index 00000000000000..a87467a5ba554b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-29-23-30-35.gh-issue-125331.quKQ7V.rst @@ -0,0 +1,5 @@ +``from __future__ import barry_as_FLUFL`` now works in more contexts, +including when it is used in files, with the ``-c`` flag, and in the REPL +when there are multiple statements on the same line. Previously, it worked +only on subsequent lines in the REPL, and when the appropriate flags were +passed directly to :func:`compile`. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-11-03-06-05-16.gh-issue-126349.7YwWsI.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-11-03-06-05-16.gh-issue-126349.7YwWsI.rst deleted file mode 100644 index aecc8c9abf3ce9..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-11-03-06-05-16.gh-issue-126349.7YwWsI.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :func:`turtle.fill`, :func:`turtle.poly` and :func:`turtle.no_animation` context managers. -Patch by Marie Roald and Yngve Mardal Moe. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-11-18-12-17-45.gh-issue-125723.tW_hFG.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-11-18-12-17-45.gh-issue-125723.tW_hFG.rst deleted file mode 100644 index 62ca6f62f521a8..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-11-18-12-17-45.gh-issue-125723.tW_hFG.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix crash with ``gi_frame.f_locals`` when generator frames outlive their -generator. Patch by Mikhail Efimov. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-11-30-16-13-31.gh-issue-127349.ssYd6n.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-11-30-16-13-31.gh-issue-127349.ssYd6n.rst deleted file mode 100644 index 3c1586b6cbb8e7..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-11-30-16-13-31.gh-issue-127349.ssYd6n.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed the error when resizing terminal in Python REPL. Patch by Semyon -Moroz. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-04-22-14-40.gh-issue-127119._hpyFE.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-04-22-14-40.gh-issue-127119._hpyFE.rst deleted file mode 100644 index f021bd490f488c..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-04-22-14-40.gh-issue-127119._hpyFE.rst +++ /dev/null @@ -1 +0,0 @@ -Slightly optimize the :class:`int` deallocator. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-17-46.gh-issue-126004.-p8MAS.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-17-46.gh-issue-126004.-p8MAS.rst deleted file mode 100644 index 60b1c5d8b80793..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-17-46.gh-issue-126004.-p8MAS.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end` -values in the :func:`codecs.xmlcharrefreplace_errors` error handler. -Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-30-58.gh-issue-126004.-p8MAS.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-30-58.gh-issue-126004.-p8MAS.rst deleted file mode 100644 index 619d73042a9bb8..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-30-58.gh-issue-126004.-p8MAS.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end` -values in the :func:`codecs.backslashreplace_errors` error handler. Patch by -Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-32-58.gh-issue-126004.CYAwTB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-32-58.gh-issue-126004.CYAwTB.rst deleted file mode 100644 index de70c59ee48eec..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-06-11-32-58.gh-issue-126004.CYAwTB.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix handling of :attr:`UnicodeError.start` and :attr:`UnicodeError.end` -values in the :func:`codecs.replace_errors` error handler. Patch by Bénédikt -Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-17-09-28-17.gh-issue-128016.DPqhah.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-17-09-28-17.gh-issue-128016.DPqhah.rst deleted file mode 100644 index 0832d777bc3251..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-17-09-28-17.gh-issue-128016.DPqhah.rst +++ /dev/null @@ -1 +0,0 @@ -Improved the ``SyntaxWarning`` message for invalid escape sequences to clarify that such sequences will raise a ``SyntaxError`` in future Python releases. The new message also suggests a potential fix, i.e., ``Did you mean "\\e"?``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-29-15-09-21.gh-issue-128330.IaYL7G.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-29-15-09-21.gh-issue-128330.IaYL7G.rst deleted file mode 100644 index 8fe628d18f4bd4..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-29-15-09-21.gh-issue-128330.IaYL7G.rst +++ /dev/null @@ -1 +0,0 @@ -Restore terminal control characters on REPL exit. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-30-15-49-31.gh-issue-127953.B4_6L9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-30-15-49-31.gh-issue-127953.B4_6L9.rst deleted file mode 100644 index f19afcd90b16ea..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-30-15-49-31.gh-issue-127953.B4_6L9.rst +++ /dev/null @@ -1,2 +0,0 @@ -The time to handle a ``LINE`` event in sys.monitoring (and sys.settrace) is -now independent of the number of lines in the code object. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-07-19-26-40.gh-issue-126703.9i-S5t.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-07-19-26-40.gh-issue-126703.9i-S5t.rst deleted file mode 100644 index dcd5f449c98ef3..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-07-19-26-40.gh-issue-126703.9i-S5t.rst +++ /dev/null @@ -1 +0,0 @@ -Improve performance of iterating over lists and tuples by using a freelist for the iterator objects. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-18-56-20.gh-issue-128563.baDvls.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-18-56-20.gh-issue-128563.baDvls.rst deleted file mode 100644 index 4d29f346cb6251..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-18-56-20.gh-issue-128563.baDvls.rst +++ /dev/null @@ -1 +0,0 @@ -A new type of interpreter has been added to CPython. This interpreter uses tail calls for its instruction handlers. Preliminary benchmark results suggest 7-11% geometric mean faster on pyperformance (depending on platform), and up to 30% faster on Python-intensive workloads. This interpreter currently only works on newer compilers, such as ``clang-19``. Other compilers will continue using the old interpreter. Patch by Ken Jin, with ideas on how to implement this in CPython by Mark Shannon, Garret Gu, Haoran Xu, and Josh Haberman. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-23-54-16.gh-issue-100239.ijOOUs.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-23-54-16.gh-issue-100239.ijOOUs.rst deleted file mode 100644 index f58c1fc767515e..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-23-54-16.gh-issue-100239.ijOOUs.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add opcode ``BINARY_OP_EXTEND`` which executes a pair of functions (guard and -specialization functions) accessed from the inline cache. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-13-17-03-49.gh-issue-128807.BGGBxD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-13-17-03-49.gh-issue-128807.BGGBxD.rst deleted file mode 100644 index 34952e9abb66e5..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-13-17-03-49.gh-issue-128807.BGGBxD.rst +++ /dev/null @@ -1,6 +0,0 @@ -Add a marking phase to the free-threaded GC. This is similar to what was -done in GH-126491. Since the free-threaded GC does not have generations and -is not incremental, the marking phase looks for all objects reachable from -known roots. The roots are objects known to not be garbage, like the module -dictionary for :mod:`sys`. For most programs, this marking phase should -make the GC a bit faster since typically less work is done per object. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-16-18-16-18.gh-issue-128910.9pqfab.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-16-18-16-18.gh-issue-128910.9pqfab.rst deleted file mode 100644 index e095ba9ebf6be4..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-16-18-16-18.gh-issue-128910.9pqfab.rst +++ /dev/null @@ -1,2 +0,0 @@ -Undocumented and unused private C-API functions ``_PyTrash_begin`` and -``_PyTrash_end`` are removed. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-16-22-54-12.gh-issue-100239.7_HpBU.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-16-22-54-12.gh-issue-100239.7_HpBU.rst deleted file mode 100644 index 6f086b7ecc0036..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-16-22-54-12.gh-issue-100239.7_HpBU.rst +++ /dev/null @@ -1 +0,0 @@ -Specialize ``BINARY_OP`` for bitwise logical operations on compact ints. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-13-16-14.gh-issue-128842.OMs5X6.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-13-16-14.gh-issue-128842.OMs5X6.rst deleted file mode 100644 index 9898060076db79..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-17-13-16-14.gh-issue-128842.OMs5X6.rst +++ /dev/null @@ -1 +0,0 @@ -Collect JIT memory stats using pystats. Patch by Diego Russo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-18-01-06-58.gh-issue-128799.vSNagk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-18-01-06-58.gh-issue-128799.vSNagk.rst deleted file mode 100644 index eb2361bb5d4525..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-18-01-06-58.gh-issue-128799.vSNagk.rst +++ /dev/null @@ -1 +0,0 @@ -Add frame of ``except*`` to traceback when it wraps a naked exception. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-19-09-07-44.gh-issue-128714.m1fyCB.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-19-09-07-44.gh-issue-128714.m1fyCB.rst deleted file mode 100644 index 431032241e9157..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-19-09-07-44.gh-issue-128714.m1fyCB.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the potential races in get/set dunder methods ``__annotations__``, ``__annotate__`` and ``__type_params__`` for function object, and add related tests. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-21-19-48-30.gh-issue-124363.vOFhHW.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-21-19-48-30.gh-issue-124363.vOFhHW.rst deleted file mode 100644 index 553aa5a4dd573e..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-21-19-48-30.gh-issue-124363.vOFhHW.rst +++ /dev/null @@ -1 +0,0 @@ -Treat debug expressions in f-string as raw strings. Patch by Pablo Galindo diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-21-23-35-41.gh-issue-129093.0rvETC.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-21-23-35-41.gh-issue-129093.0rvETC.rst deleted file mode 100644 index 067d52eff2da1e..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-21-23-35-41.gh-issue-129093.0rvETC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix f-strings such as ``f'{expr=}'`` sometimes not displaying the full -expression when the expression contains ``!=``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-22-34.gh-issue-129201.wiZzEb.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-22-34.gh-issue-129201.wiZzEb.rst deleted file mode 100644 index 26737330716181..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-22-34.gh-issue-129201.wiZzEb.rst +++ /dev/null @@ -1,5 +0,0 @@ -The free-threaded version of the cyclic garbage collector has been optimized to -conditionally use CPU prefetch instructions during the collection. This can -reduce collection times by making it more likely that data is in the CPU cache -when it is needed. The prefetch instructions are enabled if the number of -long-lived objects (objects surviving a full collection) exceeds a threshold. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst deleted file mode 100644 index d946f6a2fea185..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add fast path for medium-size integers in :c:func:`PyLong_FromUnsignedLong`, -:c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-24-11-37-22.gh-issue-129231.ZsAP9v.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-24-11-37-22.gh-issue-129231.ZsAP9v.rst deleted file mode 100644 index b30492a1947058..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-24-11-37-22.gh-issue-129231.ZsAP9v.rst +++ /dev/null @@ -1 +0,0 @@ -Improve memory layout of JIT traces. Patch by Diego Russo diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-06-23-59.gh-issue-129345.uOjkML.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-06-23-59.gh-issue-129345.uOjkML.rst deleted file mode 100644 index 68e1103db45652..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-06-23-59.gh-issue-129345.uOjkML.rst +++ /dev/null @@ -1 +0,0 @@ -Fix null pointer dereference in :func:`syslog.openlog` when an audit hook raises an exception. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-10-26-04.gh-issue-129393.0eICq6.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-10-26-04.gh-issue-129393.0eICq6.rst deleted file mode 100644 index e36e6f565efd81..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-10-26-04.gh-issue-129393.0eICq6.rst +++ /dev/null @@ -1,2 +0,0 @@ -On FreeBSD, :data:`sys.platform` doesn't contain the major version anymore. -It is always ``'freebsd'``, instead of ``'freebsd13'`` or ``'freebsd14'``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-11-13-41.gh-issue-128563.xElppE.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-11-13-41.gh-issue-128563.xElppE.rst deleted file mode 100644 index dfd932e836bda6..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-28-11-13-41.gh-issue-128563.xElppE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue where the "lltrace" debug feature could have been incorrectly -enabled for some frames. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-04-12-42-40.gh-issue-129643.K24Zow.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-04-12-42-40.gh-issue-129643.K24Zow.rst deleted file mode 100644 index 27dd3b7f652aca..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-04-12-42-40.gh-issue-129643.K24Zow.rst +++ /dev/null @@ -1 +0,0 @@ -Fix thread safety of :c:func:`PyList_SetItem` in free-threading builds. Patch by Kumar Aditya. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-04-21-26-05.gh-issue-129668.zDanyM.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-04-21-26-05.gh-issue-129668.zDanyM.rst deleted file mode 100644 index e42ef57c3164a1..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-04-21-26-05.gh-issue-129668.zDanyM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix race condition when raising :exc:`MemoryError` in the free threaded -build. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-11-29-52.gh-issue-129643.4mGzvg.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-11-29-52.gh-issue-129643.4mGzvg.rst deleted file mode 100644 index 420e1fb9781ff3..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-11-29-52.gh-issue-129643.4mGzvg.rst +++ /dev/null @@ -1 +0,0 @@ -Fix thread safety of :c:func:`PyList_Insert` in free-threading builds. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-22-58-18.gh-issue-129715.mLlpIO.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-22-58-18.gh-issue-129715.mLlpIO.rst deleted file mode 100644 index f8eb7481aea350..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-05-22-58-18.gh-issue-129715.mLlpIO.rst +++ /dev/null @@ -1 +0,0 @@ -Improve JIT performance for generators. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-06-17-05-09.gh-issue-129763.6ZxQ8W.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-06-17-05-09.gh-issue-129763.6ZxQ8W.rst deleted file mode 100644 index ffb96c20fcad7e..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-06-17-05-09.gh-issue-129763.6ZxQ8W.rst +++ /dev/null @@ -1 +0,0 @@ -Remove the internal ``LLTRACE`` macro (use :c:macro:`Py_DEBUG` instead). diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-06-17-57-33.gh-issue-129732.yl97oq.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-06-17-57-33.gh-issue-129732.yl97oq.rst deleted file mode 100644 index a4b104af61692a..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-06-17-57-33.gh-issue-129732.yl97oq.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a race in ``_Py_qsbr_reserve`` in the free threading build. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-07-17-06-39.gh-issue-100239.WvBTPL.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-07-17-06-39.gh-issue-100239.WvBTPL.rst deleted file mode 100644 index 428111cff1bc79..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-07-17-06-39.gh-issue-100239.WvBTPL.rst +++ /dev/null @@ -1 +0,0 @@ -Replace the opcode BINARY_SUBSCR and its family by BINARY_OP with oparg NB_SUBSCR. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-10-11-30-13.gh-issue-129953.wipsl_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-10-11-30-13.gh-issue-129953.wipsl_.rst new file mode 100644 index 00000000000000..db9905eeaeef9c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-10-11-30-13.gh-issue-129953.wipsl_.rst @@ -0,0 +1,4 @@ +The internal (evaluation) stack is now spilled to memory whenever execution +esacpes from the interpreter or JIT compiled code. This should have no +observable effect in either Python or builtin extensions, but will allow +various important optimizations in the future. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-10-20-01-56.gh-issue-129967.J60tEl.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-10-20-01-56.gh-issue-129967.J60tEl.rst new file mode 100644 index 00000000000000..69ec03d2ae3824 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-10-20-01-56.gh-issue-129967.J60tEl.rst @@ -0,0 +1,2 @@ +Fix a race condition in the :term:`free threading` build when ``repr(set)`` +is called concurrently with ``set.clear()``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst new file mode 100644 index 00000000000000..9b435703eb734a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst @@ -0,0 +1 @@ +Fix data race in compile_template in :file:`sre.c`. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-22-20-21.gh-issue-129715.mopO8n.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-22-20-21.gh-issue-129715.mopO8n.rst new file mode 100644 index 00000000000000..e71602b06a33ce --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-22-20-21.gh-issue-129715.mopO8n.rst @@ -0,0 +1 @@ +Improve the experimental JIT's handling of returns to unknown callers. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-13-00-28-43.gh-issue-116042.861juq.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-13-00-28-43.gh-issue-116042.861juq.rst new file mode 100644 index 00000000000000..098804fa92e804 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-13-00-28-43.gh-issue-116042.861juq.rst @@ -0,0 +1,2 @@ +Fix location for SyntaxErrors of invalid escapes in the tokenizer. Patch by +Pablo Galindo diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-13-02-39-42.gh-issue-107956.dLguDW.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-13-02-39-42.gh-issue-107956.dLguDW.rst new file mode 100644 index 00000000000000..737ecdca159a17 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-13-02-39-42.gh-issue-107956.dLguDW.rst @@ -0,0 +1,2 @@ +A ``build-details.json`` file is now install in the platform-independent +standard library directory (:pep:`739` implementation). diff --git a/Misc/NEWS.d/next/Documentation/2025-01-14-11-06-41.gh-issue-67206.LYKmi5.rst b/Misc/NEWS.d/next/Documentation/2025-01-14-11-06-41.gh-issue-67206.LYKmi5.rst deleted file mode 100644 index 11fb617e98edc3..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2025-01-14-11-06-41.gh-issue-67206.LYKmi5.rst +++ /dev/null @@ -1,3 +0,0 @@ -Document that :const:`string.printable` is not printable in the POSIX sense. -In particular, :meth:`string.printable.isprintable() ` returns -:const:`False`. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Documentation/2025-01-16-18-59-11.gh-issue-125722.eHHRga.rst b/Misc/NEWS.d/next/Documentation/2025-01-16-18-59-11.gh-issue-125722.eHHRga.rst deleted file mode 100644 index bf6253eed2eb90..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2025-01-16-18-59-11.gh-issue-125722.eHHRga.rst +++ /dev/null @@ -1,2 +0,0 @@ -Require Sphinx 8.1.3 or later to build the Python documentation. Patch by -Adam Turner. diff --git a/Misc/NEWS.d/next/IDLE/2025-02-08-23-42-24.gh-issue-129873.-gofkd.rst b/Misc/NEWS.d/next/IDLE/2025-02-08-23-42-24.gh-issue-129873.-gofkd.rst deleted file mode 100644 index d13f11550fc02d..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2025-02-08-23-42-24.gh-issue-129873.-gofkd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Simplify displaying the IDLE doc by only copying the text section of -idle.html to idlelib/help.html. Patch by Stan Ulbrych. diff --git a/Misc/NEWS.d/next/Library/2020-08-07-16-55-57.bpo-27307.Xqzzda.rst b/Misc/NEWS.d/next/Library/2020-08-07-16-55-57.bpo-27307.Xqzzda.rst deleted file mode 100644 index 6e7a856d994cb6..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-08-07-16-55-57.bpo-27307.Xqzzda.rst +++ /dev/null @@ -1 +0,0 @@ -Add attribute and item access support to :class:`string.Formatter` in auto-numbering mode, which allows format strings like '{.name}' and '{[1]}'. diff --git a/Misc/NEWS.d/next/Library/2022-05-23-21-23-29.gh-issue-81340.D11RkZ.rst b/Misc/NEWS.d/next/Library/2022-05-23-21-23-29.gh-issue-81340.D11RkZ.rst deleted file mode 100644 index 49e6305bf83138..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-05-23-21-23-29.gh-issue-81340.D11RkZ.rst +++ /dev/null @@ -1,5 +0,0 @@ -Use :func:`os.copy_file_range` in :func:`shutil.copy`, :func:`shutil.copy2`, -and :func:`shutil.copyfile` functions by default. An underlying Linux system -call gives filesystems an opportunity to implement the use of copy-on-write -(in case of btrfs and XFS) or server-side copy (in the case of NFS.) -Patch by Illia Volochii. diff --git a/Misc/NEWS.d/next/Library/2023-02-01-16-41-31.gh-issue-101410.Dt2aQE.rst b/Misc/NEWS.d/next/Library/2023-02-01-16-41-31.gh-issue-101410.Dt2aQE.rst deleted file mode 100644 index 31493686daec97..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-01-16-41-31.gh-issue-101410.Dt2aQE.rst +++ /dev/null @@ -1,3 +0,0 @@ -Support custom messages for domain errors in the :mod:`math` module -(:func:`math.sqrt`, :func:`math.log` and :func:`math.atanh` were modified as -examples). Patch by Charlie Zhao and Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Library/2024-07-14-23-19-20.gh-issue-119257.9OEzcN.rst b/Misc/NEWS.d/next/Library/2024-07-14-23-19-20.gh-issue-119257.9OEzcN.rst deleted file mode 100644 index 8f3f863d93e021..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-07-14-23-19-20.gh-issue-119257.9OEzcN.rst +++ /dev/null @@ -1,2 +0,0 @@ -Show tab completions menu below the current line, which results in less -janky behaviour, and fixes a cursor movement bug. Patch by Daniel Hollas diff --git a/Misc/NEWS.d/next/Library/2024-08-01-01-00-00.gh-issue-55454.wy0vGw.rst b/Misc/NEWS.d/next/Library/2024-08-01-01-00-00.gh-issue-55454.wy0vGw.rst deleted file mode 100644 index 58fc85963217c9..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-08-01-01-00-00.gh-issue-55454.wy0vGw.rst +++ /dev/null @@ -1 +0,0 @@ -Add IMAP4 ``IDLE`` support to the :mod:`imaplib` module. Patch by Forest. diff --git a/Misc/NEWS.d/next/Library/2024-08-12-11-58-15.gh-issue-119349.-xTnHl.rst b/Misc/NEWS.d/next/Library/2024-08-12-11-58-15.gh-issue-119349.-xTnHl.rst deleted file mode 100644 index 5dd8264a608dfa..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-08-12-11-58-15.gh-issue-119349.-xTnHl.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add the :func:`ctypes.util.dllist` function to list the loaded shared -libraries for the current process. diff --git a/Misc/NEWS.d/next/Library/2024-09-12-14-24-25.gh-issue-123987.7_OD1p.rst b/Misc/NEWS.d/next/Library/2024-09-12-14-24-25.gh-issue-123987.7_OD1p.rst deleted file mode 100644 index b110900e7efd33..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-09-12-14-24-25.gh-issue-123987.7_OD1p.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed issue in NamespaceReader where a non-path item in a namespace path, -such as a sentinel added by an editable installer, would break resource -loading. diff --git a/Misc/NEWS.d/next/Library/2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst b/Misc/NEWS.d/next/Library/2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst deleted file mode 100644 index e55d3539355d73..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-09-27-19-21-53.gh-issue-124703.lYTLEv.rst +++ /dev/null @@ -1 +0,0 @@ -Quitting :mod:`pdb` in ``inline`` mode will emit a confirmation prompt and exit gracefully now, instead of printing an exception traceback. diff --git a/Misc/NEWS.d/next/Library/2024-10-02-11-17-23.gh-issue-91048.QWY-b1.rst b/Misc/NEWS.d/next/Library/2024-10-02-11-17-23.gh-issue-91048.QWY-b1.rst deleted file mode 100644 index c2faf470ffc9cf..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-10-02-11-17-23.gh-issue-91048.QWY-b1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :func:`asyncio.capture_call_graph` and -:func:`asyncio.print_call_graph` functions. diff --git a/Misc/NEWS.d/next/Library/2024-10-20-13-01-05.gh-issue-125746.wDLTay.rst b/Misc/NEWS.d/next/Library/2024-10-20-13-01-05.gh-issue-125746.wDLTay.rst new file mode 100644 index 00000000000000..387d793fd209d9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-20-13-01-05.gh-issue-125746.wDLTay.rst @@ -0,0 +1,2 @@ +Delay deprecated :meth:`zipimport.zipimporter.load_module` removal +time to 3.15. Use :meth:`zipimport.zipimporter.exec_module` instead. diff --git a/Misc/NEWS.d/next/Library/2024-10-26-16-59-02.gh-issue-125553.4pDLzt.rst b/Misc/NEWS.d/next/Library/2024-10-26-16-59-02.gh-issue-125553.4pDLzt.rst deleted file mode 100644 index 291c5e6f6f2181..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-10-26-16-59-02.gh-issue-125553.4pDLzt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix round-trip invariance for backslash continuations in -:func:`tokenize.untokenize`. diff --git a/Misc/NEWS.d/next/Library/2024-11-10-19-45-01.gh-issue-126332.WCCKoH.rst b/Misc/NEWS.d/next/Library/2024-11-10-19-45-01.gh-issue-126332.WCCKoH.rst deleted file mode 100644 index 9277797ddc745e..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-11-10-19-45-01.gh-issue-126332.WCCKoH.rst +++ /dev/null @@ -1 +0,0 @@ -Fix _pyrepl crash when entering a double CTRL-Z on an overflowing line. diff --git a/Misc/NEWS.d/next/Library/2024-11-23-21-17-28.gh-issue-124369.Z0hQFQ.rst b/Misc/NEWS.d/next/Library/2024-11-23-21-17-28.gh-issue-124369.Z0hQFQ.rst deleted file mode 100644 index 31840da74a2dea..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-11-23-21-17-28.gh-issue-124369.Z0hQFQ.rst +++ /dev/null @@ -1 +0,0 @@ -Deprecate ``pdb.Pdb.curframe_locals`` diff --git a/Misc/NEWS.d/next/Library/2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst b/Misc/NEWS.d/next/Library/2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst deleted file mode 100644 index 8619296143b7d7..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-11-24-22-06-42.gh-issue-127096.R7LLpQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Do not recreate unnamed section on every read in -:class:`configparser.ConfigParser`. Patch by Andrey Efremov. diff --git a/Misc/NEWS.d/next/Library/2024-11-27-23-29-05.gh-issue-109798.OPj1CT.rst b/Misc/NEWS.d/next/Library/2024-11-27-23-29-05.gh-issue-109798.OPj1CT.rst new file mode 100644 index 00000000000000..89b66d13d38df3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-27-23-29-05.gh-issue-109798.OPj1CT.rst @@ -0,0 +1 @@ +Added additional information into error messages in :mod:`datetime`, and made the messages more consistent between the C and Python implementations. Patch by Semyon Moroz. diff --git a/Misc/NEWS.d/next/Library/2024-12-07-20-33-43.gh-issue-127712.Uzsij4.rst b/Misc/NEWS.d/next/Library/2024-12-07-20-33-43.gh-issue-127712.Uzsij4.rst deleted file mode 100644 index 40450cddc956c1..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-07-20-33-43.gh-issue-127712.Uzsij4.rst +++ /dev/null @@ -1 +0,0 @@ -Fix handling of the ``secure`` argument of :class:`logging.handlers.SMTPHandler`. diff --git a/Misc/NEWS.d/next/Library/2024-12-10-19-39-35.gh-issue-125413.wOb4yr.rst b/Misc/NEWS.d/next/Library/2024-12-10-19-39-35.gh-issue-125413.wOb4yr.rst deleted file mode 100644 index 9ac96179a88367..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-10-19-39-35.gh-issue-125413.wOb4yr.rst +++ /dev/null @@ -1,6 +0,0 @@ -Add :attr:`pathlib.Path.info` attribute, which stores an object -implementing the :class:`pathlib.types.PathInfo` protocol (also new). The -object supports querying the file type and internally caching -:func:`~os.stat` results. Path objects generated by -:meth:`~pathlib.Path.iterdir` are initialized with file type information -gleaned from scanning the parent directory. diff --git a/Misc/NEWS.d/next/Library/2024-12-12-18-25-50.gh-issue-127873.WJRwfz.rst b/Misc/NEWS.d/next/Library/2024-12-12-18-25-50.gh-issue-127873.WJRwfz.rst deleted file mode 100644 index d7575c7efb6e88..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-12-18-25-50.gh-issue-127873.WJRwfz.rst +++ /dev/null @@ -1,3 +0,0 @@ -When ``-E`` is set, only ignore ``PYTHON_COLORS`` and not -``FORCE_COLOR``/``NO_COLOR``/``TERM`` when colourising output. -Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2024-12-16-22-20-38.gh-issue-121604.m3Xn4G.rst b/Misc/NEWS.d/next/Library/2024-12-16-22-20-38.gh-issue-121604.m3Xn4G.rst deleted file mode 100644 index 8edd8dfb604878..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-16-22-20-38.gh-issue-121604.m3Xn4G.rst +++ /dev/null @@ -1 +0,0 @@ -Add missing Deprecation warnings for :const:`importlib.machinery.DEBUG_BYTECODE_SUFFIXES`, :const:`importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES`, :class:`importlib.machinery.WindowsRegistryFinder`, :class:`importlib.abc.ResourceLoader`, :meth:`importlib.abc.SourceLoader.path_mtime`. diff --git a/Misc/NEWS.d/next/Library/2024-12-17-16-48-02.gh-issue-115514.1yOJ7T.rst b/Misc/NEWS.d/next/Library/2024-12-17-16-48-02.gh-issue-115514.1yOJ7T.rst deleted file mode 100644 index 24e836a0b0b7f9..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-17-16-48-02.gh-issue-115514.1yOJ7T.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix exceptions and incomplete writes after :class:`!asyncio._SelectorTransport` -is closed before writes are completed. diff --git a/Misc/NEWS.d/next/Library/2024-12-20-08-44-12.gh-issue-127975.8HJwu9.rst b/Misc/NEWS.d/next/Library/2024-12-20-08-44-12.gh-issue-127975.8HJwu9.rst deleted file mode 100644 index 597fa41deb811c..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-20-08-44-12.gh-issue-127975.8HJwu9.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid reusing quote types in :func:`ast.unparse` if not needed. diff --git a/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst b/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst deleted file mode 100644 index f4c4ebce10729c..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-21-03-20-12.gh-issue-128131.QpPmNt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Completely support random access of uncompressed unencrypted read-only -zip files obtained by :meth:`ZipFile.open `. diff --git a/Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst b/Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst deleted file mode 100644 index b78bc5aaf44217..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-23-02-09-44.gh-issue-58956.4OdMdT.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a frame reference leak in :mod:`bdb`. diff --git a/Misc/NEWS.d/next/Library/2024-12-26-11-00-03.gh-issue-112064.mCcw3B.rst b/Misc/NEWS.d/next/Library/2024-12-26-11-00-03.gh-issue-112064.mCcw3B.rst deleted file mode 100644 index e885add7b68c0f..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-26-11-00-03.gh-issue-112064.mCcw3B.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix incorrect handling of negative read sizes in :meth:`HTTPResponse.read -`. Patch by Yury Manushkin. diff --git a/Misc/NEWS.d/next/Library/2024-12-30-19-53-14.gh-issue-91279.EeOJk1.rst b/Misc/NEWS.d/next/Library/2024-12-30-19-53-14.gh-issue-91279.EeOJk1.rst deleted file mode 100644 index 30ee2ea5efd069..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-12-30-19-53-14.gh-issue-91279.EeOJk1.rst +++ /dev/null @@ -1,3 +0,0 @@ -:meth:`zipfile.ZipFile.writestr` now respect ``SOURCE_DATE_EPOCH`` that -distributions can set centrally and have build tools consume this in order -to produce reproducible output. diff --git a/Misc/NEWS.d/next/Library/2025-01-02-20-34-04.gh-issue-128427.onPoQZ.rst b/Misc/NEWS.d/next/Library/2025-01-02-20-34-04.gh-issue-128427.onPoQZ.rst deleted file mode 100644 index 54cae43702ded7..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-02-20-34-04.gh-issue-128427.onPoQZ.rst +++ /dev/null @@ -1,2 +0,0 @@ -:const:`uuid.NIL` and :const:`uuid.MAX` are now available to represent the Nil -and Max UUID formats as defined by :rfc:`9562`. diff --git a/Misc/NEWS.d/next/Library/2025-01-04-11-10-04.gh-issue-128479.jvOrF-.rst b/Misc/NEWS.d/next/Library/2025-01-04-11-10-04.gh-issue-128479.jvOrF-.rst deleted file mode 100644 index fc3b4d5a5273a6..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-04-11-10-04.gh-issue-128479.jvOrF-.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`!asyncio.staggered.staggered_race` leaking tasks and issuing an unhandled exception. diff --git a/Misc/NEWS.d/next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst b/Misc/NEWS.d/next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst deleted file mode 100644 index ba45884304f662..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-04-20-51-48.gh-issue-128509.3gr_-O.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :func:`sys._is_immortal` for identifying :term:`immortal` objects at -runtime. diff --git a/Misc/NEWS.d/next/Library/2025-01-06-10-37-27.gh-issue-128384.V0xzwH.rst b/Misc/NEWS.d/next/Library/2025-01-06-10-37-27.gh-issue-128384.V0xzwH.rst deleted file mode 100644 index 2ca592be20b681..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-06-10-37-27.gh-issue-128384.V0xzwH.rst +++ /dev/null @@ -1,5 +0,0 @@ -Add locking to :mod:`warnings` to avoid some data races when free-threading -is used. Change ``_warnings_runtime_state.mutex`` to be a recursive mutex -and expose it to :mod:`warnings`, via the :func:`!_acquire_lock` and -:func:`!_release_lock` functions. The lock is held when ``filters`` and -``_filters_version`` are updated. diff --git a/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst b/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst deleted file mode 100644 index 9a241e37c20a44..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-07-21-48-32.gh-issue-128498.n6jtlW.rst +++ /dev/null @@ -1,2 +0,0 @@ -Default to stdout isatty for color detection instead of stderr. Patch by -Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2025-01-08-22-30-38.gh-issue-128636.jQfWXj.rst b/Misc/NEWS.d/next/Library/2025-01-08-22-30-38.gh-issue-128636.jQfWXj.rst deleted file mode 100644 index 80c9840b585530..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-08-22-30-38.gh-issue-128636.jQfWXj.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix PyREPL failure when :data:`os.environ` is overwritten with an invalid -value. diff --git a/Misc/NEWS.d/next/Library/2025-01-09-16-20-34.gh-issue-128156.GfObBq.rst b/Misc/NEWS.d/next/Library/2025-01-09-16-20-34.gh-issue-128156.GfObBq.rst deleted file mode 100644 index ec6a55040ae6cb..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-09-16-20-34.gh-issue-128156.GfObBq.rst +++ /dev/null @@ -1,3 +0,0 @@ -When using macOS system ``libffi``, support for complex types in -:mod:`ctypes` is now checked at runtime (macOS 10.15 or newer). The types -must also be available at build time. diff --git a/Misc/NEWS.d/next/Library/2025-01-10-13-06-54.gh-issue-118761.f8oADD.rst b/Misc/NEWS.d/next/Library/2025-01-10-13-06-54.gh-issue-118761.f8oADD.rst deleted file mode 100644 index 37c25cb2efd034..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-10-13-06-54.gh-issue-118761.f8oADD.rst +++ /dev/null @@ -1,5 +0,0 @@ -Improve the performance of :func:`base64.b16decode` by up to ten times -by more efficiently checking the byte-string for hexadecimal digits. -Reduce the import time of :mod:`base64` by up to six times, -by no longer importing :mod:`re`. -Patch by Bénédikt Tran, Chris Markiewicz, and Adam Turner. diff --git a/Misc/NEWS.d/next/Library/2025-01-13-07-54-32.gh-issue-128308.kYSDRF.rst b/Misc/NEWS.d/next/Library/2025-01-13-07-54-32.gh-issue-128308.kYSDRF.rst deleted file mode 100644 index efa613876a35fd..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-13-07-54-32.gh-issue-128308.kYSDRF.rst +++ /dev/null @@ -1 +0,0 @@ -Support the *name* keyword argument for eager tasks in :func:`asyncio.loop.create_task`, :func:`asyncio.create_task` and :func:`asyncio.TaskGroup.create_task`, by passing on all *kwargs* to the task factory set by :func:`asyncio.loop.set_task_factory`. diff --git a/Misc/NEWS.d/next/Library/2025-01-15-09-45-43.gh-issue-118761.TvAC8E.rst b/Misc/NEWS.d/next/Library/2025-01-15-09-45-43.gh-issue-118761.TvAC8E.rst deleted file mode 100644 index 38d18b7f4ca05e..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-15-09-45-43.gh-issue-118761.TvAC8E.rst +++ /dev/null @@ -1,3 +0,0 @@ -Reduce the import time of :mod:`csv` by up to five times, by importing -:mod:`re` on demand. In particular, ``re`` is no more implicitly exposed -as ``csv.re``. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2025-01-15-12-04-30.gh-issue-128703.6WPf38.rst b/Misc/NEWS.d/next/Library/2025-01-15-12-04-30.gh-issue-128703.6WPf38.rst new file mode 100644 index 00000000000000..1e6af90bc04b63 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-15-12-04-30.gh-issue-128703.6WPf38.rst @@ -0,0 +1,2 @@ +Fix :func:`mimetypes.guess_type` to use default mapping for empty +``Content-Type`` in registry. diff --git a/Misc/NEWS.d/next/Library/2025-01-15-15-45-21.gh-issue-128657.P5LNQA.rst b/Misc/NEWS.d/next/Library/2025-01-15-15-45-21.gh-issue-128657.P5LNQA.rst deleted file mode 100644 index 3b08a9fba59620..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-15-15-45-21.gh-issue-128657.P5LNQA.rst +++ /dev/null @@ -1 +0,0 @@ -Fix possible extra reference when using objects returned by :func:`hashlib.sha256` under :term:`free threading`. diff --git a/Misc/NEWS.d/next/Library/2025-01-15-18-54-48.gh-issue-118761.G1dv6E.rst b/Misc/NEWS.d/next/Library/2025-01-15-18-54-48.gh-issue-118761.G1dv6E.rst deleted file mode 100644 index 4144ef8f40e6dd..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-15-18-54-48.gh-issue-118761.G1dv6E.rst +++ /dev/null @@ -1,2 +0,0 @@ -Reduce the import time of :mod:`optparse` when no help text is printed. -Patch by Eli Schwartz. diff --git a/Misc/NEWS.d/next/Library/2025-01-15-19-16-50.gh-issue-118761.cbW2ZL.rst b/Misc/NEWS.d/next/Library/2025-01-15-19-16-50.gh-issue-118761.cbW2ZL.rst deleted file mode 100644 index 0eef8777512dd8..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-15-19-16-50.gh-issue-118761.cbW2ZL.rst +++ /dev/null @@ -1,3 +0,0 @@ -Reduce import time of :mod:`gettext` by up to ten times, by importing -:mod:`re` on demand. In particular, ``re`` is no longer implicitly -exposed as ``gettext.re``. Patch by Eli Schwartz. diff --git a/Misc/NEWS.d/next/Library/2025-01-15-19-32-23.gh-issue-128891.ojUxKo.rst b/Misc/NEWS.d/next/Library/2025-01-15-19-32-23.gh-issue-128891.ojUxKo.rst deleted file mode 100644 index 79d845bbab7cfc..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-15-19-32-23.gh-issue-128891.ojUxKo.rst +++ /dev/null @@ -1 +0,0 @@ -Add specialized opcodes to ``opcode.opname``. diff --git a/Misc/NEWS.d/next/Library/2025-01-15-21-41-51.gh-issue-128679.tq10F2.rst b/Misc/NEWS.d/next/Library/2025-01-15-21-41-51.gh-issue-128679.tq10F2.rst deleted file mode 100644 index 5c108da5703c00..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-15-21-41-51.gh-issue-128679.tq10F2.rst +++ /dev/null @@ -1,3 +0,0 @@ -:mod:`tracemalloc`: Fix race conditions when :func:`tracemalloc.stop` is -called by a thread, while other threads are tracing memory allocations. -Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2025-01-16-10-06-40.gh-issue-118761.z100LC.rst b/Misc/NEWS.d/next/Library/2025-01-16-10-06-40.gh-issue-118761.z100LC.rst deleted file mode 100644 index ea71ecaaeb2936..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-16-10-06-40.gh-issue-118761.z100LC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve import time of :mod:`tomllib` by removing ``typing``, ``string``, -and ``tomllib._types`` imports. Patch by Taneli Hukkinen. diff --git a/Misc/NEWS.d/next/Library/2025-01-17-11-46-16.gh-issue-128916.GEePbO.rst b/Misc/NEWS.d/next/Library/2025-01-17-11-46-16.gh-issue-128916.GEePbO.rst deleted file mode 100644 index f2db341ef81621..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-17-11-46-16.gh-issue-128916.GEePbO.rst +++ /dev/null @@ -1,3 +0,0 @@ -Do not attempt to set ``SO_REUSEPORT`` on sockets of address families -other than ``AF_INET`` and ``AF_INET6``, as it is meaningless with these -address families, and the call with fail with Linux kernel 6.12.9 and newer. diff --git a/Misc/NEWS.d/next/Library/2025-01-17-17-20-51.gh-issue-128894.gX1-8J.rst b/Misc/NEWS.d/next/Library/2025-01-17-17-20-51.gh-issue-128894.gX1-8J.rst deleted file mode 100644 index 7e015103a95713..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-17-17-20-51.gh-issue-128894.gX1-8J.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``traceback.TracebackException._format_syntax_error`` not to fail on -exceptions with custom metadata. diff --git a/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst b/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst deleted file mode 100644 index 9c985df77743da..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-17-21-33-11.gh-issue-128961.XwvyIZ.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a crash when setting state on an exhausted :class:`array.array` iterator. diff --git a/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst b/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst deleted file mode 100644 index 521496d6a2f8c2..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a :exc:`NameError` in :func:`!sysconfig.expand_makefile_vars`. Patch by -Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2025-01-18-11-24-02.gh-issue-118761.G8MmxY.rst b/Misc/NEWS.d/next/Library/2025-01-18-11-24-02.gh-issue-118761.G8MmxY.rst deleted file mode 100644 index 3b3f3f7d98c5d6..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-18-11-24-02.gh-issue-118761.G8MmxY.rst +++ /dev/null @@ -1,2 +0,0 @@ -Reduce import time of :mod:`pstats` and :mod:`zipfile` by up to 20%, by -removing unnecessary imports to :mod:`typing`. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2025-01-18-16-58-10.gh-issue-128991.EzJit9.rst b/Misc/NEWS.d/next/Library/2025-01-18-16-58-10.gh-issue-128991.EzJit9.rst deleted file mode 100644 index 64fa04fb53e89c..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-18-16-58-10.gh-issue-128991.EzJit9.rst +++ /dev/null @@ -1 +0,0 @@ -Release the enter frame reference within :mod:`bdb` callback diff --git a/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst b/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst deleted file mode 100644 index f59feac795ea18..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-20-13-12-39.gh-issue-128550.AJ5TOL.rst +++ /dev/null @@ -1 +0,0 @@ -Removed an incorrect optimization relating to eager tasks in :class:`asyncio.TaskGroup` that resulted in cancellations being missed. diff --git a/Misc/NEWS.d/next/Library/2025-01-20-16-02-38.gh-issue-129064.JXasgJ.rst b/Misc/NEWS.d/next/Library/2025-01-20-16-02-38.gh-issue-129064.JXasgJ.rst deleted file mode 100644 index 93a1eda350d1fc..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-20-16-02-38.gh-issue-129064.JXasgJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecate :func:`!sysconfig.expand_makefile_vars`, in favor of using -:func:`sysconfig.get_paths` with the ``vars`` argument. diff --git a/Misc/NEWS.d/next/Library/2025-01-20-20-59-26.gh-issue-92897.G0xH8o.rst b/Misc/NEWS.d/next/Library/2025-01-20-20-59-26.gh-issue-92897.G0xH8o.rst deleted file mode 100644 index 632ca03bbf8dd2..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-20-20-59-26.gh-issue-92897.G0xH8o.rst +++ /dev/null @@ -1,2 +0,0 @@ -Scheduled the deprecation of the ``check_home`` argument of -:func:`sysconfig.is_python_build` to Python 3.15. diff --git a/Misc/NEWS.d/next/Library/2025-01-21-18-52-32.gh-issue-129061.4idD_B.rst b/Misc/NEWS.d/next/Library/2025-01-21-18-52-32.gh-issue-129061.4idD_B.rst deleted file mode 100644 index 5c5c05e1161e86..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-21-18-52-32.gh-issue-129061.4idD_B.rst +++ /dev/null @@ -1 +0,0 @@ -Fix FORCE_COLOR and NO_COLOR when empty strings. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2025-01-22-13-29-06.gh-issue-128772.6YrxYM.rst b/Misc/NEWS.d/next/Library/2025-01-22-13-29-06.gh-issue-128772.6YrxYM.rst deleted file mode 100644 index 53d6b3ccaffda8..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-22-13-29-06.gh-issue-128772.6YrxYM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :mod:`pydoc` for methods with the ``__module__`` attribute equal to -``None``. diff --git a/Misc/NEWS.d/next/Library/2025-01-22-16-54-25.gh-issue-129205.FMqrUt.rst b/Misc/NEWS.d/next/Library/2025-01-22-16-54-25.gh-issue-129205.FMqrUt.rst deleted file mode 100644 index c4ed76408f32f6..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-22-16-54-25.gh-issue-129205.FMqrUt.rst +++ /dev/null @@ -1 +0,0 @@ -Add :func:`os.readinto` to read into a :ref:`buffer object ` from a file descriptor. diff --git a/Misc/NEWS.d/next/Library/2025-01-24-10-48-32.gh-issue-129195.89d5NU.rst b/Misc/NEWS.d/next/Library/2025-01-24-10-48-32.gh-issue-129195.89d5NU.rst deleted file mode 100644 index daf7297387dabd..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-24-10-48-32.gh-issue-129195.89d5NU.rst +++ /dev/null @@ -1 +0,0 @@ -Support reporting call graph information from :func:`!asyncio.staggered.staggered_race`. diff --git a/Misc/NEWS.d/next/Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst b/Misc/NEWS.d/next/Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst deleted file mode 100644 index a825e9d244d525..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-26-10-01-21.gh-issue-129005.ncpLvw.rst +++ /dev/null @@ -1 +0,0 @@ -Optimize ``_pyio.FileIO.readinto`` by avoiding unnecessary objects and copies using :func:`os.readinto`. diff --git a/Misc/NEWS.d/next/Library/2025-01-26-19-35-06.gh-issue-96092.mMg3gL.rst b/Misc/NEWS.d/next/Library/2025-01-26-19-35-06.gh-issue-96092.mMg3gL.rst new file mode 100644 index 00000000000000..623f7d278c6675 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-01-26-19-35-06.gh-issue-96092.mMg3gL.rst @@ -0,0 +1,4 @@ +Fix bug in :func:`traceback.walk_stack` called with None where it was skipping +more frames than in prior versions. This bug fix also changes walk_stack to +walk the stack in the frame where it was called rather than where it first gets +used. diff --git a/Misc/NEWS.d/next/Library/2025-01-27-14-05-19.gh-issue-129346.gZRd3g.rst b/Misc/NEWS.d/next/Library/2025-01-27-14-05-19.gh-issue-129346.gZRd3g.rst deleted file mode 100644 index b5377277f6c51c..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-27-14-05-19.gh-issue-129346.gZRd3g.rst +++ /dev/null @@ -1,2 +0,0 @@ -In :mod:`sqlite3`, handle out-of-memory when creating user-defined SQL -functions. diff --git a/Misc/NEWS.d/next/Library/2025-01-29-10-53-32.gh-issue-118761.i8wjpV.rst b/Misc/NEWS.d/next/Library/2025-01-29-10-53-32.gh-issue-118761.i8wjpV.rst deleted file mode 100644 index 0762cbe5d63949..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-29-10-53-32.gh-issue-118761.i8wjpV.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve import time of :mod:`subprocess` by lazy importing ``locale`` and -``signal``. Patch by Taneli Hukkinen. diff --git a/Misc/NEWS.d/next/Library/2025-01-29-11-14-20.gh-issue-118761.gMZwE1.rst b/Misc/NEWS.d/next/Library/2025-01-29-11-14-20.gh-issue-118761.gMZwE1.rst deleted file mode 100644 index c2474795d8233e..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-29-11-14-20.gh-issue-118761.gMZwE1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Always lazy import ``warnings`` in :mod:`threading`. Patch by Taneli -Hukkinen. diff --git a/Misc/NEWS.d/next/Library/2025-01-29-13-37-18.gh-issue-126400.DaBaR3.rst b/Misc/NEWS.d/next/Library/2025-01-29-13-37-18.gh-issue-126400.DaBaR3.rst deleted file mode 100644 index 1532faf4b7d6f5..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-29-13-37-18.gh-issue-126400.DaBaR3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a socket *timeout* keyword argument to -:class:`logging.handlers.SysLogHandler`. diff --git a/Misc/NEWS.d/next/Library/2025-01-29-14-30-54.gh-issue-129409.JZbOE6.rst b/Misc/NEWS.d/next/Library/2025-01-29-14-30-54.gh-issue-129409.JZbOE6.rst deleted file mode 100644 index 7e00b44c0ef471..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-29-14-30-54.gh-issue-129409.JZbOE6.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an integer overflow in the :mod:`csv` module when writing a data field -larger than 2GB. diff --git a/Misc/NEWS.d/next/Library/2025-01-29-17-10-00.gh-issue-129403.314159.rst b/Misc/NEWS.d/next/Library/2025-01-29-17-10-00.gh-issue-129403.314159.rst deleted file mode 100644 index 0c2bdd3136e3a3..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-29-17-10-00.gh-issue-129403.314159.rst +++ /dev/null @@ -1 +0,0 @@ -Corrected :exc:`ValueError` message for :class:`asyncio.Barrier` and :class:`threading.Barrier`. diff --git a/Misc/NEWS.d/next/Library/2025-01-31-11-14-05.gh-issue-129502.j_ArNo.rst b/Misc/NEWS.d/next/Library/2025-01-31-11-14-05.gh-issue-129502.j_ArNo.rst deleted file mode 100644 index e9e9d12c11d0ac..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-01-31-11-14-05.gh-issue-129502.j_ArNo.rst +++ /dev/null @@ -1,5 +0,0 @@ -Unlikely errors in preparing arguments for :mod:`ctypes` callback are now -handled in the same way as errors raised in the callback of in converting -the result of the callback -- using :func:`sys.unraisablehook` instead of -:func:`sys.excepthook` and not setting :data:`sys.last_exc` and other -variables. diff --git a/Misc/NEWS.d/next/Library/2025-02-01-14-55-33.gh-issue-129559.hQCeAz.rst b/Misc/NEWS.d/next/Library/2025-02-01-14-55-33.gh-issue-129559.hQCeAz.rst deleted file mode 100644 index f08d47b63a84b7..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-02-01-14-55-33.gh-issue-129559.hQCeAz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :meth:`bytearray.resize` method so :class:`bytearray` can be efficiently -resized in place. diff --git a/Misc/NEWS.d/next/Library/2025-02-03-01-43-16.gh-issue-129603.xge9Tx.rst b/Misc/NEWS.d/next/Library/2025-02-03-01-43-16.gh-issue-129603.xge9Tx.rst deleted file mode 100644 index 0d0ec21bddd28f..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-02-03-01-43-16.gh-issue-129603.xge9Tx.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix bugs where :class:`sqlite3.Row` objects could segfault if their -inherited :attr:`~sqlite3.Cursor.description` was set to ``None``. Patch by -Erlend Aasland. diff --git a/Misc/NEWS.d/next/Library/2025-02-03-22-31-43.gh-issue-128317.n2Swnh.rst b/Misc/NEWS.d/next/Library/2025-02-03-22-31-43.gh-issue-128317.n2Swnh.rst deleted file mode 100644 index eaff03384a976a..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-02-03-22-31-43.gh-issue-128317.n2Swnh.rst +++ /dev/null @@ -1,2 +0,0 @@ -Put CLI calendar highlighting in private class, removing ``highlight_day`` -from public :class:`calendar.TextCalendar` API. Patch by Hugo van Kemenade. diff --git a/Misc/NEWS.d/next/Library/2025-02-04-15-16-33.gh-issue-129646.sapk1F.rst b/Misc/NEWS.d/next/Library/2025-02-04-15-16-33.gh-issue-129646.sapk1F.rst deleted file mode 100644 index 742d1d60dfd1bc..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-02-04-15-16-33.gh-issue-129646.sapk1F.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update the locale alias mapping in the :mod:`locale` module to match the -latest X Org locale alias mapping and support new locales in Glibc 2.41. diff --git a/Misc/NEWS.d/next/Library/2025-02-05-13-19-15.gh-issue-129005.Sb69L_.rst b/Misc/NEWS.d/next/Library/2025-02-05-13-19-15.gh-issue-129005.Sb69L_.rst deleted file mode 100644 index 236d7766b92cc6..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-02-05-13-19-15.gh-issue-129005.Sb69L_.rst +++ /dev/null @@ -1,2 +0,0 @@ -``_pyio.FileIO.readall()`` now allocates, resizes, and fills a data buffer -using the same algorithm ``_io.FileIO.readall()`` uses. diff --git a/Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst b/Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst deleted file mode 100644 index 76e908300a858d..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-02-07-10-34-09.gh-issue-129766.6n5fQZ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix crash in :mod:`warnings`, when calling ``_release_lock()`` with no -existing lock. diff --git a/Misc/NEWS.d/next/Library/2025-02-08-15-13-43.gh-issue-97850.jQ0CvW.rst b/Misc/NEWS.d/next/Library/2025-02-08-15-13-43.gh-issue-97850.jQ0CvW.rst new file mode 100644 index 00000000000000..7b29ffe224cffa --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-08-15-13-43.gh-issue-97850.jQ0CvW.rst @@ -0,0 +1,2 @@ +Update the deprecation warning of +:meth:`importlib.abc.Loader.load_module`. diff --git a/Misc/NEWS.d/next/Library/2025-02-09-17-47-01.gh-issue-129583.-130Ys.rst b/Misc/NEWS.d/next/Library/2025-02-09-17-47-01.gh-issue-129583.-130Ys.rst deleted file mode 100644 index 9f24a83df12dd3..00000000000000 --- a/Misc/NEWS.d/next/Library/2025-02-09-17-47-01.gh-issue-129583.-130Ys.rst +++ /dev/null @@ -1 +0,0 @@ -Update bundled pip to 25.0.1 diff --git a/Misc/NEWS.d/next/Library/2025-02-10-09-45-49.gh-issue-129889.PBHXU5.rst b/Misc/NEWS.d/next/Library/2025-02-10-09-45-49.gh-issue-129889.PBHXU5.rst new file mode 100644 index 00000000000000..f0880e5de8412e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-10-09-45-49.gh-issue-129889.PBHXU5.rst @@ -0,0 +1,2 @@ +Support context manager protocol by :class:`contextvars.Token`. Patch by +Andrew Svetlov. diff --git a/Misc/NEWS.d/next/Security/2024-05-24-21-00-52.gh-issue-119511.jKrXQ8.rst b/Misc/NEWS.d/next/Security/2024-05-24-21-00-52.gh-issue-119511.jKrXQ8.rst deleted file mode 100644 index f7b4031120e643..00000000000000 --- a/Misc/NEWS.d/next/Security/2024-05-24-21-00-52.gh-issue-119511.jKrXQ8.rst +++ /dev/null @@ -1,7 +0,0 @@ -Fix a potential denial of service in the :mod:`imaplib` module. When connecting -to a malicious server, it could cause an arbitrary amount of memory to be -allocated. On many systems this is harmless as unused virtual memory is only a -mapping, but if this hit a virtual address size limit it could lead to a -:exc:`MemoryError` or other process crash. On unusual systems or builds where -all allocated memory is touched and backed by actual ram or storage it could've -consumed resources doing so until similarly crashing. diff --git a/Misc/NEWS.d/next/Security/2024-08-06-11-43-08.gh-issue-80222.wfR4BU.rst b/Misc/NEWS.d/next/Security/2024-08-06-11-43-08.gh-issue-80222.wfR4BU.rst deleted file mode 100644 index 0f0661d0b1cf4a..00000000000000 --- a/Misc/NEWS.d/next/Security/2024-08-06-11-43-08.gh-issue-80222.wfR4BU.rst +++ /dev/null @@ -1,6 +0,0 @@ -Fix bug in the folding of quoted strings when flattening an email message using -a modern email policy. Previously when a quoted string was folded so that -it spanned more than one line, the surrounding quotes and internal escapes -would be omitted. This could theoretically be used to spoof header lines -using a carefully constructed quoted string if the resulting rendered email -was transmitted or re-parsed. diff --git a/Misc/NEWS.d/next/Security/2024-10-29-09-15-10.gh-issue-126108.eTIjHY.rst b/Misc/NEWS.d/next/Security/2024-10-29-09-15-10.gh-issue-126108.eTIjHY.rst deleted file mode 100644 index 9f2c7e84d4dff0..00000000000000 --- a/Misc/NEWS.d/next/Security/2024-10-29-09-15-10.gh-issue-126108.eTIjHY.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a possible ``NULL`` pointer dereference in :c:func:`!PySys_AddWarnOptionUnicode`. diff --git a/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst deleted file mode 100644 index bff1bc6b0d609c..00000000000000 --- a/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst +++ /dev/null @@ -1,4 +0,0 @@ -When using :func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` host -parsing would not reject domain names containing square brackets (``[`` and -``]``). Square brackets are only valid for IPv6 and IPvFuture hosts according to -`RFC 3986 Section 3.2.2 `__. diff --git a/Misc/NEWS.d/next/Tests/2024-12-16-19-15-10.gh-issue-128003.GVBrfa.rst b/Misc/NEWS.d/next/Tests/2024-12-16-19-15-10.gh-issue-128003.GVBrfa.rst deleted file mode 100644 index 05711c7e589551..00000000000000 --- a/Misc/NEWS.d/next/Tests/2024-12-16-19-15-10.gh-issue-128003.GVBrfa.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add an option ``--parallel-threads=N`` to the regression test runner that -runs individual tests in multiple threads in parallel in order to find -concurrency bugs. Note that most of the test suite is not yet reviewed for -thread-safety or annotated with ``@thread_unsafe`` when necessary. diff --git a/Misc/NEWS.d/next/Tests/2025-01-04-02-41-41.gh-issue-128474.0b-tl4.rst b/Misc/NEWS.d/next/Tests/2025-01-04-02-41-41.gh-issue-128474.0b-tl4.rst deleted file mode 100644 index 7dc807757c5ec0..00000000000000 --- a/Misc/NEWS.d/next/Tests/2025-01-04-02-41-41.gh-issue-128474.0b-tl4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Disable ``test_embed`` test cases that segfault on BOLT instrument binaries. -The tests are only disabled when BOLT is enabled. diff --git a/Misc/NEWS.d/next/Tests/2025-01-30-13-09-27.gh-issue-129386.iNtbEi.rst b/Misc/NEWS.d/next/Tests/2025-01-30-13-09-27.gh-issue-129386.iNtbEi.rst deleted file mode 100644 index a03f596bc46c30..00000000000000 --- a/Misc/NEWS.d/next/Tests/2025-01-30-13-09-27.gh-issue-129386.iNtbEi.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add ``test.support.reset_code``, which can be used to reset various -bytecode-level optimizations and local instrumentation for a function. diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-01-24-14-49-40.gh-issue-129248.JAapG2.rst b/Misc/NEWS.d/next/Tools-Demos/2025-01-24-14-49-40.gh-issue-129248.JAapG2.rst deleted file mode 100644 index e3c781cf10cf50..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2025-01-24-14-49-40.gh-issue-129248.JAapG2.rst +++ /dev/null @@ -1,2 +0,0 @@ -The iOS test runner now strips the log prefix from each line output by the -test suite. diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-02-09-20-29-06.gh-issue-129911.uMFtf1.rst b/Misc/NEWS.d/next/Tools-Demos/2025-02-09-20-29-06.gh-issue-129911.uMFtf1.rst new file mode 100644 index 00000000000000..1903af78128ffc --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2025-02-09-20-29-06.gh-issue-129911.uMFtf1.rst @@ -0,0 +1 @@ +Fix the keyword entry in the help output of :program:`pygettext`. diff --git a/Misc/NEWS.d/next/Tools-Demos/2025-02-12-14-58-54.gh-issue-130025._-mp5K.rst b/Misc/NEWS.d/next/Tools-Demos/2025-02-12-14-58-54.gh-issue-130025._-mp5K.rst new file mode 100644 index 00000000000000..ec011fe35697d9 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2025-02-12-14-58-54.gh-issue-130025._-mp5K.rst @@ -0,0 +1,2 @@ +The iOS testbed now correctly handles symlinks used as Python framework +references. diff --git a/Misc/python.man b/Misc/python.man index 4076b8d3d1ba30..eb2d0e222dea55 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -37,6 +37,9 @@ python \- an interpreted, interactive, object-oriented programming language .B \-q ] [ +.B \-R +] +[ .B \-O ] [ @@ -212,6 +215,11 @@ as the current directory, the script's directory or an empty string. See also th Do not print the version and copyright messages. These messages are also suppressed in non-interactive mode. .TP +.B \-R +Turn on hash randomization. This option only has an effect if the +\fBPYTHONHASHSEED\fR environment variable is set to \fB0\fR, since hash +randomization is enabled by default. +.TP .B \-s Don't add user site directory to sys.path. .TP @@ -313,56 +321,77 @@ a regular expression on the warning message. .BI "\-X " option Set implementation-specific option. The following options are available: - -X faulthandler: enable faulthandler - - -X showrefcount: output the total reference count and number of used - memory blocks when the program finishes or after each statement in the - interactive interpreter. This only works on debug builds + \fB-X cpu_count=\fIN\fR: override the return value of \fIos.cpu_count()\fR; + \fB-X cpu_count=default\fR cancels overriding; also \fBPYTHON_CPU_COUNT\fI - -X tracemalloc: start tracing Python memory allocations using the - tracemalloc module. By default, only the most recent frame is stored in a - traceback of a trace. Use -X tracemalloc=NFRAME to start tracing with a - traceback limit of NFRAME frames - - -X importtime: show how long each import takes. It shows module name, - cumulative time (including nested imports) and self time (excluding - nested imports). Note that its output may be broken in multi-threaded - application. Typical usage is python3 -X importtime -c 'import asyncio' - - -X dev: enable CPython's "development mode", introducing additional runtime - checks which are too expensive to be enabled by default. It will not be - more verbose than the default if the code is correct: new warnings are - only emitted when an issue is detected. Effect of the developer mode: - * Add default warning filter, as -W default - * Install debug hooks on memory allocators: see the PyMem_SetupDebugHooks() - C function - * Enable the faulthandler module to dump the Python traceback on a crash + \fB-X dev\fR: enable CPython's "development mode", introducing additional + runtime checks which are too expensive to be enabled by default. It + will not be more verbose than the default if the code is correct: new + warnings are only emitted when an issue is detected. Effect of the + developer mode: + * Add default warning filter, as \fB-W default\fR + * Install debug hooks on memory allocators: see the + PyMem_SetupDebugHooks() C function + * Enable the faulthandler module to dump the Python traceback on a + crash * Enable asyncio debug mode * Set the dev_mode attribute of sys.flags to True * io.IOBase destructor logs close() exceptions - -X utf8: enable UTF-8 mode for operating system interfaces, overriding the default - locale-aware mode. -X utf8=0 explicitly disables UTF-8 mode (even when it would - otherwise activate automatically). See PYTHONUTF8 for more details - - -X pycache_prefix=PATH: enable writing .pyc files to a parallel tree rooted at the - given directory instead of to the code tree. - - -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None' + \fB-X importtime\fR: show how long each import takes. It shows module name, + cumulative time (including nested imports) and self time (excluding + nested imports). Note that its output may be broken in multi-threaded + application. Typical usage is + \fBpython3 -X importtime -c 'import asyncio'\fR - -X no_debug_ranges: disable the inclusion of the tables mapping extra location - information (end line, start column offset and end column offset) to every - instruction in code objects. This is useful when smaller code objects and pyc - files are desired as well as suppressing the extra visual location indicators - when the interpreter displays tracebacks. + \fB-X faulthandler\fR: enable faulthandler - -X frozen_modules=[on|off]: whether or not frozen modules should be used. + \fB-X frozen_modules=\fR[\fBon\fR|\fBoff\fR]: whether or not frozen modules + should be used. The default is "on" (or "off" if you are running a local build). - -X int_max_str_digits=number: limit the size of int<->str conversions. + \fB-X gil=\fR[\fB0\fR|\fB1\fR]: enable (1) or disable (0) the GIL; also + \fBPYTHON_GIL\fR + Only available in builds configured with \fB--disable-gil\fR. + + \fB-X int_max_str_digits=\fInumber\fR: limit the size of int<->str conversions. This helps avoid denial of service attacks when parsing untrusted data. The default is sys.int_info.default_max_str_digits. 0 disables. + \fB-X no_debug_ranges\fR: disable the inclusion of the tables mapping extra + location information (end line, start column offset and end column + offset) to every instruction in code objects. This is useful when + smaller code objects and pyc files are desired as well as suppressing + the extra visual location indicators when the interpreter displays + tracebacks. + + \fB-X perf\fR: support the Linux "perf" profiler; also \fBPYTHONPERFSUPPORT=1\fR + + \fB-X perf_jit\fR: support the Linux "perf" profiler with DWARF support; + also \fBPYTHON_PERF_JIT_SUPPORT=1\fR + + \fB-X presite=\fIMOD\fR: import this module before site; also \fBPYTHON_PRESITE\fR + This only works on debug builds. + + \fB-X pycache_prefix=\fIPATH\fR: enable writing .pyc files to a parallel + tree rooted at the given directory instead of to the code tree. + + \fB-X showrefcount\fR: output the total reference count and number of used + memory blocks when the program finishes or after each statement in the + interactive interpreter. This only works on debug builds + + \fB-X tracemalloc\fR: start tracing Python memory allocations using the + tracemalloc module. By default, only the most recent frame is stored in a + traceback of a trace. Use -X tracemalloc=NFRAME to start tracing with a + traceback limit of NFRAME frames + + \fB-X utf8\fR: enable UTF-8 mode for operating system interfaces, + overriding the default locale-aware mode. \fB-X utf8=0\fR explicitly + disables UTF-8 mode (even when it would otherwise activate + automatically). See \fBPYTHONUTF8\fR for more details + + \fB-X warn_default_encoding\fR: enable opt-in EncodingWarning for 'encoding=None' + .TP .B \-x Skip the first line of the source. This is intended for a DOS @@ -447,83 +476,77 @@ needed for developing Python extensions and embedding the interpreter. .RE .SH ENVIRONMENT VARIABLES -.IP PYTHONSAFEPATH -If this is set to a non-empty string, don't automatically prepend a potentially -unsafe path to \fBsys.path\fP such as the current directory, the script's -directory or an empty string. See also the \fB\-P\fP option. -.IP PYTHONHOME -Change the location of the standard Python libraries. By default, the -libraries are searched in ${prefix}/lib/python and -${exec_prefix}/lib/python, where ${prefix} and ${exec_prefix} -are installation-dependent directories, both defaulting to -\fI/usr/local\fP. When $PYTHONHOME is set to a single directory, its value -replaces both ${prefix} and ${exec_prefix}. To specify different values -for these, set $PYTHONHOME to ${prefix}:${exec_prefix}. -.IP PYTHONPATH -Augments the default search path for module files. -The format is the same as the shell's $PATH: one or more directory -pathnames separated by colons. -Non-existent directories are silently ignored. -The default search path is installation dependent, but generally -begins with ${prefix}/lib/python (see PYTHONHOME above). -The default search path is always appended to $PYTHONPATH. -If a script argument is given, the directory containing the script is -inserted in the path in front of $PYTHONPATH. -The search path can be manipulated from within a Python program as the -variable -.IR sys.path . -.IP PYTHONPLATLIBDIR -Override sys.platlibdir. -.IP PYTHONSTARTUP -If this is the name of a readable file, the Python commands in that -file are executed before the first prompt is displayed in interactive -mode. -The file is executed in the same name space where interactive commands -are executed so that objects defined or imported in it can be used -without qualification in the interactive session. -You can also change the prompts -.I sys.ps1 -and -.I sys.ps2 -in this file. -.IP PYTHONOPTIMIZE -If this is set to a non-empty string it is equivalent to specifying -the \fB\-O\fP option. If set to an integer, it is equivalent to -specifying \fB\-O\fP multiple times. +.IP PYTHONASYNCIODEBUG +If this environment variable is set to a non-empty string, enable the debug +mode of the asyncio module. +.IP PYTHON_BASIC_REPL +If this variable is set to any value, the interpreter will not attempt to +load the Python-based REPL that requires curses and readline, and will instead +use the traditional parser-based REPL. +.IP PYTHONBREAKPOINT +If this environment variable is set to 0, it disables the default debugger. It +can be set to the callable of your debugger of choice. +.IP PYTHONCOERCECLOCALE +If set to the value 0, causes the main Python command line application to skip +coercing the legacy ASCII-based C and POSIX locales to a more capable UTF-8 +based alternative. +.IP PYTHON_COLORS +If this variable is set to 1, the interpreter will colorize various kinds of +output. Setting it to 0 deactivates this behavior. +.IP PYTHON_CPU_COUNT +If this variable is set to a positive integer, it overrides the return +values of \fIos.cpu_count\fR and \fIos.process_cpu_count\fR. +.IP +See also the \fB\-X cpu_count\fR option. .IP PYTHONDEBUG If this is set to a non-empty string it is equivalent to specifying the \fB\-d\fP option. If set to an integer, it is equivalent to specifying \fB\-d\fP multiple times. +.IP PYTHONEXECUTABLE +If this environment variable is set, +.IB sys.argv[0] +will be set to its value instead of the value got through the C runtime. Only +works on Mac OS X. +.IP PYTHONFAULTHANDLER +If this environment variable is set to a non-empty string, +.IR faulthandler.enable() +is called at startup: install a handler for SIGSEGV, SIGFPE, SIGABRT, SIGBUS +and SIGILL signals to dump the Python traceback. +.IP +This is equivalent to the \fB-X faulthandler\fP option. +.IP PYTHON_FROZEN_MODULES +If this variable is set to \fBon\fR or \fBoff\fR, it determines whether or not +frozen modules are ignored by the import machinery. A value of \fBon\fR means +they get imported and \fBoff\fR means they are ignored. The default is \fBon\fR +for non-debug builds (the normal case) and \fBoff\fR for debug builds. +.IP +See also the \fB\-X frozen_modules\fR option. +.IP PYTHON_GIL +If this variable is set to 1, the global interpreter lock (GIL) will be forced +on. Setting it to 0 forces the GIL off. Only available in builds configured +with \fB--disable-gil\fP. +.IP PYTHON_HISTORY +This environment variable can be used to set the location of a history file +(on Unix, it is \fI~/.python_history\fP by default). +.IP +This is equivalent to the \fB-X gil\fR option. +.IP PYTHONNODEBUGRANGES +If this variable is set, it disables the inclusion of the tables mapping +extra location information (end line, start column offset and end column +offset) to every instruction in code objects. This is useful when smaller code +objects and pyc files are desired as well as suppressing the extra visual +location indicators when the interpreter displays tracebacks. .IP PYTHONDONTWRITEBYTECODE If this is set to a non-empty string it is equivalent to specifying the \fB\-B\fP option (don't try to write .I .pyc files). -.IP PYTHONINSPECT -If this is set to a non-empty string it is equivalent to specifying -the \fB\-i\fP option. -.IP PYTHONIOENCODING -If this is set before running the interpreter, it overrides the encoding used -for stdin/stdout/stderr, in the syntax -.IB encodingname ":" errorhandler -The -.IB errorhandler -part is optional and has the same meaning as in str.encode. For stderr, the -.IB errorhandler - part is ignored; the handler will always be \'backslashreplace\'. -.IP PYTHONNOUSERSITE -If this is set to a non-empty string it is equivalent to specifying the -\fB\-s\fP option (Don't add the user site directory to sys.path). -.IP PYTHONUNBUFFERED -If this is set to a non-empty string it is equivalent to specifying -the \fB\-u\fP option. -.IP PYTHONVERBOSE -If this is set to a non-empty string it is equivalent to specifying -the \fB\-v\fP option. If set to an integer, it is equivalent to -specifying \fB\-v\fP multiple times. -.IP PYTHONWARNINGS -If this is set to a comma-separated string it is equivalent to -specifying the \fB\-W\fP option for each separate value. +.IP PYTHONDEVMODE +If this environment variable is set to a non-empty string, enable Python's +"development mode", introducing additional runtime checks that are too +expensive to be enabled by default. +.IP +This is equivalent to the \fB\-X dev\fR option. .IP PYTHONHASHSEED If this variable is set to "random", a random value is used to seed the hashes of str and bytes objects. @@ -536,11 +559,33 @@ values. The integer must be a decimal number in the range [0,4294967295]. Specifying the value 0 will disable hash randomization. +.IP PYTHONHOME +Change the location of the standard Python libraries. By default, the +libraries are searched in ${prefix}/lib/python and +${exec_prefix}/lib/python, where ${prefix} and ${exec_prefix} +are installation-dependent directories, both defaulting to +\fI/usr/local\fP. When $PYTHONHOME is set to a single directory, its value +replaces both ${prefix} and ${exec_prefix}. To specify different values +for these, set $PYTHONHOME to ${prefix}:${exec_prefix}. +.IP PYTHONINSPECT +If this is set to a non-empty string it is equivalent to specifying +the \fB\-i\fP option. .IP PYTHONINTMAXSTRDIGITS Limit the maximum digit characters in an int value when converting from a string and when converting an int back to a str. A value of 0 disables the limit. Conversions to or from bases 2, 4, 8, 16, and 32 are never limited. +.IP +This is equivalent to the \fB-X int_max_str_digits=\fINUMBER\fR option. +.IP PYTHONIOENCODING +If this is set before running the interpreter, it overrides the encoding used +for stdin/stdout/stderr, in the syntax +.IB encodingname ":" errorhandler +The +.IB errorhandler +part is optional and has the same meaning as in str.encode. For stderr, the +.IB errorhandler +part is ignored; the handler will always be \'backslashreplace\'. .IP PYTHONMALLOC Set the Python memory allocators and/or install debug hooks. The available memory allocators are @@ -567,9 +612,67 @@ This variable is ignored if the environment variable is used to force the .BR malloc (3) allocator of the C library, or if Python is configured without pymalloc support. -.IP PYTHONASYNCIODEBUG -If this environment variable is set to a non-empty string, enable the debug -mode of the asyncio module. +.IP PYTHONNOUSERSITE +If this is set to a non-empty string it is equivalent to specifying the +\fB\-s\fP option (Don't add the user site directory to sys.path). +.IP PYTHONOPTIMIZE +If this is set to a non-empty string it is equivalent to specifying +the \fB\-O\fP option. If set to an integer, it is equivalent to +specifying \fB\-O\fP multiple times. +.IP PYTHONPATH +Augments the default search path for module files. +The format is the same as the shell's $PATH: one or more directory +pathnames separated by colons. +Non-existent directories are silently ignored. +The default search path is installation dependent, but generally +begins with ${prefix}/lib/python (see PYTHONHOME above). +The default search path is always appended to $PYTHONPATH. +If a script argument is given, the directory containing the script is +inserted in the path in front of $PYTHONPATH. +The search path can be manipulated from within a Python program as the +variable +.IR sys.path . +.IP PYTHON_PERF_JIT_SUPPORT +If this variable is set to a nonzero value, it enables support for +the Linux perf profiler so Python calls can be detected by it using DWARF +information. +Setting to 0 disables. +.IP +See also the \fB\-X perf_jit\fR option. +.IP PYTHONPERFSUPPORT +If this variable is set to a nonzero value, it enables support for +the Linux perf profiler so Python calls can be detected by it. +Setting to 0 disables. +.IP +See also the \fB\-X perf\fR option. +.IP PYTHONPLATLIBDIR +Override sys.platlibdir. +.IP PYTHONPROFILEIMPORTTIME +If this environment variable is set to a non-empty string, Python will +show how long each import takes. This is exactly equivalent to setting +\fB\-X importtime\fP on the command line. +.IP PYTHONPYCACHEPREFIX +If this is set, Python will write \fB.pyc\fR files in a mirror directory tree +at this path, instead of in \fB__pycache__\fR directories within the source +tree. +.IP +This is equivalent to specifying the \fB\-X pycache_prefix=\fIPATH\fR option. +.IP PYTHONSAFEPATH +If this is set to a non-empty string, don't automatically prepend a potentially +unsafe path to \fBsys.path\fP such as the current directory, the script's +directory or an empty string. See also the \fB\-P\fP option. +.IP PYTHONSTARTUP +If this is the name of a readable file, the Python commands in that +file are executed before the first prompt is displayed in interactive +mode. +The file is executed in the same name space where interactive commands +are executed so that objects defined or imported in it can be used +without qualification in the interactive session. +You can also change the prompts +.I sys.ps1 +and +.I sys.ps2 +in this file. .IP PYTHONTRACEMALLOC If this environment variable is set to a non-empty string, start tracing Python memory allocations using the tracemalloc module. @@ -578,40 +681,26 @@ The value of the variable is the maximum number of frames stored in a traceback of a trace. For example, .IB PYTHONTRACEMALLOC=1 stores only the most recent frame. -.IP PYTHONFAULTHANDLER -If this environment variable is set to a non-empty string, -.IR faulthandler.enable() -is called at startup: install a handler for SIGSEGV, SIGFPE, SIGABRT, SIGBUS -and SIGILL signals to dump the Python traceback. -.IP -This is equivalent to the \fB-X faulthandler\fP option. -.IP PYTHONEXECUTABLE -If this environment variable is set, -.IB sys.argv[0] -will be set to its value instead of the value got through the C runtime. Only -works on Mac OS X. +.IP PYTHONUNBUFFERED +If this is set to a non-empty string it is equivalent to specifying +the \fB\-u\fP option. .IP PYTHONUSERBASE Defines the user base directory, which is used to compute the path of the user .IR site-packages directory and installation paths for .IR "python \-m pip install \-\-user" . -.IP PYTHONPROFILEIMPORTTIME -If this environment variable is set to a non-empty string, Python will -show how long each import takes. This is exactly equivalent to setting -\fB\-X importtime\fP on the command line. -.IP PYTHONBREAKPOINT -If this environment variable is set to 0, it disables the default debugger. It -can be set to the callable of your debugger of choice. -.IP PYTHON_COLORS -If this variable is set to 1, the interpreter will colorize various kinds of -output. Setting it to 0 deactivates this behavior. -.IP PYTHON_HISTORY -This environment variable can be used to set the location of a history file -(on Unix, it is \fI~/.python_history\fP by default). -.IP PYTHON_GIL -If this variable is set to 1, the global interpreter lock (GIL) will be forced -on. Setting it to 0 forces the GIL off. Only available in builds configured -with \fB--disable-gil\fP. +.IP PYTHONUTF8 +If set to 1, enable the Python "UTF-8 Mode". Setting to 0 disables. +.IP PYTHONVERBOSE +If this is set to a non-empty string it is equivalent to specifying +the \fB\-v\fP option. If set to an integer, it is equivalent to +specifying \fB\-v\fP multiple times. +.IP PYTHONWARNDEFAULTENCODING +If this environment variable is set to a non-empty string, issue a +\fIEncodingWarning\fR when the locale-specific default encoding is used. +.IP PYTHONWARNINGS +If this is set to a comma-separated string it is equivalent to +specifying the \fB\-W\fP option for each separate value. .SS Debug-mode variables Setting these variables only has an effect in a debug build of Python, that is, if Python was configured with the @@ -619,6 +708,17 @@ if Python was configured with the .IP PYTHONDUMPREFS If this environment variable is set, Python will dump objects and reference counts still alive after shutting down the interpreter. +.IP PYTHONDUMPREFSFILE +If set, Python will dump objects and reference counts still alive after +shutting down the interpreter into a file under the path given as the value to +this environment variable. +.IP PYTHON_PRESITE +If this variable is set to a module, that module will be imported +early in the interpreter lifecycle, before the \fIsite\fR module is +executed, and before the \fI__main__\fR module is created. +This only works on debug builds. +.IP +This is equivalent to the \fB-X presite=\fImodule\fR option. .SH AUTHOR The Python Software Foundation: https://www.python.org/psf/ .SH INTERNET RESOURCES diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 5a4e65636e4b96..ff24fd76a61733 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -413,12 +413,22 @@ future_ensure_alive(FutureObj *fut) } \ } while(0); +static void unregister_task(asyncio_state *state, TaskObj *task); static int future_schedule_callbacks(asyncio_state *state, FutureObj *fut) { _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(fut); + assert(fut->fut_state != STATE_PENDING); + + if (Task_Check(state, fut)) { + // remove task from linked-list of tasks + // as it is finished now + TaskObj *task = (TaskObj *)fut; + unregister_task(state, task); + } + if (fut->fut_callback0 != NULL) { /* There's a 1st callback */ @@ -4030,6 +4040,7 @@ add_tasks_llist(struct llist_node *head, PyListObject *tasks) struct llist_node *node; llist_for_each_safe(node, head) { TaskObj *task = llist_data(node, TaskObj, task_node); + assert(task->task_state == STATE_PENDING); // The linked list holds borrowed references to task // as such it is possible that the task is concurrently // deallocated while added to this list. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index bcbf4217d41a9b..8b202cc51788a9 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -637,17 +637,19 @@ check_date_args(int year, int month, int day) { if (year < MINYEAR || year > MAXYEAR) { - PyErr_Format(PyExc_ValueError, "year %i is out of range", year); + PyErr_Format(PyExc_ValueError, + "year must be in %d..%d, not %d", MINYEAR, MAXYEAR, year); return -1; } if (month < 1 || month > 12) { - PyErr_SetString(PyExc_ValueError, - "month must be in 1..12"); + PyErr_Format(PyExc_ValueError, + "month must be in 1..12, not %d", month); return -1; } - if (day < 1 || day > days_in_month(year, month)) { - PyErr_SetString(PyExc_ValueError, - "day is out of range for month"); + int dim = days_in_month(year, month); + if (day < 1 || day > dim) { + PyErr_Format(PyExc_ValueError, + "day must be in 1..%d, not %d", dim, day); return -1; } return 0; @@ -660,28 +662,25 @@ static int check_time_args(int h, int m, int s, int us, int fold) { if (h < 0 || h > 23) { - PyErr_SetString(PyExc_ValueError, - "hour must be in 0..23"); + PyErr_Format(PyExc_ValueError, "hour must be in 0..23, not %i", h); return -1; } if (m < 0 || m > 59) { - PyErr_SetString(PyExc_ValueError, - "minute must be in 0..59"); + PyErr_Format(PyExc_ValueError, "minute must be in 0..59, not %i", m); return -1; } if (s < 0 || s > 59) { - PyErr_SetString(PyExc_ValueError, - "second must be in 0..59"); + PyErr_Format(PyExc_ValueError, "second must be in 0..59, not %i", s); return -1; } if (us < 0 || us > 999999) { - PyErr_SetString(PyExc_ValueError, - "microsecond must be in 0..999999"); + PyErr_Format(PyExc_ValueError, + "microsecond must be in 0..999999, not %i", us); return -1; } if (fold != 0 && fold != 1) { - PyErr_SetString(PyExc_ValueError, - "fold must be either 0 or 1"); + PyErr_Format(PyExc_ValueError, + "fold must be either 0 or 1, not %i", fold); return -1; } return 0; @@ -1435,8 +1434,7 @@ new_timezone(PyObject *offset, PyObject *name) GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { PyErr_Format(PyExc_ValueError, "offset must be a timedelta" " strictly between -timedelta(hours=24) and" - " timedelta(hours=24)," - " not %R.", offset); + " timedelta(hours=24), not %R", offset); return NULL; } @@ -1505,10 +1503,10 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) GET_TD_SECONDS(offset) == 0 && GET_TD_MICROSECONDS(offset) < 1) || GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { - Py_DECREF(offset); PyErr_Format(PyExc_ValueError, "offset must be a timedelta" " strictly between -timedelta(hours=24) and" - " timedelta(hours=24)."); + " timedelta(hours=24), not %R", offset); + Py_DECREF(offset); return NULL; } } @@ -2261,7 +2259,7 @@ get_float_as_integer_ratio(PyObject *floatobj) if (!PyTuple_Check(ratio)) { PyErr_Format(PyExc_TypeError, "unexpected return type from as_integer_ratio(): " - "expected tuple, got '%.200s'", + "expected tuple, not '%.200s'", Py_TYPE(ratio)->tp_name); Py_DECREF(ratio); return NULL; @@ -3382,7 +3380,8 @@ date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw) int rv = iso_to_ymd(year, week, day, &year, &month, &day); if (rv == -4) { - PyErr_Format(PyExc_ValueError, "Year is out of range: %d", year); + PyErr_Format(PyExc_ValueError, + "year must be in %d..%d, not %d", MINYEAR, MAXYEAR, year); return NULL; } @@ -3392,7 +3391,7 @@ date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw) } if (rv == -3) { - PyErr_Format(PyExc_ValueError, "Invalid day: %d (range is [1, 7])", + PyErr_Format(PyExc_ValueError, "Invalid weekday: %d (range is [1, 7])", day); return NULL; } @@ -4378,8 +4377,7 @@ timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt) return NULL; } if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) { - PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " - "is not self"); + PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo is not self"); return NULL; } @@ -5352,7 +5350,8 @@ utc_to_seconds(int year, int month, int day, /* ymd_to_ord() doesn't support year <= 0 */ if (year < MINYEAR || year > MAXYEAR) { - PyErr_Format(PyExc_ValueError, "year %i is out of range", year); + PyErr_Format(PyExc_ValueError, + "year must be in %d..%d, not %d", MINYEAR, MAXYEAR, year); return -1; } diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index 876627bcf5fad8..ad618398d5b824 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -605,7 +605,7 @@ change_locale(int category, char **oldloc) /* Keep a copy of the LC_CTYPE locale */ *oldloc = setlocale(LC_CTYPE, NULL); if (!*oldloc) { - PyErr_SetString(PyExc_RuntimeError, "faild to get LC_CTYPE locale"); + PyErr_SetString(PyExc_RuntimeError, "failed to get LC_CTYPE locale"); return -1; } *oldloc = _PyMem_Strdup(*oldloc); diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c index 390375628bfb4f..35d090e3ca2dce 100644 --- a/Modules/_sqlite/blob.c +++ b/Modules/_sqlite/blob.c @@ -119,7 +119,7 @@ static void blob_seterror(pysqlite_Blob *self, int rc) { assert(self->connection != NULL); - _pysqlite_seterror(self->connection->state, self->connection->db); + set_error_from_db(self->connection->state, self->connection->db); } static PyObject * diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 16afd7eada113f..7997e5f4d986f3 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -188,7 +188,7 @@ connection_exec_stmt(pysqlite_Connection *self, const char *sql) Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - (void)_pysqlite_seterror(self->state, self->db); + set_error_from_db(self->state, self->db); return -1; } return 0; @@ -274,7 +274,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database, pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self)); if (rc != SQLITE_OK) { - _pysqlite_seterror(state, db); + set_error_from_db(state, db); goto error; } @@ -607,11 +607,11 @@ blobopen_impl(pysqlite_Connection *self, const char *table, const char *col, Py_END_ALLOW_THREADS if (rc == SQLITE_MISUSE) { - PyErr_Format(self->state->InterfaceError, sqlite3_errstr(rc)); + set_error_from_code(self->state, rc); return NULL; } else if (rc != SQLITE_OK) { - _pysqlite_seterror(self->state, self->db); + set_error_from_db(self->state, self->db); return NULL; } @@ -1139,6 +1139,20 @@ destructor_callback(void *ctx) } } +static int +check_num_params(pysqlite_Connection *self, const int n, const char *name) +{ + int limit = sqlite3_limit(self->db, SQLITE_LIMIT_FUNCTION_ARG, -1); + assert(limit >= 0); + if (n < -1 || n > limit) { + PyErr_Format(self->ProgrammingError, + "'%s' must be between -1 and %d, not %d", + name, limit, n); + return -1; + } + return 0; +} + /*[clinic input] _sqlite3.Connection.create_function as pysqlite_connection_create_function @@ -1167,6 +1181,9 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } + if (check_num_params(self, narg, "narg") < 0) { + return NULL; + } if (deterministic) { flags |= SQLITE_DETERMINISTIC; @@ -1307,10 +1324,12 @@ create_window_function_impl(pysqlite_Connection *self, PyTypeObject *cls, "SQLite 3.25.0 or higher"); return NULL; } - if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } + if (check_num_params(self, num_params, "num_params") < 0) { + return NULL; + } int flags = SQLITE_UTF8; int rc; @@ -1333,9 +1352,9 @@ create_window_function_impl(pysqlite_Connection *self, PyTypeObject *cls, } if (rc != SQLITE_OK) { - // Errors are not set on the database connection, so we cannot - // use _pysqlite_seterror(). - PyErr_SetString(self->ProgrammingError, sqlite3_errstr(rc)); + /* Errors are not set on the database connection; use result code + * instead. */ + set_error_from_code(self->state, rc); return NULL; } Py_RETURN_NONE; @@ -1367,6 +1386,9 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) { return NULL; } + if (check_num_params(self, n_arg, "n_arg") < 0) { + return NULL; + } callback_context *ctx = create_callback_context(cls, aggregate_class); if (ctx == NULL) { @@ -2090,7 +2112,7 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self, Py_END_ALLOW_THREADS if (bck_handle == NULL) { - _pysqlite_seterror(self->state, bck_conn); + set_error_from_db(self->state, bck_conn); return NULL; } @@ -2128,7 +2150,7 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self, Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->state, bck_conn); + set_error_from_db(self->state, bck_conn); return NULL; } @@ -2186,7 +2208,7 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self, if (callable != Py_None) { free_callback_context(ctx); } - _pysqlite_seterror(self->state, self->db); + set_error_from_db(self->state, self->db); return NULL; } @@ -2304,7 +2326,7 @@ deserialize_impl(pysqlite_Connection *self, Py_buffer *data, Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - (void)_pysqlite_seterror(self->state, self->db); + set_error_from_db(self->state, self->db); return NULL; } Py_RETURN_NONE; @@ -2499,7 +2521,7 @@ setconfig_impl(pysqlite_Connection *self, int op, int enable) int actual; int rc = sqlite3_db_config(self->db, op, enable, &actual); if (rc != SQLITE_OK) { - (void)_pysqlite_seterror(self->state, self->db); + set_error_from_db(self->state, self->db); return NULL; } if (enable != actual) { @@ -2534,7 +2556,7 @@ getconfig_impl(pysqlite_Connection *self, int op) int current; int rc = sqlite3_db_config(self->db, op, -1, ¤t); if (rc != SQLITE_OK) { - (void)_pysqlite_seterror(self->state, self->db); + set_error_from_db(self->state, self->db); return -1; } return current; diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 02d598040775b0..ad3587d88dd854 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -505,7 +505,7 @@ begin_transaction(pysqlite_Connection *self) Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - (void)_pysqlite_seterror(self->state, self->db); + set_error_from_db(self->state, self->db); return -1; } @@ -715,7 +715,7 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self, if (rc != SQLITE_OK) { PyObject *exc = PyErr_GetRaisedException(); sqlite3 *db = sqlite3_db_handle(self->st); - _pysqlite_seterror(state, db); + set_error_from_db(state, db); _PyErr_ChainExceptions1(exc); return; } @@ -764,7 +764,7 @@ bind_parameters(pysqlite_state *state, pysqlite_Statement *self, if (rc != SQLITE_OK) { PyObject *exc = PyErr_GetRaisedException(); sqlite3 *db = sqlite3_db_handle(self->st); - _pysqlite_seterror(state, db); + set_error_from_db(state, db); _PyErr_ChainExceptions1(exc); return; } @@ -896,7 +896,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation PyErr_Clear(); } } - _pysqlite_seterror(state, self->connection->db); + set_error_from_db(state, self->connection->db); goto error; } @@ -1087,7 +1087,7 @@ pysqlite_cursor_executescript_impl(pysqlite_Cursor *self, return Py_NewRef((PyObject *)self); error: - _pysqlite_seterror(self->connection->state, db); + set_error_from_db(self->connection->state, db); return NULL; } @@ -1122,8 +1122,7 @@ pysqlite_cursor_iternext(PyObject *op) Py_CLEAR(self->statement); } else if (rc != SQLITE_ROW) { - (void)_pysqlite_seterror(self->connection->state, - self->connection->db); + set_error_from_db(self->connection->state, self->connection->db); (void)stmt_reset(self->statement); Py_CLEAR(self->statement); Py_DECREF(row); diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index facced0dfbfafd..736e60fd778287 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -62,7 +62,7 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(state, db); + set_error_from_db(state, db); return NULL; } diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index b0622e66928f47..103248ff55aa0c 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -118,18 +118,31 @@ raise_exception(PyObject *type, int errcode, const char *errmsg) Py_XDECREF(exc); } +void +set_error_from_code(pysqlite_state *state, int code) +{ + PyObject *exc_class = get_exception_class(state, code); + if (exc_class == NULL) { + // No new exception need be raised. + return; + } + + const char *errmsg = sqlite3_errstr(code); + assert(errmsg != NULL); + raise_exception(exc_class, code, errmsg); +} + /** * Checks the SQLite error code and sets the appropriate DB-API exception. - * Returns the error code (0 means no error occurred). */ -int -_pysqlite_seterror(pysqlite_state *state, sqlite3 *db) +void +set_error_from_db(pysqlite_state *state, sqlite3 *db) { int errorcode = sqlite3_errcode(db); PyObject *exc_class = get_exception_class(state, errorcode); if (exc_class == NULL) { - // No new exception need be raised; just pass the error code - return errorcode; + // No new exception need be raised. + return; } /* Create and set the exception. */ @@ -137,7 +150,6 @@ _pysqlite_seterror(pysqlite_state *state, sqlite3 *db) // sqlite3_errmsg() always returns an UTF-8 encoded message const char *errmsg = sqlite3_errmsg(db); raise_exception(exc_class, extended_errcode, errmsg); - return extended_errcode; } #ifdef WORDS_BIGENDIAN diff --git a/Modules/_sqlite/util.h b/Modules/_sqlite/util.h index 68b1a8cb67ace3..f8e45baffaefe3 100644 --- a/Modules/_sqlite/util.h +++ b/Modules/_sqlite/util.h @@ -30,9 +30,9 @@ /** * Checks the SQLite error code and sets the appropriate DB-API exception. - * Returns the error code (0 means no error occurred). */ -int _pysqlite_seterror(pysqlite_state *state, sqlite3 *db); +void set_error_from_db(pysqlite_state *state, sqlite3 *db); +void set_error_from_code(pysqlite_state *state, int code); sqlite_int64 _pysqlite_long_as_int64(PyObject * value); diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 0d8d4843d33c1b..54f0e64d4819f1 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -1167,13 +1167,21 @@ compile_template(_sremodulestate *module_state, PatternObject *pattern, PyObject *template) { /* delegate to Python code */ - PyObject *func = module_state->compile_template; + PyObject *func = FT_ATOMIC_LOAD_PTR(module_state->compile_template); if (func == NULL) { func = PyImport_ImportModuleAttrString("re", "_compile_template"); if (func == NULL) { return NULL; } +#ifdef Py_GIL_DISABLED + PyObject *other_func = NULL; + if (!_Py_atomic_compare_exchange_ptr(&module_state->compile_template, &other_func, func)) { + Py_DECREF(func); + func = other_func; + } +#else Py_XSETREF(module_state->compile_template, func); +#endif } PyObject *args[] = {(PyObject *)pattern, template}; diff --git a/Modules/_testexternalinspection.c b/Modules/_testexternalinspection.c index 22074c81b7405f..77984460400c5d 100644 --- a/Modules/_testexternalinspection.c +++ b/Modules/_testexternalinspection.c @@ -410,6 +410,7 @@ get_py_runtime(pid_t pid) { uintptr_t address = search_map_for_section(pid, "PyRuntime", "libpython"); if (address == 0) { + PyErr_Clear(); address = search_map_for_section(pid, "PyRuntime", "python"); } return address; @@ -778,6 +779,7 @@ parse_coro_chain( } if (PyList_Append(render_to, name)) { + Py_DECREF(name); return -1; } Py_DECREF(name); @@ -955,7 +957,6 @@ parse_task( if (PyList_Append(render_to, result)) { goto err; } - Py_DECREF(result); PyObject *awaited_by = PyList_New(0); if (awaited_by == NULL) { @@ -973,6 +974,7 @@ parse_task( ) { goto err; } + Py_DECREF(result); return 0; @@ -1457,6 +1459,13 @@ get_stack_trace(PyObject* self, PyObject* args) } uintptr_t runtime_start_address = get_py_runtime(pid); + if (runtime_start_address == 0) { + if (!PyErr_Occurred()) { + PyErr_SetString( + PyExc_RuntimeError, "Failed to get .PyRuntime address"); + } + return NULL; + } struct _Py_DebugOffsets local_debug_offsets; if (read_offsets(pid, &runtime_start_address, &local_debug_offsets)) { @@ -1510,6 +1519,13 @@ get_async_stack_trace(PyObject* self, PyObject* args) } uintptr_t runtime_start_address = get_py_runtime(pid); + if (runtime_start_address == 0) { + if (!PyErr_Occurred()) { + PyErr_SetString( + PyExc_RuntimeError, "Failed to get .PyRuntime address"); + } + return NULL; + } struct _Py_DebugOffsets local_debug_offsets; if (read_offsets(pid, &runtime_start_address, &local_debug_offsets)) { @@ -1527,6 +1543,7 @@ get_async_stack_trace(PyObject* self, PyObject* args) } PyObject* calls = PyList_New(0); if (calls == NULL) { + Py_DECREF(result); return NULL; } if (PyList_SetItem(result, 0, calls)) { /* steals ref to 'calls' */ diff --git a/Modules/main.c b/Modules/main.c index f8a2438cdd0d93..0aebce0d3b7aa2 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -99,7 +99,7 @@ static int pymain_err_print(int *exitcode_p) { int exitcode; - if (_Py_HandleSystemExit(&exitcode)) { + if (_Py_HandleSystemExitAndKeyboardInterrupt(&exitcode)) { *exitcode_p = exitcode; return 1; } @@ -292,11 +292,7 @@ pymain_start_pyrepl_no_main(void) goto done; } if (!PyDict_SetItemString(kwargs, "pythonstartup", _PyLong_GetOne())) { - _PyRuntime.signals.unhandled_keyboard_interrupt = 0; console_result = PyObject_Call(console, empty_tuple, kwargs); - if (!console_result && PyErr_Occurred() == PyExc_KeyboardInterrupt) { - _PyRuntime.signals.unhandled_keyboard_interrupt = 1; - } if (console_result == NULL) { res = pymain_exit_err_print(); } @@ -338,11 +334,7 @@ pymain_run_module(const wchar_t *modname, int set_argv0) Py_DECREF(module); return pymain_exit_err_print(); } - _PyRuntime.signals.unhandled_keyboard_interrupt = 0; result = PyObject_Call(runmodule, runargs, NULL); - if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) { - _PyRuntime.signals.unhandled_keyboard_interrupt = 1; - } Py_DECREF(runmodule); Py_DECREF(module); Py_DECREF(runargs); @@ -763,6 +755,8 @@ Py_RunMain(void) { int exitcode = 0; + _PyRuntime.signals.unhandled_keyboard_interrupt = 0; + pymain_run_python(&exitcode); if (Py_FinalizeEx() < 0) { diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h index 5c6a425b0f803a..99651f3c64bc5a 100644 --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -705,10 +705,9 @@ PyDoc_STRVAR(unicode_isprintable__doc__, "isprintable($self, /)\n" "--\n" "\n" -"Return True if the string is printable, False otherwise.\n" +"Return True if all characters in the string are printable, False otherwise.\n" "\n" -"A string is printable if all of its characters are considered printable in\n" -"repr() or if it is empty."); +"A character is printable if repr() may use it in its output."); #define UNICODE_ISPRINTABLE_METHODDEF \ {"isprintable", (PyCFunction)unicode_isprintable, METH_NOARGS, unicode_isprintable__doc__}, @@ -1895,4 +1894,4 @@ unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=4d1cecd6d08498a4 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=db37497bf38a2c17 input=a9049054013a1b77]*/ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index d979cd72b48e69..900d001d4dd56a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1590,7 +1590,7 @@ _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t h *value_addr = PyStackRef_NULL; return DKIX_EMPTY; } - if (_Py_IsImmortal(value) || _PyObject_HasDeferredRefcount(value)) { + if (_PyObject_HasDeferredRefcount(value)) { *value_addr = (_PyStackRef){ .bits = (uintptr_t)value | Py_TAG_DEFERRED }; return ix; } diff --git a/Objects/object.c b/Objects/object.c index f3c7fa6d906ad6..16aedac916bf34 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1612,7 +1612,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) else { PyObject **dictptr = _PyObject_ComputedDictPointer(obj); if (dictptr != NULL) { - dict = *dictptr; + dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*dictptr); } else { dict = NULL; @@ -2538,6 +2538,7 @@ _Py_SetImmortalUntracked(PyObject *op) op->ob_tid = _Py_UNOWNED_TID; op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL; op->ob_ref_shared = 0; + _Py_atomic_or_uint8(&op->ob_gc_bits, _PyGC_BITS_DEFERRED); #else op->ob_refcnt = _Py_IMMORTAL_INITIAL_REFCNT; #endif @@ -2994,6 +2995,11 @@ _Py_Dealloc(PyObject *op) destructor dealloc = type->tp_dealloc; #ifdef Py_DEBUG PyThreadState *tstate = _PyThreadState_GET(); +#ifndef Py_GIL_DISABLED + /* This assertion doesn't hold for the free-threading build, as + * PyStackRef_CLOSE_SPECIALIZED is not implemented */ + assert(tstate->current_frame == NULL || tstate->current_frame->stackpointer != NULL); +#endif PyObject *old_exc = tstate != NULL ? tstate->current_exception : NULL; // Keep the old exception type alive to prevent undefined behavior // on (tstate->curexc_type != old_exc_type) below diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 5688049b024696..6341251007aa8e 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -3297,12 +3297,12 @@ static bool _collect_alloc_stats( static void py_mimalloc_print_stats(FILE *out) { - fprintf(out, "Small block threshold = %zd, in %u size classes.\n", - MI_SMALL_OBJ_SIZE_MAX, MI_BIN_HUGE); - fprintf(out, "Medium block threshold = %zd\n", - MI_MEDIUM_OBJ_SIZE_MAX); - fprintf(out, "Large object max size = %zd\n", - MI_LARGE_OBJ_SIZE_MAX); + fprintf(out, "Small block threshold = %zu, in %u size classes.\n", + (size_t)MI_SMALL_OBJ_SIZE_MAX, MI_BIN_HUGE); + fprintf(out, "Medium block threshold = %zu\n", + (size_t)MI_MEDIUM_OBJ_SIZE_MAX); + fprintf(out, "Large object max size = %zu\n", + (size_t)MI_LARGE_OBJ_SIZE_MAX); mi_heap_t *heap = mi_heap_get_default(); struct _alloc_stats stats; diff --git a/Objects/setobject.c b/Objects/setobject.c index 26ab352ca6d989..1978ae2b165d18 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -535,9 +535,18 @@ set_repr_lock_held(PySetObject *so) return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name); } - keys = PySequence_List((PyObject *)so); - if (keys == NULL) + // gh-129967: avoid PySequence_List because it might re-lock the object + // lock or the GIL and allow something to clear the set from underneath us. + keys = PyList_New(so->used); + if (keys == NULL) { goto done; + } + + Py_ssize_t pos = 0, idx = 0; + setentry *entry; + while (set_next(so, &pos, &entry)) { + PyList_SET_ITEM(keys, idx++, Py_NewRef(entry->key)); + } /* repr(keys)[1:-1] */ listrepr = PyObject_Repr(keys); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f3238da8a642e4..818a00708b5d3d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1010,7 +1010,7 @@ set_version_unlocked(PyTypeObject *tp, unsigned int version) _Py_atomic_add_uint16(&tp->tp_versions_used, 1); } #endif - FT_ATOMIC_STORE_UINT32_RELAXED(tp->tp_version_tag, version); + FT_ATOMIC_STORE_UINT_RELAXED(tp->tp_version_tag, version); #ifndef Py_GIL_DISABLED if (version != 0) { PyTypeObject **slot = @@ -1039,7 +1039,8 @@ type_modified_unlocked(PyTypeObject *type) We don't assign new version tags eagerly, but only as needed. */ - if (FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag) == 0) { + ASSERT_TYPE_LOCK_HELD(); + if (type->tp_version_tag == 0) { return; } // Cannot modify static builtin types. @@ -1085,7 +1086,8 @@ type_modified_unlocked(PyTypeObject *type) if (PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { // This field *must* be invalidated if the type is modified (see the // comment on struct _specialization_cache): - ((PyHeapTypeObject *)type)->_spec_cache.getitem = NULL; + FT_ATOMIC_STORE_PTR_RELAXED( + ((PyHeapTypeObject *)type)->_spec_cache.getitem, NULL); } } @@ -1093,7 +1095,7 @@ void PyType_Modified(PyTypeObject *type) { // Quick check without the lock held - if (type->tp_version_tag == 0) { + if (FT_ATOMIC_LOAD_UINT_RELAXED(type->tp_version_tag) == 0) { return; } @@ -1166,7 +1168,8 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { if (PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { // This field *must* be invalidated if the type is modified (see the // comment on struct _specialization_cache): - ((PyHeapTypeObject *)type)->_spec_cache.getitem = NULL; + FT_ATOMIC_STORE_PTR_RELAXED( + ((PyHeapTypeObject *)type)->_spec_cache.getitem, NULL); } } @@ -2248,7 +2251,9 @@ _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems) if (PyType_IS_GC(type)) { _PyObject_GC_Link(obj); } - memset(obj, '\0', size); + // Zero out the object after the PyObject header. The header fields are + // initialized by _PyObject_Init[Var](). + memset((char *)obj + sizeof(PyObject), 0, size - sizeof(PyObject)); if (type->tp_itemsize == 0) { _PyObject_Init(obj, type); diff --git a/Objects/unicodectype.c b/Objects/unicodectype.c index aa5c5b2a4ad2eb..7cd0dca3d13545 100644 --- a/Objects/unicodectype.c +++ b/Objects/unicodectype.c @@ -142,18 +142,10 @@ int _PyUnicode_IsNumeric(Py_UCS4 ch) return (ctype->flags & NUMERIC_MASK) != 0; } -/* Returns 1 for Unicode characters to be hex-escaped when repr()ed, - 0 otherwise. - All characters except those characters defined in the Unicode character - database as following categories are considered printable. - * Cc (Other, Control) - * Cf (Other, Format) - * Cs (Other, Surrogate) - * Co (Other, Private Use) - * Cn (Other, Not Assigned) - * Zl Separator, Line ('\u2028', LINE SEPARATOR) - * Zp Separator, Paragraph ('\u2029', PARAGRAPH SEPARATOR) - * Zs (Separator, Space) other than ASCII space('\x20'). +/* Returns 1 for Unicode characters that repr() may use in its output, + and 0 for characters to be hex-escaped. + + See documentation of `str.isprintable` for details. */ int _PyUnicode_IsPrintable(Py_UCS4 ch) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 75967d69ed374d..371c358a4950c2 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -12452,15 +12452,14 @@ unicode_isidentifier_impl(PyObject *self) /*[clinic input] str.isprintable as unicode_isprintable -Return True if the string is printable, False otherwise. +Return True if all characters in the string are printable, False otherwise. -A string is printable if all of its characters are considered printable in -repr() or if it is empty. +A character is printable if repr() may use it in its output. [clinic start generated code]*/ static PyObject * unicode_isprintable_impl(PyObject *self) -/*[clinic end generated code: output=3ab9626cd32dd1a0 input=98a0e1c2c1813209]*/ +/*[clinic end generated code: output=3ab9626cd32dd1a0 input=4e56bcc6b06ca18c]*/ { Py_ssize_t i, length; int kind; diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index dbdb6b743bea37..17abfa85201a90 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -53,6 +53,7 @@ $(PySourcePath)Include;$(PySourcePath)Include\internal;$(PySourcePath)Include\internal\mimalloc;$(GeneratedPyConfigDir);$(PySourcePath)PC;%(AdditionalIncludeDirectories) WIN32;$(_Py3NamePreprocessorDefinition);$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PyStatsPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions) + _Py_USING_PGO=1;%(PreprocessorDefinitions) MaxSpeed true diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 2fe8d11badcbac..52d63401a6e6b5 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -1694,3 +1694,18 @@ _PyPegen_concatenate_strings(Parser *p, asdl_expr_seq *strings, assert(current_pos == n_elements); return _PyAST_JoinedStr(values, lineno, col_offset, end_lineno, end_col_offset, p->arena); } + +stmt_ty +_PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq * names, int level, + int lineno, int col_offset, int end_lineno, int end_col_offset, + PyArena *arena) { + if (level == 0 && PyUnicode_CompareWithASCIIString(module, "__future__") == 0) { + for (Py_ssize_t i = 0; i < asdl_seq_LEN(names); i++) { + alias_ty alias = asdl_seq_GET(names, i); + if (PyUnicode_CompareWithASCIIString(alias->name, "barry_as_FLUFL") == 0) { + p->flags |= PyPARSE_BARRY_AS_BDFL; + } + } + } + return _PyAST_ImportFrom(module, names, level, lineno, col_offset, end_lineno, end_col_offset, arena); +} diff --git a/Parser/parser.c b/Parser/parser.c index 9ff58ab7e7bfd5..71606d7023a44c 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -447,13 +447,13 @@ static char *soft_keywords[] = { #define _tmp_108_type 1360 #define _tmp_109_type 1361 #define _tmp_110_type 1362 -#define _tmp_111_type 1363 +#define _loop1_111_type 1363 #define _tmp_112_type 1364 #define _tmp_113_type 1365 #define _tmp_114_type 1366 -#define _loop0_115_type 1367 +#define _tmp_115_type 1367 #define _loop0_116_type 1368 -#define _tmp_117_type 1369 +#define _loop0_117_type 1369 #define _tmp_118_type 1370 #define _tmp_119_type 1371 #define _tmp_120_type 1372 @@ -462,21 +462,21 @@ static char *soft_keywords[] = { #define _tmp_123_type 1375 #define _tmp_124_type 1376 #define _tmp_125_type 1377 -#define _loop0_126_type 1378 -#define _gather_127_type 1379 -#define _tmp_128_type 1380 +#define _tmp_126_type 1378 +#define _loop0_127_type 1379 +#define _gather_128_type 1380 #define _tmp_129_type 1381 #define _tmp_130_type 1382 #define _tmp_131_type 1383 -#define _loop0_132_type 1384 -#define _gather_133_type 1385 -#define _loop0_134_type 1386 -#define _gather_135_type 1387 -#define _loop0_136_type 1388 -#define _gather_137_type 1389 -#define _tmp_138_type 1390 -#define _loop0_139_type 1391 -#define _tmp_140_type 1392 +#define _tmp_132_type 1384 +#define _loop0_133_type 1385 +#define _gather_134_type 1386 +#define _loop0_135_type 1387 +#define _gather_136_type 1388 +#define _loop0_137_type 1389 +#define _gather_138_type 1390 +#define _tmp_139_type 1391 +#define _loop0_140_type 1392 #define _tmp_141_type 1393 #define _tmp_142_type 1394 #define _tmp_143_type 1395 @@ -501,11 +501,13 @@ static char *soft_keywords[] = { #define _tmp_162_type 1414 #define _tmp_163_type 1415 #define _tmp_164_type 1416 -#define _loop0_165_type 1417 +#define _tmp_165_type 1417 #define _tmp_166_type 1418 -#define _tmp_167_type 1419 +#define _loop0_167_type 1419 #define _tmp_168_type 1420 #define _tmp_169_type 1421 +#define _tmp_170_type 1422 +#define _tmp_171_type 1423 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -870,13 +872,13 @@ static void *_tmp_107_rule(Parser *p); static void *_tmp_108_rule(Parser *p); static void *_tmp_109_rule(Parser *p); static void *_tmp_110_rule(Parser *p); -static void *_tmp_111_rule(Parser *p); +static asdl_seq *_loop1_111_rule(Parser *p); static void *_tmp_112_rule(Parser *p); static void *_tmp_113_rule(Parser *p); static void *_tmp_114_rule(Parser *p); -static asdl_seq *_loop0_115_rule(Parser *p); +static void *_tmp_115_rule(Parser *p); static asdl_seq *_loop0_116_rule(Parser *p); -static void *_tmp_117_rule(Parser *p); +static asdl_seq *_loop0_117_rule(Parser *p); static void *_tmp_118_rule(Parser *p); static void *_tmp_119_rule(Parser *p); static void *_tmp_120_rule(Parser *p); @@ -885,21 +887,21 @@ static void *_tmp_122_rule(Parser *p); static void *_tmp_123_rule(Parser *p); static void *_tmp_124_rule(Parser *p); static void *_tmp_125_rule(Parser *p); -static asdl_seq *_loop0_126_rule(Parser *p); -static asdl_seq *_gather_127_rule(Parser *p); -static void *_tmp_128_rule(Parser *p); +static void *_tmp_126_rule(Parser *p); +static asdl_seq *_loop0_127_rule(Parser *p); +static asdl_seq *_gather_128_rule(Parser *p); static void *_tmp_129_rule(Parser *p); static void *_tmp_130_rule(Parser *p); static void *_tmp_131_rule(Parser *p); -static asdl_seq *_loop0_132_rule(Parser *p); -static asdl_seq *_gather_133_rule(Parser *p); -static asdl_seq *_loop0_134_rule(Parser *p); -static asdl_seq *_gather_135_rule(Parser *p); -static asdl_seq *_loop0_136_rule(Parser *p); -static asdl_seq *_gather_137_rule(Parser *p); -static void *_tmp_138_rule(Parser *p); -static asdl_seq *_loop0_139_rule(Parser *p); -static void *_tmp_140_rule(Parser *p); +static void *_tmp_132_rule(Parser *p); +static asdl_seq *_loop0_133_rule(Parser *p); +static asdl_seq *_gather_134_rule(Parser *p); +static asdl_seq *_loop0_135_rule(Parser *p); +static asdl_seq *_gather_136_rule(Parser *p); +static asdl_seq *_loop0_137_rule(Parser *p); +static asdl_seq *_gather_138_rule(Parser *p); +static void *_tmp_139_rule(Parser *p); +static asdl_seq *_loop0_140_rule(Parser *p); static void *_tmp_141_rule(Parser *p); static void *_tmp_142_rule(Parser *p); static void *_tmp_143_rule(Parser *p); @@ -924,11 +926,13 @@ static void *_tmp_161_rule(Parser *p); static void *_tmp_162_rule(Parser *p); static void *_tmp_163_rule(Parser *p); static void *_tmp_164_rule(Parser *p); -static asdl_seq *_loop0_165_rule(Parser *p); +static void *_tmp_165_rule(Parser *p); static void *_tmp_166_rule(Parser *p); -static void *_tmp_167_rule(Parser *p); +static asdl_seq *_loop0_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); // file: statements? $ @@ -3356,7 +3360,7 @@ import_from_rule(Parser *p) UNUSED(_end_lineno); // Only used by EXTRA macro int _end_col_offset = _token->end_col_offset; UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _PyAST_ImportFrom ( b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); + _res = _PyPegen_checked_future_import ( p , b -> v . Name . id , c , _PyPegen_seq_count_dots ( a ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -20323,6 +20327,7 @@ invalid_type_param_rule(Parser *p) } // invalid_expression: +// | STRING ((!STRING expression_without_invalid))+ STRING // | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid // | disjunction 'if' disjunction !('else' | ':') // | 'lambda' lambda_params? ':' &FSTRING_MIDDLE @@ -20338,6 +20343,36 @@ invalid_expression_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; + { // STRING ((!STRING expression_without_invalid))+ STRING + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING ((!STRING expression_without_invalid))+ STRING")); + asdl_seq * a; + expr_ty string_var; + expr_ty string_var_1; + if ( + (string_var = _PyPegen_string_token(p)) // STRING + && + (a = _loop1_111_rule(p)) // ((!STRING expression_without_invalid))+ + && + (string_var_1 = _PyPegen_string_token(p)) // STRING + ) + { + D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING ((!STRING expression_without_invalid))+ STRING")); + _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( PyPegen_first_item ( a , expr_ty ) , PyPegen_last_item ( a , expr_ty ) , "invalid syntax. Is this intended to be part of the string?" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "STRING ((!STRING expression_without_invalid))+ STRING")); + } { // !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid if (p->error_indicator) { p->level--; @@ -20347,7 +20382,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_111_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_112_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -20383,7 +20418,7 @@ invalid_expression_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_112_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_113_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -20504,7 +20539,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_113_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_114_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -20530,7 +20565,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_114_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_115_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -20538,7 +20573,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_113_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_114_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 !('=' | ':=')")); @@ -20618,7 +20653,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_115_var; + asdl_seq * _loop0_116_var; expr_ty a; expr_ty expression_var; if ( @@ -20626,7 +20661,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_115_var = _loop0_115_rule(p)) // star_named_expressions* + (_loop0_116_var = _loop0_116_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20683,10 +20718,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_116_var; + asdl_seq * _loop0_117_var; expr_ty a; if ( - (_loop0_116_var = _loop0_116_rule(p)) // ((star_targets '='))* + (_loop0_117_var = _loop0_117_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -20713,10 +20748,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_116_var; + asdl_seq * _loop0_117_var; expr_ty a; if ( - (_loop0_116_var = _loop0_116_rule(p)) // ((star_targets '='))* + (_loop0_117_var = _loop0_117_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -20972,11 +21007,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_117_var; + void *_tmp_118_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_117_var = _tmp_117_rule(p)) // '[' | '(' | '{' + (_tmp_118_var = _tmp_118_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -21003,12 +21038,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_118_var; + void *_tmp_119_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_118_var = _tmp_118_rule(p)) // '[' | '{' + (_tmp_119_var = _tmp_119_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21038,12 +21073,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_118_var; + void *_tmp_119_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_118_var = _tmp_118_rule(p)) // '[' | '{' + (_tmp_119_var = _tmp_119_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21179,10 +21214,10 @@ 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* '/'")); asdl_seq * _loop0_32_var; - void *_tmp_119_var; + void *_tmp_120_var; Token * a; if ( - (_tmp_119_var = _tmp_119_rule(p)) // slash_no_default | slash_with_default + (_tmp_120_var = _tmp_120_rule(p)) // slash_no_default | slash_with_default && (_loop0_32_var = _loop0_32_rule(p)) // param_maybe_default* && @@ -21284,16 +21319,16 @@ invalid_parameters_rule(Parser *p) asdl_seq * _loop0_32_var_1; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_120_var; + void *_tmp_121_var; Token * a; if ( - (_opt_var = _tmp_119_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] + (_opt_var = _tmp_120_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] && (_loop0_32_var = _loop0_32_rule(p)) // param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_120_var = _tmp_120_rule(p)) // ',' | param_no_default + (_tmp_121_var = _tmp_121_rule(p)) // ',' | param_no_default && (_loop0_32_var_1 = _loop0_32_rule(p)) // param_maybe_default* && @@ -21372,7 +21407,7 @@ invalid_default_rule(Parser *p) if ( (a = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_121_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_122_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' &(')' | ',')")); @@ -21417,12 +21452,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_122_var; + void *_tmp_123_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_122_var = _tmp_122_rule(p)) // ')' | ',' (')' | '**') + (_tmp_123_var = _tmp_123_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -21506,19 +21541,19 @@ 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_32_var; - void *_tmp_123_var; - void *_tmp_123_var_1; + void *_tmp_124_var; + void *_tmp_124_var_1; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_123_var = _tmp_123_rule(p)) // param_no_default | ',' + (_tmp_124_var = _tmp_124_rule(p)) // param_no_default | ',' && (_loop0_32_var = _loop0_32_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_123_var_1 = _tmp_123_rule(p)) // param_no_default | ',' + (_tmp_124_var_1 = _tmp_124_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 | ',')")); @@ -21633,7 +21668,7 @@ invalid_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_124_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_125_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' ('*' | '**' | '/')")); @@ -21770,10 +21805,10 @@ 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* '/'")); asdl_seq * _loop0_75_var; - void *_tmp_125_var; + void *_tmp_126_var; Token * a; if ( - (_tmp_125_var = _tmp_125_rule(p)) // lambda_slash_no_default | lambda_slash_with_default + (_tmp_126_var = _tmp_126_rule(p)) // lambda_slash_no_default | lambda_slash_with_default && (_loop0_75_var = _loop0_75_rule(p)) // lambda_param_maybe_default* && @@ -21833,7 +21868,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_param_no_default* '(' ','.lambda_param+ ','? ')'")); - asdl_seq * _gather_127_var; + asdl_seq * _gather_128_var; asdl_seq * _loop0_71_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -21844,7 +21879,7 @@ invalid_lambda_parameters_rule(Parser *p) && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_127_var = _gather_127_rule(p)) // ','.lambda_param+ + (_gather_128_var = _gather_128_rule(p)) // ','.lambda_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -21875,16 +21910,16 @@ invalid_lambda_parameters_rule(Parser *p) asdl_seq * _loop0_75_var_1; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_128_var; + void *_tmp_129_var; Token * a; if ( - (_opt_var = _tmp_125_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] + (_opt_var = _tmp_126_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] && (_loop0_75_var = _loop0_75_rule(p)) // lambda_param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_128_var = _tmp_128_rule(p)) // ',' | lambda_param_no_default + (_tmp_129_var = _tmp_129_rule(p)) // ',' | lambda_param_no_default && (_loop0_75_var_1 = _loop0_75_rule(p)) // lambda_param_maybe_default* && @@ -22027,11 +22062,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_129_var; + void *_tmp_130_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_129_var = _tmp_129_rule(p)) // ':' | ',' (':' | '**') + (_tmp_130_var = _tmp_130_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -22085,19 +22120,19 @@ 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_75_var; - void *_tmp_130_var; - void *_tmp_130_var_1; + void *_tmp_131_var; + void *_tmp_131_var_1; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_130_var = _tmp_130_rule(p)) // lambda_param_no_default | ',' + (_tmp_131_var = _tmp_131_rule(p)) // lambda_param_no_default | ',' && (_loop0_75_var = _loop0_75_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_130_var_1 = _tmp_130_rule(p)) // lambda_param_no_default | ',' + (_tmp_131_var_1 = _tmp_131_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 | ',')")); @@ -22215,7 +22250,7 @@ invalid_lambda_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_124_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_125_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' ('*' | '**' | '/')")); @@ -22365,13 +22400,13 @@ invalid_for_if_clause_rule(Parser *p) Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_131_var; + void *_tmp_132_var; if ( (_opt_var = _PyPegen_expect_token(p, 682), !p->error_indicator) // 'async'? && (_keyword = _PyPegen_expect_token(p, 678)) // token='for' && - (_tmp_131_var = _tmp_131_rule(p)) // bitwise_or ((',' bitwise_or))* ','? + (_tmp_132_var = _tmp_132_rule(p)) // bitwise_or ((',' bitwise_or))* ','? && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 679) // token='in' ) @@ -22546,14 +22581,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_133_var; + asdl_seq * _gather_134_var; Token * _keyword; Token * a; expr_ty dotted_name_var; if ( (a = _PyPegen_expect_token(p, 622)) // token='import' && - (_gather_133_var = _gather_133_rule(p)) // ','.dotted_name+ + (_gather_134_var = _gather_134_rule(p)) // ','.dotted_name+ && (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && @@ -22700,7 +22735,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_135_var; + asdl_seq * _gather_136_var; Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22710,7 +22745,7 @@ invalid_with_stmt_rule(Parser *p) && (_keyword = _PyPegen_expect_token(p, 633)) // token='with' && - (_gather_135_var = _gather_135_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_136_var = _gather_136_rule(p)) // ','.(expression ['as' star_target])+ && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -22734,7 +22769,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_137_var; + asdl_seq * _gather_138_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -22750,7 +22785,7 @@ invalid_with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_137_var = _gather_137_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_138_var = _gather_138_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22799,7 +22834,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_135_var; + asdl_seq * _gather_136_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22810,7 +22845,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (a = _PyPegen_expect_token(p, 633)) // token='with' && - (_gather_135_var = _gather_135_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_136_var = _gather_136_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -22838,7 +22873,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_137_var; + asdl_seq * _gather_138_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -22855,7 +22890,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_137_var = _gather_137_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_138_var = _gather_138_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22952,7 +22987,7 @@ invalid_try_stmt_rule(Parser *p) && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_138_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_139_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -22977,7 +23012,7 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_139_var; + asdl_seq * _loop0_140_var; asdl_seq * _loop1_37_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22989,7 +23024,7 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_139_var = _loop0_139_rule(p)) // block* + (_loop0_140_var = _loop0_140_rule(p)) // block* && (_loop1_37_var = _loop1_37_rule(p)) // except_block+ && @@ -23026,7 +23061,7 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_139_var; + asdl_seq * _loop0_140_var; asdl_seq * _loop1_38_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -23036,13 +23071,13 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_139_var = _loop0_139_rule(p)) // block* + (_loop0_140_var = _loop0_140_rule(p)) // block* && (_loop1_38_var = _loop1_38_rule(p)) // except_star_block+ && (a = _PyPegen_expect_token(p, 663)) // token='except' && - (_opt_var = _tmp_140_rule(p), !p->error_indicator) // [expression ['as' NAME]] + (_opt_var = _tmp_141_rule(p), !p->error_indicator) // [expression ['as' NAME]] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23327,14 +23362,14 @@ invalid_except_star_stmt_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_except_star_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); Token * _literal; - void *_tmp_141_var; + void *_tmp_142_var; Token * a; if ( (a = _PyPegen_expect_token(p, 663)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_141_var = _tmp_141_rule(p)) // NEWLINE | ':' + (_tmp_142_var = _tmp_142_rule(p)) // NEWLINE | ':' ) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); @@ -23931,7 +23966,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_142_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_143_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -24695,7 +24730,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_143_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_144_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -24805,7 +24840,7 @@ invalid_kvpair_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_143_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_144_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -25093,7 +25128,7 @@ invalid_replacement_field_rule(Parser *p) && (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_144_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_145_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); @@ -25125,7 +25160,7 @@ invalid_replacement_field_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_145_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_146_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); @@ -25189,9 +25224,9 @@ invalid_replacement_field_rule(Parser *p) && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_146_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_147_rule(p), !p->error_indicator) // ['!' NAME] && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_147_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_148_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); @@ -25228,7 +25263,7 @@ invalid_replacement_field_rule(Parser *p) && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_146_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_147_rule(p), !p->error_indicator) // ['!' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -25269,7 +25304,7 @@ invalid_replacement_field_rule(Parser *p) && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_146_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_147_rule(p), !p->error_indicator) // ['!' NAME] && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) @@ -25316,7 +25351,7 @@ invalid_conversion_character_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_147_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_148_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); @@ -25383,14 +25418,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_148_var; + void *_tmp_149_var; Token * a; expr_ty b; expr_ty sum_var; if ( (sum_var = sum_rule(p)) // sum && - (_tmp_148_var = _tmp_148_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' + (_tmp_149_var = _tmp_149_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' && (a = _PyPegen_expect_token(p, 687)) // token='not' && @@ -25435,11 +25470,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_149_var; + void *_tmp_150_var; Token * a; expr_ty b; if ( - (_tmp_149_var = _tmp_149_rule(p)) // '+' | '-' | '~' + (_tmp_150_var = _tmp_150_rule(p)) // '+' | '-' | '~' && (a = _PyPegen_expect_token(p, 687)) // token='not' && @@ -26213,12 +26248,12 @@ _loop1_12_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_150_var; + void *_tmp_151_var; while ( - (_tmp_150_var = _tmp_150_rule(p)) // star_targets '=' + (_tmp_151_var = _tmp_151_rule(p)) // star_targets '=' ) { - _res = _tmp_150_var; + _res = _tmp_151_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26551,12 +26586,12 @@ _loop0_18_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_151_var; + void *_tmp_152_var; while ( - (_tmp_151_var = _tmp_151_rule(p)) // '.' | '...' + (_tmp_152_var = _tmp_152_rule(p)) // '.' | '...' ) { - _res = _tmp_151_var; + _res = _tmp_152_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26618,12 +26653,12 @@ _loop1_19_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_151_var; + void *_tmp_152_var; while ( - (_tmp_151_var = _tmp_151_rule(p)) // '.' | '...' + (_tmp_152_var = _tmp_152_rule(p)) // '.' | '...' ) { - _res = _tmp_151_var; + _res = _tmp_152_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26970,12 +27005,12 @@ _loop1_25_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_152_var; + void *_tmp_153_var; while ( - (_tmp_152_var = _tmp_152_rule(p)) // '@' named_expression NEWLINE + (_tmp_153_var = _tmp_153_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_152_var; + _res = _tmp_153_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28927,12 +28962,12 @@ _loop1_56_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_153_var; + void *_tmp_154_var; while ( - (_tmp_153_var = _tmp_153_rule(p)) // ',' star_expression + (_tmp_154_var = _tmp_154_rule(p)) // ',' star_expression ) { - _res = _tmp_153_var; + _res = _tmp_154_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29116,12 +29151,12 @@ _loop1_59_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_154_var; + void *_tmp_155_var; while ( - (_tmp_154_var = _tmp_154_rule(p)) // 'or' conjunction + (_tmp_155_var = _tmp_155_rule(p)) // 'or' conjunction ) { - _res = _tmp_154_var; + _res = _tmp_155_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29188,12 +29223,12 @@ _loop1_60_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_155_var; + void *_tmp_156_var; while ( - (_tmp_155_var = _tmp_155_rule(p)) // 'and' inversion + (_tmp_156_var = _tmp_156_rule(p)) // 'and' inversion ) { - _res = _tmp_155_var; + _res = _tmp_156_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29380,7 +29415,7 @@ _loop0_63_rule(Parser *p) while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_156_rule(p)) // slice | starred_expression + (elem = _tmp_157_rule(p)) // slice | starred_expression ) { _res = elem; @@ -29445,7 +29480,7 @@ _gather_64_rule(Parser *p) void *elem; asdl_seq * seq; if ( - (elem = _tmp_156_rule(p)) // slice | starred_expression + (elem = _tmp_157_rule(p)) // slice | starred_expression && (seq = _loop0_63_rule(p)) // _loop0_63 ) @@ -30431,12 +30466,12 @@ _loop1_79_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); - void *_tmp_157_var; + void *_tmp_158_var; while ( - (_tmp_157_var = _tmp_157_rule(p)) // fstring | string + (_tmp_158_var = _tmp_158_rule(p)) // fstring | string ) { - _res = _tmp_157_var; + _res = _tmp_158_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30741,12 +30776,12 @@ _loop0_84_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_158_var; + void *_tmp_159_var; while ( - (_tmp_158_var = _tmp_158_rule(p)) // 'if' disjunction + (_tmp_159_var = _tmp_159_rule(p)) // 'if' disjunction ) { - _res = _tmp_158_var; + _res = _tmp_159_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30872,7 +30907,7 @@ _loop0_86_rule(Parser *p) while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_159_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_160_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -30938,7 +30973,7 @@ _gather_87_rule(Parser *p) void *elem; asdl_seq * seq; if ( - (elem = _tmp_159_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_160_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && (seq = _loop0_86_rule(p)) // _loop0_86 ) @@ -31265,12 +31300,12 @@ _loop0_93_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_160_var; + void *_tmp_161_var; while ( - (_tmp_160_var = _tmp_160_rule(p)) // ',' star_target + (_tmp_161_var = _tmp_161_rule(p)) // ',' star_target ) { - _res = _tmp_160_var; + _res = _tmp_161_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31449,12 +31484,12 @@ _loop1_96_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_160_var; + void *_tmp_161_var; while ( - (_tmp_160_var = _tmp_160_rule(p)) // ',' star_target + (_tmp_161_var = _tmp_161_rule(p)) // ',' star_target ) { - _res = _tmp_160_var; + _res = _tmp_161_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31829,13 +31864,13 @@ _tmp_103_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _tmp_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); - void *_tmp_161_var; + void *_tmp_162_var; if ( - (_tmp_161_var = _tmp_161_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs + (_tmp_162_var = _tmp_162_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs ) { D(fprintf(stderr, "%*c+ _tmp_103[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); - _res = _tmp_161_var; + _res = _tmp_162_var; goto done; } p->mark = _mark; @@ -31900,7 +31935,7 @@ _loop0_104_rule(Parser *p) while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_162_rule(p)) // starred_expression !'=' + (elem = _tmp_163_rule(p)) // starred_expression !'=' ) { _res = elem; @@ -31965,7 +32000,7 @@ _gather_105_rule(Parser *p) void *elem; asdl_seq * seq; if ( - (elem = _tmp_162_rule(p)) // starred_expression !'=' + (elem = _tmp_163_rule(p)) // starred_expression !'=' && (seq = _loop0_104_rule(p)) // _loop0_104 ) @@ -32259,9 +32294,81 @@ _tmp_110_rule(Parser *p) return _res; } -// _tmp_111: NAME STRING | SOFT_KEYWORD +// _loop1_111: (!STRING expression_without_invalid) +static asdl_seq * +_loop1_111_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; + { // (!STRING expression_without_invalid) + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop1_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(!STRING expression_without_invalid)")); + void *_tmp_164_var; + while ( + (_tmp_164_var = _tmp_164_rule(p)) // !STRING expression_without_invalid + ) + { + _res = _tmp_164_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 _loop1_111[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(!STRING expression_without_invalid)")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; + } + 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 (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _tmp_112: NAME STRING | SOFT_KEYWORD static void * -_tmp_111_rule(Parser *p) +_tmp_112_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32277,7 +32384,7 @@ _tmp_111_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -32286,12 +32393,12 @@ _tmp_111_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_112[%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_111[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } { // SOFT_KEYWORD @@ -32299,18 +32406,18 @@ _tmp_111_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_112[%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_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_112[%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_111[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; @@ -32319,9 +32426,9 @@ _tmp_111_rule(Parser *p) return _res; } -// _tmp_112: 'else' | ':' +// _tmp_113: 'else' | ':' static void * -_tmp_112_rule(Parser *p) +_tmp_113_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32337,18 +32444,18 @@ _tmp_112_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 671)) // token='else' ) { - D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } { // ':' @@ -32356,18 +32463,18 @@ _tmp_112_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -32376,9 +32483,9 @@ _tmp_112_rule(Parser *p) return _res; } -// _tmp_113: '=' | ':=' +// _tmp_114: '=' | ':=' static void * -_tmp_113_rule(Parser *p) +_tmp_114_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32394,18 +32501,18 @@ _tmp_113_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -32413,18 +32520,18 @@ _tmp_113_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -32433,9 +32540,9 @@ _tmp_113_rule(Parser *p) return _res; } -// _tmp_114: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_115: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_114_rule(Parser *p) +_tmp_115_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32451,18 +32558,18 @@ _tmp_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_115[%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_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_115[%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_114[%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, "list")); } { // tuple @@ -32470,18 +32577,18 @@ _tmp_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_115[%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_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_115[%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_114[%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, "tuple")); } { // genexp @@ -32489,18 +32596,18 @@ _tmp_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_115[%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_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_115[%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_114[%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, "genexp")); } { // 'True' @@ -32508,18 +32615,18 @@ _tmp_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 610)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_114[%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, "'True'")); } { // 'None' @@ -32527,18 +32634,18 @@ _tmp_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 611)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_114[%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, "'None'")); } { // 'False' @@ -32546,18 +32653,18 @@ _tmp_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 612)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_114[%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, "'False'")); } _res = NULL; @@ -32566,9 +32673,9 @@ _tmp_114_rule(Parser *p) return _res; } -// _loop0_115: star_named_expressions +// _loop0_116: star_named_expressions static asdl_seq * -_loop0_115_rule(Parser *p) +_loop0_116_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32593,7 +32700,7 @@ _loop0_115_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_116[%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 @@ -32616,7 +32723,7 @@ _loop0_115_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_115[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_116[%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); @@ -32633,9 +32740,9 @@ _loop0_115_rule(Parser *p) return _seq; } -// _loop0_116: (star_targets '=') +// _loop0_117: (star_targets '=') static asdl_seq * -_loop0_116_rule(Parser *p) +_loop0_117_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32660,13 +32767,13 @@ _loop0_116_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_150_var; + D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_151_var; while ( - (_tmp_150_var = _tmp_150_rule(p)) // star_targets '=' + (_tmp_151_var = _tmp_151_rule(p)) // star_targets '=' ) { - _res = _tmp_150_var; + _res = _tmp_151_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32683,7 +32790,7 @@ _loop0_116_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_116[%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, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32700,9 +32807,9 @@ _loop0_116_rule(Parser *p) return _seq; } -// _tmp_117: '[' | '(' | '{' +// _tmp_118: '[' | '(' | '{' static void * -_tmp_117_rule(Parser *p) +_tmp_118_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32718,18 +32825,18 @@ _tmp_117_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' @@ -32737,18 +32844,18 @@ _tmp_117_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' @@ -32756,18 +32863,18 @@ _tmp_117_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -32776,9 +32883,9 @@ _tmp_117_rule(Parser *p) return _res; } -// _tmp_118: '[' | '{' +// _tmp_119: '[' | '{' static void * -_tmp_118_rule(Parser *p) +_tmp_119_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32794,18 +32901,18 @@ _tmp_118_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_119[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -32813,18 +32920,18 @@ _tmp_118_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_119[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -32833,9 +32940,9 @@ _tmp_118_rule(Parser *p) return _res; } -// _tmp_119: slash_no_default | slash_with_default +// _tmp_120: slash_no_default | slash_with_default static void * -_tmp_119_rule(Parser *p) +_tmp_120_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32851,18 +32958,18 @@ _tmp_119_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_120[%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_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_120[%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_119[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); } { // slash_with_default @@ -32870,18 +32977,18 @@ _tmp_119_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_120[%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_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_120[%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_119[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } _res = NULL; @@ -32890,9 +32997,9 @@ _tmp_119_rule(Parser *p) return _res; } -// _tmp_120: ',' | param_no_default +// _tmp_121: ',' | param_no_default static void * -_tmp_120_rule(Parser *p) +_tmp_121_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32908,18 +33015,18 @@ _tmp_120_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_120[%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, "','")); } { // param_no_default @@ -32927,18 +33034,18 @@ _tmp_120_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_121[%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_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_121[%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_120[%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, "param_no_default")); } _res = NULL; @@ -32947,9 +33054,9 @@ _tmp_120_rule(Parser *p) return _res; } -// _tmp_121: ')' | ',' +// _tmp_122: ')' | ',' static void * -_tmp_121_rule(Parser *p) +_tmp_122_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32965,18 +33072,18 @@ _tmp_121_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_121[%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, "')'")); } { // ',' @@ -32984,18 +33091,18 @@ _tmp_121_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_121[%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, "','")); } _res = NULL; @@ -33004,9 +33111,9 @@ _tmp_121_rule(Parser *p) return _res; } -// _tmp_122: ')' | ',' (')' | '**') +// _tmp_123: ')' | ',' (')' | '**') static void * -_tmp_122_rule(Parser *p) +_tmp_123_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33022,18 +33129,18 @@ _tmp_122_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; 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_123[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -33041,21 +33148,21 @@ _tmp_122_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_163_var; + void *_tmp_165_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_163_var = _tmp_163_rule(p)) // ')' | '**' + (_tmp_165_var = _tmp_165_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_163_var); + D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_165_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_123[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -33064,9 +33171,9 @@ _tmp_122_rule(Parser *p) return _res; } -// _tmp_123: param_no_default | ',' +// _tmp_124: param_no_default | ',' static void * -_tmp_123_rule(Parser *p) +_tmp_124_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33082,18 +33189,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, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_124[%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_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_124[%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_123[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_124[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } { // ',' @@ -33101,18 +33208,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, "','")); + D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; 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_124[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -33121,9 +33228,9 @@ _tmp_123_rule(Parser *p) return _res; } -// _tmp_124: '*' | '**' | '/' +// _tmp_125: '*' | '**' | '/' static void * -_tmp_124_rule(Parser *p) +_tmp_125_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33139,18 +33246,18 @@ _tmp_124_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_124[%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, "'*'")); } { // '**' @@ -33158,18 +33265,18 @@ _tmp_124_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_124[%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, "'**'")); } { // '/' @@ -33177,18 +33284,18 @@ _tmp_124_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_124[%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, "'/'")); } _res = NULL; @@ -33197,9 +33304,9 @@ _tmp_124_rule(Parser *p) return _res; } -// _tmp_125: lambda_slash_no_default | lambda_slash_with_default +// _tmp_126: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_125_rule(Parser *p) +_tmp_126_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33215,18 +33322,18 @@ _tmp_125_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_126[%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_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_126[%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_125[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); } { // lambda_slash_with_default @@ -33234,18 +33341,18 @@ _tmp_125_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_126[%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_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_126[%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_125[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; @@ -33254,9 +33361,9 @@ _tmp_125_rule(Parser *p) return _res; } -// _loop0_126: ',' lambda_param +// _loop0_127: ',' lambda_param static asdl_seq * -_loop0_126_rule(Parser *p) +_loop0_127_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33281,7 +33388,7 @@ _loop0_126_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); + D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); Token * _literal; arg_ty elem; while ( @@ -33313,7 +33420,7 @@ _loop0_126_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_126[%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, "',' lambda_param")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33330,9 +33437,9 @@ _loop0_126_rule(Parser *p) return _seq; } -// _gather_127: lambda_param _loop0_126 +// _gather_128: lambda_param _loop0_127 static asdl_seq * -_gather_127_rule(Parser *p) +_gather_128_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33343,27 +33450,27 @@ _gather_127_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // lambda_param _loop0_126 + { // lambda_param _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, "lambda_param _loop0_126")); + D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_127")); arg_ty elem; asdl_seq * seq; if ( (elem = lambda_param_rule(p)) // lambda_param && - (seq = _loop0_126_rule(p)) // _loop0_126 + (seq = _loop0_127_rule(p)) // _loop0_127 ) { - D(fprintf(stderr, "%*c+ _gather_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_126")); + D(fprintf(stderr, "%*c+ _gather_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _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, "lambda_param _loop0_126")); + D(fprintf(stderr, "%*c%s _gather_128[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_127")); } _res = NULL; done: @@ -33371,9 +33478,9 @@ _gather_127_rule(Parser *p) return _res; } -// _tmp_128: ',' | lambda_param_no_default +// _tmp_129: ',' | lambda_param_no_default static void * -_tmp_128_rule(Parser *p) +_tmp_129_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33389,18 +33496,18 @@ _tmp_128_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_128[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // lambda_param_no_default @@ -33408,18 +33515,18 @@ _tmp_128_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_129[%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_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_129[%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_128[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } _res = NULL; @@ -33428,9 +33535,9 @@ _tmp_128_rule(Parser *p) return _res; } -// _tmp_129: ':' | ',' (':' | '**') +// _tmp_130: ':' | ',' (':' | '**') static void * -_tmp_129_rule(Parser *p) +_tmp_130_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33446,18 +33553,18 @@ _tmp_129_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -33465,21 +33572,21 @@ _tmp_129_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_164_var; + void *_tmp_166_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_164_var = _tmp_164_rule(p)) // ':' | '**' + (_tmp_166_var = _tmp_166_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_164_var); + D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_166_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -33488,9 +33595,9 @@ _tmp_129_rule(Parser *p) return _res; } -// _tmp_130: lambda_param_no_default | ',' +// _tmp_131: lambda_param_no_default | ',' static void * -_tmp_130_rule(Parser *p) +_tmp_131_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33506,18 +33613,18 @@ _tmp_130_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_131[%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_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_131[%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_130[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } { // ',' @@ -33525,18 +33632,18 @@ _tmp_130_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -33545,9 +33652,9 @@ _tmp_130_rule(Parser *p) return _res; } -// _tmp_131: bitwise_or ((',' bitwise_or))* ','? +// _tmp_132: bitwise_or ((',' bitwise_or))* ','? static void * -_tmp_131_rule(Parser *p) +_tmp_132_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33563,25 +33670,25 @@ _tmp_131_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); - asdl_seq * _loop0_165_var; + D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + asdl_seq * _loop0_167_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_165_var = _loop0_165_rule(p)) // ((',' bitwise_or))* + (_loop0_167_var = _loop0_167_rule(p)) // ((',' bitwise_or))* && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { - D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); - _res = _PyPegen_dummy_name(p, bitwise_or_var, _loop0_165_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + _res = _PyPegen_dummy_name(p, bitwise_or_var, _loop0_167_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); } _res = NULL; @@ -33590,9 +33697,9 @@ _tmp_131_rule(Parser *p) return _res; } -// _loop0_132: ',' dotted_name +// _loop0_133: ',' dotted_name static asdl_seq * -_loop0_132_rule(Parser *p) +_loop0_133_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33617,7 +33724,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, "',' dotted_name")); + D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name")); Token * _literal; expr_ty elem; while ( @@ -33649,7 +33756,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_133[%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); @@ -33666,9 +33773,9 @@ _loop0_132_rule(Parser *p) return _seq; } -// _gather_133: dotted_name _loop0_132 +// _gather_134: dotted_name _loop0_133 static asdl_seq * -_gather_133_rule(Parser *p) +_gather_134_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33679,27 +33786,27 @@ _gather_133_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // dotted_name _loop0_132 + { // dotted_name _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, "dotted_name _loop0_132")); + D(fprintf(stderr, "%*c> _gather_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_133")); expr_ty elem; asdl_seq * seq; if ( (elem = dotted_name_rule(p)) // dotted_name && - (seq = _loop0_132_rule(p)) // _loop0_132 + (seq = _loop0_133_rule(p)) // _loop0_133 ) { - D(fprintf(stderr, "%*c+ _gather_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_132")); + D(fprintf(stderr, "%*c+ _gather_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _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, "dotted_name _loop0_132")); + D(fprintf(stderr, "%*c%s _gather_134[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_133")); } _res = NULL; done: @@ -33707,9 +33814,9 @@ _gather_133_rule(Parser *p) return _res; } -// _loop0_134: ',' (expression ['as' star_target]) +// _loop0_135: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_134_rule(Parser *p) +_loop0_135_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33734,13 +33841,13 @@ _loop0_134_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_135[%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_166_rule(p)) // expression ['as' star_target] + (elem = _tmp_168_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -33766,7 +33873,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_135[%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); @@ -33783,9 +33890,9 @@ _loop0_134_rule(Parser *p) return _seq; } -// _gather_135: (expression ['as' star_target]) _loop0_134 +// _gather_136: (expression ['as' star_target]) _loop0_135 static asdl_seq * -_gather_135_rule(Parser *p) +_gather_136_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33796,27 +33903,27 @@ _gather_135_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_134 + { // (expression ['as' star_target]) _loop0_135 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_134")); + D(fprintf(stderr, "%*c> _gather_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_135")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_166_rule(p)) // expression ['as' star_target] + (elem = _tmp_168_rule(p)) // expression ['as' star_target] && - (seq = _loop0_134_rule(p)) // _loop0_134 + (seq = _loop0_135_rule(p)) // _loop0_135 ) { - D(fprintf(stderr, "%*c+ _gather_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_134")); + D(fprintf(stderr, "%*c+ _gather_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_135")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_135[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_134")); + D(fprintf(stderr, "%*c%s _gather_136[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_135")); } _res = NULL; done: @@ -33824,9 +33931,9 @@ _gather_135_rule(Parser *p) return _res; } -// _loop0_136: ',' (expressions ['as' star_target]) +// _loop0_137: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_136_rule(Parser *p) +_loop0_137_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33851,13 +33958,13 @@ _loop0_136_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_137[%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_167_rule(p)) // expressions ['as' star_target] + (elem = _tmp_169_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -33883,7 +33990,7 @@ _loop0_136_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_136[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_137[%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); @@ -33900,9 +34007,9 @@ _loop0_136_rule(Parser *p) return _seq; } -// _gather_137: (expressions ['as' star_target]) _loop0_136 +// _gather_138: (expressions ['as' star_target]) _loop0_137 static asdl_seq * -_gather_137_rule(Parser *p) +_gather_138_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33913,27 +34020,27 @@ _gather_137_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_136 + { // (expressions ['as' star_target]) _loop0_137 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_136")); + D(fprintf(stderr, "%*c> _gather_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_137")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_167_rule(p)) // expressions ['as' star_target] + (elem = _tmp_169_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_136_rule(p)) // _loop0_136 + (seq = _loop0_137_rule(p)) // _loop0_137 ) { - D(fprintf(stderr, "%*c+ _gather_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_136")); + D(fprintf(stderr, "%*c+ _gather_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_137")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_137[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_136")); + D(fprintf(stderr, "%*c%s _gather_138[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_137")); } _res = NULL; done: @@ -33941,9 +34048,9 @@ _gather_137_rule(Parser *p) return _res; } -// _tmp_138: 'except' | 'finally' +// _tmp_139: 'except' | 'finally' static void * -_tmp_138_rule(Parser *p) +_tmp_139_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -33959,18 +34066,18 @@ _tmp_138_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 663)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -33978,18 +34085,18 @@ _tmp_138_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 659)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -33998,9 +34105,9 @@ _tmp_138_rule(Parser *p) return _res; } -// _loop0_139: block +// _loop0_140: block static asdl_seq * -_loop0_139_rule(Parser *p) +_loop0_140_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34025,7 +34132,7 @@ _loop0_139_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + D(fprintf(stderr, "%*c> _loop0_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); asdl_stmt_seq* block_var; while ( (block_var = block_rule(p)) // block @@ -34048,7 +34155,7 @@ _loop0_139_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_139[%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, "block")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34065,9 +34172,9 @@ _loop0_139_rule(Parser *p) return _seq; } -// _tmp_140: expression ['as' NAME] +// _tmp_141: expression ['as' NAME] static void * -_tmp_140_rule(Parser *p) +_tmp_141_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34083,7 +34190,7 @@ _tmp_140_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c> _tmp_141[%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; @@ -34093,12 +34200,12 @@ _tmp_140_rule(Parser *p) (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] ) { - D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c+ _tmp_141[%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_140[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' NAME]")); } _res = NULL; @@ -34107,9 +34214,9 @@ _tmp_140_rule(Parser *p) return _res; } -// _tmp_141: NEWLINE | ':' +// _tmp_142: NEWLINE | ':' static void * -_tmp_141_rule(Parser *p) +_tmp_142_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34125,18 +34232,18 @@ _tmp_141_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_142[%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_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_142[%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_141[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); } { // ':' @@ -34144,18 +34251,18 @@ _tmp_141_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -34164,9 +34271,9 @@ _tmp_141_rule(Parser *p) return _res; } -// _tmp_142: positional_patterns ',' +// _tmp_143: positional_patterns ',' static void * -_tmp_142_rule(Parser *p) +_tmp_143_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34182,7 +34289,7 @@ _tmp_142_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; asdl_pattern_seq* positional_patterns_var; if ( @@ -34191,12 +34298,12 @@ _tmp_142_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c+ _tmp_143[%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_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; @@ -34205,9 +34312,9 @@ _tmp_142_rule(Parser *p) return _res; } -// _tmp_143: '}' | ',' +// _tmp_144: '}' | ',' static void * -_tmp_143_rule(Parser *p) +_tmp_144_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34223,18 +34330,18 @@ _tmp_143_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -34242,18 +34349,18 @@ _tmp_143_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -34262,9 +34369,9 @@ _tmp_143_rule(Parser *p) return _res; } -// _tmp_144: '=' | '!' | ':' | '}' +// _tmp_145: '=' | '!' | ':' | '}' static void * -_tmp_144_rule(Parser *p) +_tmp_145_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34280,18 +34387,18 @@ _tmp_144_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // '!' @@ -34299,18 +34406,18 @@ _tmp_144_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -34318,18 +34425,18 @@ _tmp_144_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -34337,18 +34444,18 @@ _tmp_144_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -34357,9 +34464,9 @@ _tmp_144_rule(Parser *p) return _res; } -// _tmp_145: '!' | ':' | '}' +// _tmp_146: '!' | ':' | '}' static void * -_tmp_145_rule(Parser *p) +_tmp_146_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34375,18 +34482,18 @@ _tmp_145_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -34394,18 +34501,18 @@ _tmp_145_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -34413,18 +34520,18 @@ _tmp_145_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -34433,9 +34540,9 @@ _tmp_145_rule(Parser *p) return _res; } -// _tmp_146: '!' NAME +// _tmp_147: '!' NAME static void * -_tmp_146_rule(Parser *p) +_tmp_147_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34451,7 +34558,7 @@ _tmp_146_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -34460,12 +34567,12 @@ _tmp_146_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_147[%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_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -34474,9 +34581,9 @@ _tmp_146_rule(Parser *p) return _res; } -// _tmp_147: ':' | '}' +// _tmp_148: ':' | '}' static void * -_tmp_147_rule(Parser *p) +_tmp_148_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34492,18 +34599,18 @@ _tmp_147_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -34511,18 +34618,18 @@ _tmp_147_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -34531,9 +34638,9 @@ _tmp_147_rule(Parser *p) return _res; } -// _tmp_148: '+' | '-' | '*' | '/' | '%' | '//' | '@' +// _tmp_149: '+' | '-' | '*' | '/' | '%' | '//' | '@' static void * -_tmp_148_rule(Parser *p) +_tmp_149_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34549,18 +34656,18 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "'+'")); } { // '-' @@ -34568,18 +34675,18 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "'-'")); } { // '*' @@ -34587,18 +34694,18 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "'*'")); } { // '/' @@ -34606,18 +34713,18 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "'/'")); } { // '%' @@ -34625,18 +34732,18 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 24)) // token='%' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "'%'")); } { // '//' @@ -34644,18 +34751,18 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 47)) // token='//' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "'//'")); } { // '@' @@ -34663,18 +34770,18 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 49)) // token='@' ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "'@'")); } _res = NULL; @@ -34683,9 +34790,9 @@ _tmp_148_rule(Parser *p) return _res; } -// _tmp_149: '+' | '-' | '~' +// _tmp_150: '+' | '-' | '~' static void * -_tmp_149_rule(Parser *p) +_tmp_150_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34701,18 +34808,18 @@ _tmp_149_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%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, "'+'")); } { // '-' @@ -34720,18 +34827,18 @@ _tmp_149_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%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, "'-'")); } { // '~' @@ -34739,18 +34846,18 @@ _tmp_149_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~'")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 31)) // token='~' ) { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~'")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%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, "'~'")); } _res = NULL; @@ -34759,9 +34866,9 @@ _tmp_149_rule(Parser *p) return _res; } -// _tmp_150: star_targets '=' +// _tmp_151: star_targets '=' static void * -_tmp_150_rule(Parser *p) +_tmp_151_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34777,7 +34884,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, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -34786,7 +34893,7 @@ _tmp_150_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -34796,7 +34903,7 @@ _tmp_150_rule(Parser *p) 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_151[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -34805,9 +34912,9 @@ _tmp_150_rule(Parser *p) return _res; } -// _tmp_151: '.' | '...' +// _tmp_152: '.' | '...' static void * -_tmp_151_rule(Parser *p) +_tmp_152_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34823,18 +34930,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, "'.'")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; 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_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -34842,18 +34949,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, "'...'")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; 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_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -34862,9 +34969,9 @@ _tmp_151_rule(Parser *p) return _res; } -// _tmp_152: '@' named_expression NEWLINE +// _tmp_153: '@' named_expression NEWLINE static void * -_tmp_152_rule(Parser *p) +_tmp_153_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34880,7 +34987,7 @@ _tmp_152_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -34892,7 +34999,7 @@ _tmp_152_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -34902,7 +35009,7 @@ _tmp_152_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%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, "'@' named_expression NEWLINE")); } _res = NULL; @@ -34911,9 +35018,9 @@ _tmp_152_rule(Parser *p) return _res; } -// _tmp_153: ',' star_expression +// _tmp_154: ',' star_expression static void * -_tmp_153_rule(Parser *p) +_tmp_154_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34929,7 +35036,7 @@ _tmp_153_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -34938,7 +35045,7 @@ _tmp_153_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -34948,7 +35055,7 @@ _tmp_153_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%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, "',' star_expression")); } _res = NULL; @@ -34957,9 +35064,9 @@ _tmp_153_rule(Parser *p) return _res; } -// _tmp_154: 'or' conjunction +// _tmp_155: 'or' conjunction static void * -_tmp_154_rule(Parser *p) +_tmp_155_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -34975,7 +35082,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, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -34984,7 +35091,7 @@ _tmp_154_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -34994,7 +35101,7 @@ _tmp_154_rule(Parser *p) 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_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -35003,9 +35110,9 @@ _tmp_154_rule(Parser *p) return _res; } -// _tmp_155: 'and' inversion +// _tmp_156: 'and' inversion static void * -_tmp_155_rule(Parser *p) +_tmp_156_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35021,7 +35128,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, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -35030,7 +35137,7 @@ _tmp_155_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -35040,7 +35147,7 @@ _tmp_155_rule(Parser *p) 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_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -35049,9 +35156,9 @@ _tmp_155_rule(Parser *p) return _res; } -// _tmp_156: slice | starred_expression +// _tmp_157: slice | starred_expression static void * -_tmp_156_rule(Parser *p) +_tmp_157_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35067,18 +35174,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, "slice")); + D(fprintf(stderr, "%*c> _tmp_157[%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_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c+ _tmp_157[%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_156[%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, "slice")); } { // starred_expression @@ -35086,18 +35193,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, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_157[%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_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_157[%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_156[%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, "starred_expression")); } _res = NULL; @@ -35106,9 +35213,9 @@ _tmp_156_rule(Parser *p) return _res; } -// _tmp_157: fstring | string +// _tmp_158: fstring | string static void * -_tmp_157_rule(Parser *p) +_tmp_158_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35124,18 +35231,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, "fstring")); + D(fprintf(stderr, "%*c> _tmp_158[%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_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c+ _tmp_158[%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_157[%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, "fstring")); } { // string @@ -35143,18 +35250,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, "string")); + D(fprintf(stderr, "%*c> _tmp_158[%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_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); + D(fprintf(stderr, "%*c+ _tmp_158[%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_157[%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, "string")); } _res = NULL; @@ -35163,9 +35270,9 @@ _tmp_157_rule(Parser *p) return _res; } -// _tmp_158: 'if' disjunction +// _tmp_159: 'if' disjunction static void * -_tmp_158_rule(Parser *p) +_tmp_159_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35181,7 +35288,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, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -35190,7 +35297,7 @@ _tmp_158_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -35200,7 +35307,7 @@ _tmp_158_rule(Parser *p) 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_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -35209,9 +35316,9 @@ _tmp_158_rule(Parser *p) return _res; } -// _tmp_159: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_160: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_159_rule(Parser *p) +_tmp_160_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35227,18 +35334,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, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_160[%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_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_160[%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_159[%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, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -35246,7 +35353,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, "(assignment_expression | expression !':=') !'='")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); void *_tmp_85_var; if ( (_tmp_85_var = _tmp_85_rule(p)) // assignment_expression | expression !':=' @@ -35254,12 +35361,12 @@ _tmp_159_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); _res = _tmp_85_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_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -35268,9 +35375,9 @@ _tmp_159_rule(Parser *p) return _res; } -// _tmp_160: ',' star_target +// _tmp_161: ',' star_target static void * -_tmp_160_rule(Parser *p) +_tmp_161_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35286,7 +35393,7 @@ _tmp_160_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -35295,7 +35402,7 @@ _tmp_160_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -35305,7 +35412,7 @@ _tmp_160_rule(Parser *p) 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_161[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -35314,10 +35421,10 @@ _tmp_160_rule(Parser *p) return _res; } -// _tmp_161: +// _tmp_162: // | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs static void * -_tmp_161_rule(Parser *p) +_tmp_162_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35333,7 +35440,7 @@ _tmp_161_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); asdl_seq * _gather_87_var; Token * _literal; asdl_seq* kwargs_var; @@ -35345,12 +35452,12 @@ _tmp_161_rule(Parser *p) (kwargs_var = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); _res = _PyPegen_dummy_name(p, _gather_87_var, _literal, kwargs_var); 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_162[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); } _res = NULL; @@ -35359,9 +35466,9 @@ _tmp_161_rule(Parser *p) return _res; } -// _tmp_162: starred_expression !'=' +// _tmp_163: starred_expression !'=' static void * -_tmp_162_rule(Parser *p) +_tmp_163_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35377,7 +35484,7 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); + D(fprintf(stderr, "%*c> _tmp_163[%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 @@ -35385,12 +35492,12 @@ _tmp_162_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); + D(fprintf(stderr, "%*c+ _tmp_163[%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_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_163[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression !'='")); } _res = NULL; @@ -35399,9 +35506,49 @@ _tmp_162_rule(Parser *p) return _res; } -// _tmp_163: ')' | '**' +// _tmp_164: !STRING expression_without_invalid static void * -_tmp_163_rule(Parser *p) +_tmp_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; + { // !STRING expression_without_invalid + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!STRING expression_without_invalid")); + expr_ty expression_without_invalid_var; + if ( + _PyPegen_lookahead(0, (void *(*)(Parser *)) _PyPegen_string_token, p) + && + (expression_without_invalid_var = expression_without_invalid_rule(p)) // expression_without_invalid + ) + { + D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!STRING expression_without_invalid")); + _res = expression_without_invalid_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_164[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!STRING expression_without_invalid")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_165: ')' | '**' +static void * +_tmp_165_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35417,18 +35564,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_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_165[%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_165[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -35436,18 +35583,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_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_165[%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_165[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -35456,9 +35603,9 @@ _tmp_163_rule(Parser *p) return _res; } -// _tmp_164: ':' | '**' +// _tmp_166: ':' | '**' static void * -_tmp_164_rule(Parser *p) +_tmp_166_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35474,18 +35621,18 @@ _tmp_164_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_164[%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, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_164[%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_164[%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, "':'")); } { // '**' @@ -35493,18 +35640,18 @@ _tmp_164_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_164[%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, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_164[%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_164[%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; @@ -35513,9 +35660,9 @@ _tmp_164_rule(Parser *p) return _res; } -// _loop0_165: (',' bitwise_or) +// _loop0_167: (',' bitwise_or) static asdl_seq * -_loop0_165_rule(Parser *p) +_loop0_167_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35540,13 +35687,13 @@ _loop0_165_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' bitwise_or)")); - void *_tmp_168_var; + D(fprintf(stderr, "%*c> _loop0_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' bitwise_or)")); + void *_tmp_170_var; while ( - (_tmp_168_var = _tmp_168_rule(p)) // ',' bitwise_or + (_tmp_170_var = _tmp_170_rule(p)) // ',' bitwise_or ) { - _res = _tmp_168_var; + _res = _tmp_170_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -35563,7 +35710,7 @@ _loop0_165_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_167[%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); @@ -35580,9 +35727,9 @@ _loop0_165_rule(Parser *p) return _seq; } -// _tmp_166: expression ['as' star_target] +// _tmp_168: expression ['as' star_target] static void * -_tmp_166_rule(Parser *p) +_tmp_168_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35598,22 +35745,22 @@ _tmp_166_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_168[%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_169_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_171_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_168[%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_166[%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, "expression ['as' star_target]")); } _res = NULL; @@ -35622,9 +35769,9 @@ _tmp_166_rule(Parser *p) return _res; } -// _tmp_167: expressions ['as' star_target] +// _tmp_169: expressions ['as' star_target] static void * -_tmp_167_rule(Parser *p) +_tmp_169_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35640,22 +35787,22 @@ _tmp_167_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_169[%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_169_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_171_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_169[%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_167[%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, "expressions ['as' star_target]")); } _res = NULL; @@ -35664,9 +35811,9 @@ _tmp_167_rule(Parser *p) return _res; } -// _tmp_168: ',' bitwise_or +// _tmp_170: ',' bitwise_or static void * -_tmp_168_rule(Parser *p) +_tmp_170_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35682,7 +35829,7 @@ _tmp_168_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + D(fprintf(stderr, "%*c> _tmp_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); Token * _literal; expr_ty bitwise_or_var; if ( @@ -35691,12 +35838,12 @@ _tmp_168_rule(Parser *p) (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or ) { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + D(fprintf(stderr, "%*c+ _tmp_170[%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_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_170[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' bitwise_or")); } _res = NULL; @@ -35705,9 +35852,9 @@ _tmp_168_rule(Parser *p) return _res; } -// _tmp_169: 'as' star_target +// _tmp_171: 'as' star_target static void * -_tmp_169_rule(Parser *p) +_tmp_171_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -35723,7 +35870,7 @@ _tmp_169_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -35732,12 +35879,12 @@ _tmp_169_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_171[%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_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; diff --git a/Parser/pegen.h b/Parser/pegen.h index 32c64e7774b878..651659ac6c926b 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -346,6 +346,8 @@ mod_ty _PyPegen_make_module(Parser *, asdl_stmt_seq *); void *_PyPegen_arguments_parsing_error(Parser *, expr_ty); expr_ty _PyPegen_get_last_comprehension_item(comprehension_ty comprehension); void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehension_seq *comprehensions); +stmt_ty _PyPegen_checked_future_import(Parser *p, identifier module, asdl_alias_seq *, + int , int, int , int , int , PyArena *); // Parser API diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 6146f69912bfa3..f62b8695995617 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -352,8 +352,8 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, assert(p->tok->fp == NULL || p->tok->fp == stdin || p->tok->done == E_EOF); if (p->tok->lineno <= lineno && p->tok->inp > p->tok->buf) { - Py_ssize_t size = p->tok->inp - p->tok->buf; - error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); + Py_ssize_t size = p->tok->inp - p->tok->line_start; + error_line = PyUnicode_DecodeUTF8(p->tok->line_start, size, "replace"); } else if (p->tok->fp == NULL || p->tok->fp == stdin) { error_line = get_error_line_from_tokenizer_buffers(p, lineno); diff --git a/Parser/string_parser.c b/Parser/string_parser.c index 9dd8f9ef28bd4f..b93300b00a8545 100644 --- a/Parser/string_parser.c +++ b/Parser/string_parser.c @@ -11,7 +11,7 @@ //// STRING HANDLING FUNCTIONS //// static int -warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token *t) +warn_invalid_escape_sequence(Parser *p, const char* buffer, const char *first_invalid_escape, Token *t) { if (p->call_invalid_rules) { // Do not report warnings if we are in the second pass of the parser @@ -48,8 +48,46 @@ warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token else { category = PyExc_DeprecationWarning; } + + // Calculate the lineno and the col_offset of the invalid escape sequence + const char *start = buffer; + const char *end = first_invalid_escape; + int lineno = t->lineno; + int col_offset = t->col_offset; + while (start < end) { + if (*start == '\n') { + lineno++; + col_offset = 0; + } + else { + col_offset++; + } + start++; + } + + // Count the number of quotes in the token + char first_quote = 0; + if (lineno == t->lineno) { + int quote_count = 0; + char* tok = PyBytes_AsString(t->bytes); + for (int i = 0; i < PyBytes_Size(t->bytes); i++) { + if (tok[i] == '\'' || tok[i] == '\"') { + if (quote_count == 0) { + first_quote = tok[i]; + } + if (tok[i] == first_quote) { + quote_count++; + } + } else { + break; + } + } + + col_offset += quote_count; + } + if (PyErr_WarnExplicitObject(category, msg, p->tok->filename, - t->lineno, NULL, NULL) < 0) { + lineno, NULL, NULL) < 0) { if (PyErr_ExceptionMatches(category)) { /* Replace the Syntax/DeprecationWarning exception with a SyntaxError to get a more accurate error report */ @@ -60,13 +98,13 @@ warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token error location, if p->known_err_token is not set. */ p->known_err_token = t; if (octal) { - RAISE_SYNTAX_ERROR( + RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, lineno, col_offset-1, lineno, col_offset+1, "\"\\%.3s\" is an invalid octal escape sequence. " "Did you mean \"\\\\%.3s\"? A raw string is also an option.", first_invalid_escape, first_invalid_escape); } else { - RAISE_SYNTAX_ERROR( + RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, lineno, col_offset-1, lineno, col_offset+1, "\"\\%c\" is an invalid escape sequence. " "Did you mean \"\\\\%c\"? A raw string is also an option.", c, c); @@ -163,7 +201,7 @@ decode_unicode_with_escapes(Parser *parser, const char *s, size_t len, Token *t) // HACK: later we can simply pass the line no, since we don't preserve the tokens // when we are decoding the string but we preserve the line numbers. if (v != NULL && first_invalid_escape != NULL && t != NULL) { - if (warn_invalid_escape_sequence(parser, first_invalid_escape, t) < 0) { + if (warn_invalid_escape_sequence(parser, s, first_invalid_escape, t) < 0) { /* We have not decref u before because first_invalid_escape points inside u. */ Py_XDECREF(u); @@ -185,7 +223,7 @@ decode_bytes_with_escapes(Parser *p, const char *s, Py_ssize_t len, Token *t) } if (first_invalid_escape != NULL) { - if (warn_invalid_escape_sequence(p, first_invalid_escape, t) < 0) { + if (warn_invalid_escape_sequence(p, s, first_invalid_escape, t) < 0) { Py_DECREF(result); return NULL; } diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 78d84002d593fb..0b58e8cd2a2ced 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -567,62 +567,6 @@ fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) return make_const(node, newval, arena); } -/* Change literal list or set of constants into constant - tuple or frozenset respectively. Change literal list of - non-constants into tuple. - Used for right operand of "in" and "not in" tests and for iterable - in "for" loop and comprehensions. -*/ -static int -fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state) -{ - PyObject *newval; - if (arg->kind == List_kind) { - /* First change a list into tuple. */ - asdl_expr_seq *elts = arg->v.List.elts; - if (has_starred(elts)) { - return 1; - } - expr_context_ty ctx = arg->v.List.ctx; - arg->kind = Tuple_kind; - arg->v.Tuple.elts = elts; - arg->v.Tuple.ctx = ctx; - /* Try to create a constant tuple. */ - newval = make_const_tuple(elts); - } - else if (arg->kind == Set_kind) { - newval = make_const_tuple(arg->v.Set.elts); - if (newval) { - Py_SETREF(newval, PyFrozenSet_New(newval)); - } - } - else { - return 1; - } - return make_const(arg, newval, arena); -} - -static int -fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) -{ - asdl_int_seq *ops; - asdl_expr_seq *args; - Py_ssize_t i; - - ops = node->v.Compare.ops; - args = node->v.Compare.comparators; - /* Change literal list or set in 'in' or 'not in' into - tuple or frozenset respectively. */ - i = asdl_seq_LEN(ops) - 1; - int op = asdl_seq_GET(ops, i); - if (op == In || op == NotIn) { - if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) { - return 0; - } - } - return 1; -} - static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); @@ -783,7 +727,6 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) case Compare_kind: CALL(astfold_expr, expr_ty, node_->v.Compare.left); CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators); - CALL(fold_compare, expr_ty, node_); break; case Call_kind: CALL(astfold_expr, expr_ty, node_->v.Call.func); @@ -852,8 +795,6 @@ astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState CALL(astfold_expr, expr_ty, node_->target); CALL(astfold_expr, expr_ty, node_->iter); CALL_SEQ(astfold_expr, expr, node_->ifs); - - CALL(fold_iter, expr_ty, node_->iter); return 1; } @@ -940,8 +881,6 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) CALL(astfold_expr, expr_ty, node_->v.For.iter); CALL_SEQ(astfold_stmt, stmt, node_->v.For.body); CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse); - - CALL(fold_iter, expr_ty, node_->v.For.iter); break; case AsyncFor_kind: CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 703d7ec61ebab3..b18b0075315ad3 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -361,7 +361,7 @@ dummy_func( } pure inst(POP_TOP, (value --)) { - DECREF_INPUTS(); + PyStackRef_CLOSE(value); } pure inst(PUSH_NULL, (-- res)) { @@ -388,7 +388,7 @@ dummy_func( ERROR_NO_POP(); } } - DECREF_INPUTS(); + PyStackRef_CLOSE(value); } tier1 inst(INSTRUMENTED_POP_ITER, (iter -- )) { @@ -400,7 +400,7 @@ dummy_func( (void)receiver; val = value; DEAD(value); - DECREF_INPUTS(); + PyStackRef_CLOSE(receiver); } tier1 inst(INSTRUMENTED_END_SEND, (receiver, value -- val)) { @@ -418,7 +418,7 @@ dummy_func( inst(UNARY_NEGATIVE, (value -- res)) { PyObject *res_o = PyNumber_Negative(PyStackRef_AsPyObjectBorrow(value)); - DECREF_INPUTS(); + PyStackRef_CLOSE(value); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -453,7 +453,7 @@ dummy_func( op(_TO_BOOL, (value -- res)) { int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value)); - DECREF_INPUTS(); + PyStackRef_CLOSE(value); ERROR_IF(err < 0, error); res = err ? PyStackRef_True : PyStackRef_False; } @@ -475,7 +475,7 @@ dummy_func( res = PyStackRef_False; } else { - DECREF_INPUTS(); + PyStackRef_CLOSE(value); res = PyStackRef_True; } } @@ -507,13 +507,13 @@ dummy_func( } else { assert(Py_SIZE(value_o)); - DECREF_INPUTS(); + PyStackRef_CLOSE(value); res = PyStackRef_True; } } op(_REPLACE_WITH_TRUE, (value -- res)) { - DECREF_INPUTS(); + PyStackRef_CLOSE(value); res = PyStackRef_True; } @@ -524,7 +524,7 @@ dummy_func( inst(UNARY_INVERT, (value -- res)) { PyObject *res_o = PyNumber_Invert(PyStackRef_AsPyObjectBorrow(value)); - DECREF_INPUTS(); + PyStackRef_CLOSE(value); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -721,7 +721,7 @@ dummy_func( // At the end we just skip over the STORE_FAST. op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); - PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + PyObject *right_o = PyStackRef_AsPyObjectSteal(right); assert(PyUnicode_CheckExact(left_o)); assert(PyUnicode_CheckExact(right_o)); @@ -752,8 +752,7 @@ dummy_func( PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); PyUnicode_Append(&temp, right_o); *target_local = PyStackRef_FromPyObjectSteal(temp); - PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc); - DEAD(right); + Py_DECREF(right_o); ERROR_IF(PyStackRef_IsNull(*target_local), error); #if TIER_ONE // The STORE_FAST is already done. This is done here in tier one, @@ -967,7 +966,7 @@ dummy_func( inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) { int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(v)); - DECREF_INPUTS(); + PyStackRef_CLOSE(v); ERROR_IF(err, error); } @@ -1048,7 +1047,7 @@ dummy_func( inst(CALL_INTRINSIC_1, (value -- res)) { assert(oparg <= MAX_INTRINSIC_1); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); - DECREF_INPUTS(); + PyStackRef_CLOSE(value); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -1135,12 +1134,12 @@ dummy_func( "'async for' requires an object with " "__aiter__ method, got %.100s", type->tp_name); - DECREF_INPUTS(); + PyStackRef_CLOSE(obj); ERROR_IF(true, error); } iter_o = (*getter)(obj_o); - DECREF_INPUTS(); + PyStackRef_CLOSE(obj); ERROR_IF(iter_o == NULL, error); if (Py_TYPE(iter_o)->tp_as_async == NULL || @@ -1166,7 +1165,7 @@ dummy_func( inst(GET_AWAITABLE, (iterable -- iter)) { PyObject *iter_o = _PyEval_GetAwaitable(PyStackRef_AsPyObjectBorrow(iterable), oparg); - DECREF_INPUTS(); + PyStackRef_CLOSE(iterable); ERROR_IF(iter_o == NULL, error); iter = PyStackRef_FromPyObjectSteal(iter_o); } @@ -1228,7 +1227,7 @@ dummy_func( JUMPBY(oparg); } else { - DECREF_INPUTS(); + PyStackRef_CLOSE(v); ERROR_IF(true, error); } } @@ -1357,7 +1356,7 @@ dummy_func( } } - tier1 inst(CLEANUP_THROW, (sub_iter_st, last_sent_val_st, exc_value_st -- none, value)) { + tier1 inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value_st -- none, value)) { PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #ifndef Py_TAIL_CALL_INTERP assert(throwflag); @@ -1366,9 +1365,9 @@ dummy_func( int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration); if (matches) { - none = PyStackRef_None; value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value); DECREF_INPUTS(); + none = PyStackRef_None; } else { _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); @@ -1410,7 +1409,7 @@ dummy_func( if (ns == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); - DECREF_INPUTS(); + PyStackRef_CLOSE(v); ERROR_IF(true, error); } if (PyDict_CheckExact(ns)) { @@ -1419,7 +1418,7 @@ dummy_func( else { err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); } - DECREF_INPUTS(); + PyStackRef_CLOSE(v); ERROR_IF(err, error); } @@ -1462,10 +1461,10 @@ dummy_func( (void)counter; } - op(_UNPACK_SEQUENCE, (seq -- output[oparg])) { - _PyStackRef *top = output + oparg; - int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg, -1, top); - DECREF_INPUTS(); + op(_UNPACK_SEQUENCE, (seq -- output[oparg], top[0])) { + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg, -1, top); + Py_DECREF(seq_o); ERROR_IF(res == 0, error); } @@ -1479,7 +1478,7 @@ dummy_func( STAT_INC(UNPACK_SEQUENCE, hit); val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0)); val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1)); - DECREF_INPUTS(); + PyStackRef_CLOSE(seq); } inst(UNPACK_SEQUENCE_TUPLE, (unused/1, seq -- values[oparg])) { @@ -1511,10 +1510,10 @@ dummy_func( DECREF_INPUTS(); } - inst(UNPACK_EX, (seq -- left[oparg & 0xFF], unused, right[oparg >> 8])) { - _PyStackRef *top = right + (oparg >> 8); - int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg & 0xFF, oparg >> 8, top); - DECREF_INPUTS(); + inst(UNPACK_EX, (seq -- left[oparg & 0xFF], unused, right[oparg >> 8], top[0])) { + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg & 0xFF, oparg >> 8, top); + Py_DECREF(seq_o); ERROR_IF(res == 0, error); } @@ -1550,14 +1549,14 @@ dummy_func( inst(DELETE_ATTR, (owner --)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyObject_DelAttr(PyStackRef_AsPyObjectBorrow(owner), name); - DECREF_INPUTS(); + PyStackRef_CLOSE(owner); ERROR_IF(err, error); } inst(STORE_GLOBAL, (v --)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyDict_SetItem(GLOBALS(), name, PyStackRef_AsPyObjectBorrow(v)); - DECREF_INPUTS(); + PyStackRef_CLOSE(v); ERROR_IF(err, error); } @@ -1589,7 +1588,7 @@ dummy_func( PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *v_o; int err = PyMapping_GetOptionalItem(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &v_o); - DECREF_INPUTS(); + PyStackRef_CLOSE(mod_or_class_dict); ERROR_IF(err < 0, error); if (v_o == NULL) { if (PyDict_CheckExact(GLOBALS()) @@ -1885,17 +1884,17 @@ dummy_func( "Value after * must be an iterable, not %.200s", Py_TYPE(iterable)->tp_name); } - DECREF_INPUTS(); + PyStackRef_CLOSE(iterable_st); ERROR_IF(true, error); } assert(Py_IsNone(none_val)); - DECREF_INPUTS(); + PyStackRef_CLOSE(iterable_st); } inst(SET_UPDATE, (set, unused[oparg-1], iterable -- set, unused[oparg-1])) { int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); - DECREF_INPUTS(); + PyStackRef_CLOSE(iterable); ERROR_IF(err < 0, error); } @@ -1970,10 +1969,10 @@ dummy_func( "'%.200s' object is not a mapping", Py_TYPE(update_o)->tp_name); } - DECREF_INPUTS(); + PyStackRef_CLOSE(update); ERROR_IF(true, error); } - DECREF_INPUTS(); + PyStackRef_CLOSE(update); } inst(DICT_MERGE, (callable, unused, unused, dict, unused[oparg - 1], update -- callable, unused, unused, dict, unused[oparg - 1])) { @@ -1984,10 +1983,10 @@ dummy_func( int err = _PyDict_MergeEx(dict_o, update_o, 2); if (err < 0) { _PyEval_FormatKwargsError(tstate, callable_o, update_o); - DECREF_INPUTS(); + PyStackRef_CLOSE(update); ERROR_IF(true, error); } - DECREF_INPUTS(); + PyStackRef_CLOSE(update); } inst(MAP_ADD, (dict_st, unused[oparg - 1], key, value -- dict_st, unused[oparg - 1])) { @@ -2172,7 +2171,7 @@ dummy_func( CALL that it's not a method call. meth | NULL | arg1 | ... | argN */ - DECREF_INPUTS(); + PyStackRef_CLOSE(owner); ERROR_IF(attr_o == NULL, error); self_or_null[0] = PyStackRef_NULL; } @@ -2180,13 +2179,12 @@ dummy_func( else { /* Classic, pushes one value. */ attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); - DECREF_INPUTS(); + PyStackRef_CLOSE(owner); ERROR_IF(attr_o == NULL, error); } attr = PyStackRef_FromPyObjectSteal(attr_o); } - macro(LOAD_ATTR) = _SPECIALIZE_LOAD_ATTR + unused/8 + @@ -2736,12 +2734,11 @@ dummy_func( assert(PyExceptionInstance_Check(left_o)); int err = _PyEval_CheckExceptTypeValid(tstate, right_o); if (err < 0) { - DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_NO_POP(); } int res = PyErr_GivenExceptionMatches(left_o, right_o); - DECREF_INPUTS(); + PyStackRef_CLOSE(right); b = res ? PyStackRef_True : PyStackRef_False; } @@ -2968,7 +2965,7 @@ dummy_func( inst(GET_ITER, (iterable -- iter)) { /* before: [obj]; after [getiter(obj)] */ PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - DECREF_INPUTS(); + PyStackRef_CLOSE(iterable); ERROR_IF(iter_o == NULL, error); iter = PyStackRef_FromPyObjectSteal(iter_o); } @@ -3410,7 +3407,7 @@ dummy_func( assert((oparg & 1) == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); - DECREF_INPUTS(); + PyStackRef_CLOSE(owner); attr = PyStackRef_FromPyObjectNew(descr); } @@ -3426,7 +3423,7 @@ dummy_func( assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); - DECREF_INPUTS(); + PyStackRef_CLOSE(owner); attr = PyStackRef_FromPyObjectNew(descr); } @@ -4797,9 +4794,11 @@ dummy_func( assert(_PyEval_BinaryOps[oparg]); PyObject *res_o = _PyEval_BinaryOps[oparg](lhs_o, rhs_o); - DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + if (res_o == NULL) { + ERROR_NO_POP(); + } res = PyStackRef_FromPyObjectSteal(res_o); + DECREF_INPUTS(); } macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP; @@ -5267,10 +5266,12 @@ dummy_func( goto exit_unwind; } next_instr = frame->instr_ptr; - - LLTRACE_RESUME_FRAME(); - #ifdef Py_DEBUG + int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); + if (lltrace < 0) { + JUMP_TO_LABEL(exit_unwind); + } + frame->lltrace = lltrace; /* _PyEval_EvalFrameDefault() must not be called with an exception set, because it can clear it (directly or indirectly) and so the caller loses its exception */ diff --git a/Python/ceval.c b/Python/ceval.c index 1e4f1f3af20aca..931915c8cf780d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -135,6 +135,7 @@ static void dump_stack(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyStackRef *stack_base = _PyFrame_Stackbase(frame); PyObject *exc = PyErr_GetRaisedException(); printf(" stack=["); @@ -165,6 +166,7 @@ dump_stack(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer) printf("]\n"); fflush(stdout); PyErr_SetRaisedException(exc); + _PyFrame_GetStackPointer(frame); } static void @@ -764,6 +766,19 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch) #define PY_EVAL_C_STACK_UNITS 2 +/* _PyEval_EvalFrameDefault is too large to optimize for speed with PGO on MSVC. + */ +#if (defined(_MSC_VER) && \ + (_MSC_VER < 1943) && \ + defined(_Py_USING_PGO)) +#define DO_NOT_OPTIMIZE_INTERP_LOOP +#endif + +#ifdef DO_NOT_OPTIMIZE_INTERP_LOOP +# pragma optimize("t", off) +/* This setting is reversed below following _PyEval_EvalFrameDefault */ +#endif + #ifdef Py_TAIL_CALL_INTERP #include "opcode_targets.h" #include "generated_cases.c.h" @@ -786,6 +801,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int #ifndef Py_TAIL_CALL_INTERP uint8_t opcode; /* Current opcode */ int oparg; /* Current opcode argument, if any */ + assert(tstate->current_frame == NULL || tstate->current_frame->stackpointer != NULL); #endif _PyInterpreterFrame entry_frame; @@ -845,8 +861,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int /* Because this avoids the RESUME, we need to update instrumentation */ _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); next_instr = frame->instr_ptr; - stack_pointer = _PyFrame_GetStackPointer(frame); monitor_throw(tstate, frame, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); #ifdef Py_TAIL_CALL_INTERP return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr, 0); #else @@ -986,6 +1002,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int return NULL; } +#ifdef DO_NOT_OPTIMIZE_INTERP_LOOP +# pragma optimize("", on) +#endif + #if defined(__GNUC__) # pragma GCC diagnostic pop #elif defined(_MSC_VER) /* MS_WINDOWS */ @@ -1995,7 +2015,7 @@ _PyEval_ExceptionGroupMatch(_PyInterpreterFrame *frame, PyObject* exc_value, */ int -_PyEval_UnpackIterableStackRef(PyThreadState *tstate, _PyStackRef v_stackref, +_PyEval_UnpackIterableStackRef(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, _PyStackRef *sp) { int i = 0, j = 0; @@ -2003,8 +2023,6 @@ _PyEval_UnpackIterableStackRef(PyThreadState *tstate, _PyStackRef v_stackref, PyObject *it; /* iter(v) */ PyObject *w; PyObject *l = NULL; /* variable list */ - - PyObject *v = PyStackRef_AsPyObjectBorrow(v_stackref); assert(v != NULL); it = PyObject_GetIter(v); diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index 0a4f65feb3b512..2cb78fa80b4658 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -118,7 +118,9 @@ #ifdef Py_DEBUG #define LLTRACE_RESUME_FRAME() \ do { \ + _PyFrame_SetStackPointer(frame, stack_pointer); \ int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); \ + stack_pointer = _PyFrame_GetStackPointer(frame); \ if (lltrace < 0) { \ JUMP_TO_LABEL(exit_unwind); \ } \ @@ -395,7 +397,7 @@ do { \ stack_pointer = _PyFrame_GetStackPointer(frame); \ if (next_instr == NULL) { \ next_instr = frame->instr_ptr; \ - goto error; \ + JUMP_TO_LABEL(error); \ } \ DISPATCH(); \ } while (0) @@ -409,17 +411,21 @@ do { \ } while (0) #endif -#define GOTO_TIER_ONE(TARGET) \ -do { \ - next_instr = (TARGET); \ - OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); \ - Py_CLEAR(tstate->previous_executor); \ - if (next_instr == NULL) { \ - next_instr = frame->instr_ptr; \ - goto error; \ - } \ - DISPATCH(); \ -} while (0) +#define GOTO_TIER_ONE(TARGET) \ + do \ + { \ + next_instr = (TARGET); \ + OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); \ + _PyFrame_SetStackPointer(frame, stack_pointer); \ + Py_CLEAR(tstate->previous_executor); \ + stack_pointer = _PyFrame_GetStackPointer(frame); \ + if (next_instr == NULL) \ + { \ + next_instr = frame->instr_ptr; \ + goto error; \ + } \ + DISPATCH(); \ + } while (0) #define CURRENT_OPARG() (next_uop[-1].oparg) #define CURRENT_OPERAND0() (next_uop[-1].operand0) diff --git a/Python/clinic/context.c.h b/Python/clinic/context.c.h index 71f05aa02a51e7..0adde76d7c3cb1 100644 --- a/Python/clinic/context.c.h +++ b/Python/clinic/context.c.h @@ -179,4 +179,55 @@ PyDoc_STRVAR(_contextvars_ContextVar_reset__doc__, #define _CONTEXTVARS_CONTEXTVAR_RESET_METHODDEF \ {"reset", (PyCFunction)_contextvars_ContextVar_reset, METH_O, _contextvars_ContextVar_reset__doc__}, -/*[clinic end generated code: output=444567eaf0df25e0 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(token_enter__doc__, +"__enter__($self, /)\n" +"--\n" +"\n" +"Enter into Token context manager."); + +#define TOKEN_ENTER_METHODDEF \ + {"__enter__", (PyCFunction)token_enter, METH_NOARGS, token_enter__doc__}, + +static PyObject * +token_enter_impl(PyContextToken *self); + +static PyObject * +token_enter(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return token_enter_impl((PyContextToken *)self); +} + +PyDoc_STRVAR(token_exit__doc__, +"__exit__($self, type, val, tb, /)\n" +"--\n" +"\n" +"Exit from Token context manager, restore the linked ContextVar."); + +#define TOKEN_EXIT_METHODDEF \ + {"__exit__", _PyCFunction_CAST(token_exit), METH_FASTCALL, token_exit__doc__}, + +static PyObject * +token_exit_impl(PyContextToken *self, PyObject *type, PyObject *val, + PyObject *tb); + +static PyObject * +token_exit(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *type; + PyObject *val; + PyObject *tb; + + if (!_PyArg_CheckPositional("__exit__", nargs, 3, 3)) { + goto exit; + } + type = args[0]; + val = args[1]; + tb = args[2]; + return_value = token_exit_impl((PyContextToken *)self, type, val, tb); + +exit: + return return_value; +} +/*[clinic end generated code: output=01987cdbf68a951a input=a9049054013a1b77]*/ diff --git a/Python/codecs.c b/Python/codecs.c index 8c1ddbe879237c..a307a07a8d3406 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -1095,7 +1095,7 @@ PyObject *PyCodec_NameReplaceErrors(PyObject *exc) #define ENC_UTF32LE 4 static int -get_standard_encoding(const char *encoding, int *bytelength) +get_standard_encoding_impl(const char *encoding, int *bytelength) { if (Py_TOLOWER(encoding[0]) == 'u' && Py_TOLOWER(encoding[1]) == 't' && @@ -1153,165 +1153,204 @@ get_standard_encoding(const char *encoding, int *bytelength) return ENC_UNKNOWN; } -/* This handler is declared static until someone demonstrates - a need to call it directly. */ + +static int +get_standard_encoding(PyObject *encoding, int *code, int *bytelength) +{ + const char *encoding_cstr = PyUnicode_AsUTF8(encoding); + if (encoding_cstr == NULL) { + return -1; + } + *code = get_standard_encoding_impl(encoding_cstr, bytelength); + return 0; +} + + +// --- handler: 'surrogatepass' ----------------------------------------------- + static PyObject * -PyCodec_SurrogatePassErrors(PyObject *exc) +_PyCodec_SurrogatePassUnicodeEncodeError(PyObject *exc) { - PyObject *restuple; - PyObject *object; - PyObject *encode; - const char *encoding; - int code; - int bytelength; - Py_ssize_t i; - Py_ssize_t start; - Py_ssize_t end; - PyObject *res; + PyObject *encoding = PyUnicodeEncodeError_GetEncoding(exc); + if (encoding == NULL) { + return NULL; + } + int code, bytelength; + int rc = get_standard_encoding(encoding, &code, &bytelength); + Py_DECREF(encoding); + if (rc < 0) { + return NULL; + } + if (code == ENC_UNKNOWN) { + goto bail; + } - if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) { - unsigned char *outp; - if (PyUnicodeEncodeError_GetStart(exc, &start)) - return NULL; - if (PyUnicodeEncodeError_GetEnd(exc, &end)) - return NULL; - if (!(object = PyUnicodeEncodeError_GetObject(exc))) - return NULL; - if (!(encode = PyUnicodeEncodeError_GetEncoding(exc))) { - Py_DECREF(object); - return NULL; - } - if (!(encoding = PyUnicode_AsUTF8(encode))) { - Py_DECREF(object); - Py_DECREF(encode); - return NULL; - } - code = get_standard_encoding(encoding, &bytelength); - Py_DECREF(encode); - if (code == ENC_UNKNOWN) { - /* Not supported, fail with original exception */ - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - Py_DECREF(object); - return NULL; - } + PyObject *obj; + Py_ssize_t objlen, start, end, slen; + if (_PyUnicodeError_GetParams(exc, + &obj, &objlen, + &start, &end, &slen, false) < 0) + { + return NULL; + } - if (end - start > PY_SSIZE_T_MAX / bytelength) - end = start + PY_SSIZE_T_MAX / bytelength; - res = PyBytes_FromStringAndSize(NULL, bytelength*(end-start)); - if (!res) { - Py_DECREF(object); - return NULL; + if (slen > PY_SSIZE_T_MAX / bytelength) { + end = start + PY_SSIZE_T_MAX / bytelength; + end = Py_MIN(end, objlen); + slen = Py_MAX(0, end - start); + } + + PyObject *res = PyBytes_FromStringAndSize(NULL, bytelength * slen); + if (res == NULL) { + Py_DECREF(obj); + return NULL; + } + + unsigned char *outp = (unsigned char *)PyBytes_AsString(res); + for (Py_ssize_t i = start; i < end; i++) { + /* object is guaranteed to be "ready" */ + Py_UCS4 ch = PyUnicode_READ_CHAR(obj, i); + if (!Py_UNICODE_IS_SURROGATE(ch)) { + /* Not a surrogate, fail with original exception */ + Py_DECREF(obj); + Py_DECREF(res); + goto bail; } - outp = (unsigned char*)PyBytes_AsString(res); - for (i = start; i < end; i++) { - /* object is guaranteed to be "ready" */ - Py_UCS4 ch = PyUnicode_READ_CHAR(object, i); - if (!Py_UNICODE_IS_SURROGATE(ch)) { - /* Not a surrogate, fail with original exception */ - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - Py_DECREF(res); - Py_DECREF(object); - return NULL; - } - switch (code) { - case ENC_UTF8: + switch (code) { + case ENC_UTF8: { *outp++ = (unsigned char)(0xe0 | (ch >> 12)); *outp++ = (unsigned char)(0x80 | ((ch >> 6) & 0x3f)); *outp++ = (unsigned char)(0x80 | (ch & 0x3f)); break; - case ENC_UTF16LE: - *outp++ = (unsigned char) ch; + } + case ENC_UTF16LE: { + *outp++ = (unsigned char)ch; *outp++ = (unsigned char)(ch >> 8); break; - case ENC_UTF16BE: + } + case ENC_UTF16BE: { *outp++ = (unsigned char)(ch >> 8); - *outp++ = (unsigned char) ch; + *outp++ = (unsigned char)ch; break; - case ENC_UTF32LE: - *outp++ = (unsigned char) ch; + } + case ENC_UTF32LE: { + *outp++ = (unsigned char)ch; *outp++ = (unsigned char)(ch >> 8); *outp++ = (unsigned char)(ch >> 16); *outp++ = (unsigned char)(ch >> 24); break; - case ENC_UTF32BE: + } + case ENC_UTF32BE: { *outp++ = (unsigned char)(ch >> 24); *outp++ = (unsigned char)(ch >> 16); *outp++ = (unsigned char)(ch >> 8); - *outp++ = (unsigned char) ch; + *outp++ = (unsigned char)ch; break; } } - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - Py_DECREF(object); - return restuple; } - else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) { - const unsigned char *p; - Py_UCS4 ch = 0; - if (PyUnicodeDecodeError_GetStart(exc, &start)) - return NULL; - if (PyUnicodeDecodeError_GetEnd(exc, &end)) - return NULL; - if (!(object = PyUnicodeDecodeError_GetObject(exc))) - return NULL; - p = (const unsigned char*)PyBytes_AS_STRING(object); - if (!(encode = PyUnicodeDecodeError_GetEncoding(exc))) { - Py_DECREF(object); - return NULL; - } - if (!(encoding = PyUnicode_AsUTF8(encode))) { - Py_DECREF(object); - Py_DECREF(encode); - return NULL; - } - code = get_standard_encoding(encoding, &bytelength); - Py_DECREF(encode); - if (code == ENC_UNKNOWN) { - /* Not supported, fail with original exception */ - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - Py_DECREF(object); - return NULL; - } - /* Try decoding a single surrogate character. If - there are more, let the codec call us again. */ - p += start; - if (PyBytes_GET_SIZE(object) - start >= bytelength) { - switch (code) { - case ENC_UTF8: + Py_DECREF(obj); + PyObject *restuple = Py_BuildValue("(Nn)", res, end); + return restuple; + +bail: + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); + return NULL; +} + + +static PyObject * +_PyCodec_SurrogatePassUnicodeDecodeError(PyObject *exc) +{ + PyObject *encoding = PyUnicodeDecodeError_GetEncoding(exc); + if (encoding == NULL) { + return NULL; + } + int code, bytelength; + int rc = get_standard_encoding(encoding, &code, &bytelength); + Py_DECREF(encoding); + if (rc < 0) { + return NULL; + } + if (code == ENC_UNKNOWN) { + goto bail; + } + + PyObject *obj; + Py_ssize_t objlen, start, end, slen; + if (_PyUnicodeError_GetParams(exc, + &obj, &objlen, + &start, &end, &slen, true) < 0) + { + return NULL; + } + + /* Try decoding a single surrogate character. If + there are more, let the codec call us again. */ + Py_UCS4 ch = 0; + const unsigned char *p = (const unsigned char *)PyBytes_AS_STRING(obj); + p += start; + + if (objlen - start >= bytelength) { + switch (code) { + case ENC_UTF8: { if ((p[0] & 0xf0) == 0xe0 && (p[1] & 0xc0) == 0x80 && - (p[2] & 0xc0) == 0x80) { + (p[2] & 0xc0) == 0x80) + { /* it's a three-byte code */ - ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); + ch = ((p[0] & 0x0f) << 12) + + ((p[1] & 0x3f) << 6) + + (p[2] & 0x3f); } break; - case ENC_UTF16LE: + } + case ENC_UTF16LE: { ch = p[1] << 8 | p[0]; break; - case ENC_UTF16BE: + } + case ENC_UTF16BE: { ch = p[0] << 8 | p[1]; break; - case ENC_UTF32LE: + } + case ENC_UTF32LE: { ch = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; break; - case ENC_UTF32BE: + } + case ENC_UTF32BE: { ch = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; break; } } + } + Py_DECREF(obj); + if (!Py_UNICODE_IS_SURROGATE(ch)) { + goto bail; + } - Py_DECREF(object); - if (!Py_UNICODE_IS_SURROGATE(ch)) { - /* it's not a surrogate - fail */ - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - return NULL; - } - res = PyUnicode_FromOrdinal(ch); - if (res == NULL) - return NULL; - return Py_BuildValue("(Nn)", res, start + bytelength); + PyObject *res = PyUnicode_FromOrdinal(ch); + if (res == NULL) { + return NULL; + } + return Py_BuildValue("(Nn)", res, start + bytelength); + +bail: + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); + return NULL; +} + + +/* This handler is declared static until someone demonstrates + a need to call it directly. */ +static PyObject * +PyCodec_SurrogatePassErrors(PyObject *exc) +{ + if (_PyIsUnicodeEncodeError(exc)) { + return _PyCodec_SurrogatePassUnicodeEncodeError(exc); + } + else if (_PyIsUnicodeDecodeError(exc)) { + return _PyCodec_SurrogatePassUnicodeDecodeError(exc); } else { wrong_exception_type(exc); @@ -1454,7 +1493,8 @@ namereplace_errors(PyObject *Py_UNUSED(self), PyObject *exc) } -static PyObject *surrogatepass_errors(PyObject *self, PyObject *exc) +static inline PyObject * +surrogatepass_errors(PyObject *Py_UNUSED(self), PyObject *exc) { return PyCodec_SurrogatePassErrors(exc); } diff --git a/Python/context.c b/Python/context.c index bb1aa42b9c5e4f..dfdde7d1fa723f 100644 --- a/Python/context.c +++ b/Python/context.c @@ -1231,9 +1231,47 @@ static PyGetSetDef PyContextTokenType_getsetlist[] = { {NULL} }; +/*[clinic input] +_contextvars.Token.__enter__ as token_enter + +Enter into Token context manager. +[clinic start generated code]*/ + +static PyObject * +token_enter_impl(PyContextToken *self) +/*[clinic end generated code: output=9af4d2054e93fb75 input=41a3d6c4195fd47a]*/ +{ + return Py_NewRef(self); +} + +/*[clinic input] +_contextvars.Token.__exit__ as token_exit + + type: object + val: object + tb: object + / + +Exit from Token context manager, restore the linked ContextVar. +[clinic start generated code]*/ + +static PyObject * +token_exit_impl(PyContextToken *self, PyObject *type, PyObject *val, + PyObject *tb) +/*[clinic end generated code: output=3e6a1c95d3da703a input=7f117445f0ccd92e]*/ +{ + int ret = PyContextVar_Reset((PyObject *)self->tok_var, (PyObject *)self); + if (ret < 0) { + return NULL; + } + Py_RETURN_NONE; +} + static PyMethodDef PyContextTokenType_methods[] = { {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, + TOKEN_ENTER_METHODDEF + TOKEN_EXIT_METHODDEF {NULL} }; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 96b7386bd24846..5962e0ebd4f493 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -438,9 +438,11 @@ case _POP_TOP: { _PyStackRef value; value = stack_pointer[-1]; - PyStackRef_CLOSE(value); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); break; } @@ -477,10 +479,12 @@ receiver = stack_pointer[-2]; (void)receiver; val = value; - PyStackRef_CLOSE(receiver); stack_pointer[-2] = val; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(receiver); + stack_pointer = _PyFrame_GetStackPointer(frame); break; } @@ -491,14 +495,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Negative(PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -520,14 +528,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = err ? PyStackRef_True : PyStackRef_False; - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -557,8 +569,14 @@ res = PyStackRef_False; } else { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); res = PyStackRef_True; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } stack_pointer[-1] = res; break; @@ -575,7 +593,12 @@ } STAT_INC(TO_BOOL, hit); res = PyList_GET_SIZE(value_o) ? PyStackRef_True : PyStackRef_False; - PyStackRef_CLOSE(value); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = value; + value = res; + stack_pointer[-1] = value; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-1] = res; break; } @@ -611,8 +634,14 @@ } else { assert(Py_SIZE(value_o)); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); res = PyStackRef_True; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } stack_pointer[-1] = res; break; @@ -622,9 +651,15 @@ _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); res = PyStackRef_True; - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -635,14 +670,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Invert(PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -697,7 +736,9 @@ assert(PyLong_CheckExact(left_o)); assert(PyLong_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyLong_Multiply((PyLongObject *)left_o, (PyLongObject *)right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); if (res_o == NULL) { @@ -723,7 +764,9 @@ assert(PyLong_CheckExact(left_o)); assert(PyLong_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyLong_Add((PyLongObject *)left_o, (PyLongObject *)right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); if (res_o == NULL) { @@ -749,7 +792,9 @@ assert(PyLong_CheckExact(left_o)); assert(PyLong_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyLong_Subtract((PyLongObject *)left_o, (PyLongObject *)right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); if (res_o == NULL) { @@ -935,7 +980,7 @@ right = stack_pointer[-1]; left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); - PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + PyObject *right_o = PyStackRef_AsPyObjectSteal(right); assert(PyUnicode_CheckExact(left_o)); assert(PyUnicode_CheckExact(right_o)); int next_oparg; @@ -965,12 +1010,16 @@ assert(Py_REFCNT(left_o) >= 2); PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyUnicode_Append(&temp, right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); *target_local = PyStackRef_FromPyObjectSteal(temp); - PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc); + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (PyStackRef_IsNull(*target_local)) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } #if TIER_ONE @@ -979,8 +1028,6 @@ assert(next_instr->op.code == STORE_FAST); SKIP_OVER(1); #endif - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -1019,12 +1066,20 @@ STAT_INC(BINARY_OP, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = d->action(left_o, right_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1099,15 +1154,23 @@ stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); } - PyStackRef_CLOSE(v); - PyStackRef_CLOSE(container); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = container; + container = PyStackRef_NULL; + stack_pointer[-1] = container; + PyStackRef_CLOSE(tmp); + tmp = v; + v = PyStackRef_NULL; + stack_pointer[-2] = v; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (err) { - stack_pointer += -4; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -4; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -1276,17 +1339,25 @@ _PyErr_SetKeyError(sub); stack_pointer = _PyFrame_GetStackPointer(frame); } - PyStackRef_CLOSE(dict_st); - PyStackRef_CLOSE(sub_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = sub_st; + sub_st = PyStackRef_NULL; + stack_pointer[-1] = sub_st; + PyStackRef_CLOSE(tmp); + tmp = dict_st; + dict_st = PyStackRef_NULL; + stack_pointer[-2] = dict_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (rc <= 0) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } // not found or error res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1372,14 +1443,14 @@ int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -1393,17 +1464,24 @@ /* container[sub] = v */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v)); + _PyStackRef tmp = sub; + sub = PyStackRef_NULL; + stack_pointer[-1] = sub; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-2] = container; + PyStackRef_CLOSE(tmp); + tmp = v; + v = PyStackRef_NULL; + stack_pointer[-3] = v; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(v); - PyStackRef_CLOSE(container); - PyStackRef_CLOSE(sub); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (err) { - stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -1495,16 +1573,20 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub)); + _PyStackRef tmp = sub; + sub = PyStackRef_NULL; + stack_pointer[-1] = sub; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-2] = container; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(container); - PyStackRef_CLOSE(sub); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (err) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -1517,14 +1599,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -1540,17 +1626,23 @@ PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); + _PyStackRef tmp = value1_st; + value1_st = PyStackRef_NULL; + stack_pointer[-1] = value1_st; + PyStackRef_CLOSE(tmp); + tmp = value2_st; + value2_st = PyStackRef_NULL; + stack_pointer[-2] = value2_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(value2_st); - PyStackRef_CLOSE(value1_st); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1598,24 +1690,26 @@ "__aiter__ method, got %.100s", type->tp_name); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(obj); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(obj); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } _PyFrame_SetStackPointer(frame, stack_pointer); iter_o = (*getter)(obj_o); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(obj); + stack_pointer = _PyFrame_GetStackPointer(frame); if (iter_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } if (Py_TYPE(iter_o)->tp_as_async == NULL || Py_TYPE(iter_o)->tp_as_async->am_anext == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'async for' received an object from __aiter__ " @@ -1626,7 +1720,9 @@ JUMP_TO_ERROR(); } iter = PyStackRef_FromPyObjectSteal(iter_o); - stack_pointer[-1] = iter; + stack_pointer[0] = iter; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -1655,14 +1751,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = _PyEval_GetAwaitable(PyStackRef_AsPyObjectBorrow(iterable), oparg); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (iter_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } iter = PyStackRef_FromPyObjectSteal(iter_o); - stack_pointer[-1] = iter; + stack_pointer[0] = iter; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -1810,9 +1910,11 @@ _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(v); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } if (PyDict_CheckExact(ns)) { @@ -1825,14 +1927,14 @@ err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -1865,21 +1967,21 @@ case _UNPACK_SEQUENCE: { _PyStackRef seq; - _PyStackRef *output; + _PyStackRef *top; oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; - output = &stack_pointer[-1]; - _PyStackRef *top = output + oparg; + top = &stack_pointer[-1 + oparg]; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg, -1, top); + int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg, -1, top); + Py_DECREF(seq_o); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(seq); if (res == 0) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -1 + oparg; + stack_pointer += oparg; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1903,11 +2005,13 @@ STAT_INC(UNPACK_SEQUENCE, hit); val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0)); val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1)); - PyStackRef_CLOSE(seq); stack_pointer[-1] = val1; stack_pointer[0] = val0; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(seq); + stack_pointer = _PyFrame_GetStackPointer(frame); break; } @@ -1931,8 +2035,12 @@ for (int i = oparg; --i >= 0; ) { *values++ = PyStackRef_FromPyObjectNew(items[i]); } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(seq); - stack_pointer += -1 + oparg; + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += oparg; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1965,29 +2073,33 @@ *values++ = PyStackRef_FromPyObjectNew(items[i]); } UNLOCK_OBJECT(seq_o); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(seq); - stack_pointer += -1 + oparg; + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += oparg; assert(WITHIN_STACK_BOUNDS()); break; } case _UNPACK_EX: { _PyStackRef seq; - _PyStackRef *right; + _PyStackRef *top; oparg = CURRENT_OPARG(); seq = stack_pointer[-1]; - right = &stack_pointer[(oparg & 0xFF)]; - _PyStackRef *top = right + (oparg >> 8); + top = &stack_pointer[(oparg & 0xFF) + (oparg >> 8)]; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg & 0xFF, oparg >> 8, top); + int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg & 0xFF, oparg >> 8, top); + Py_DECREF(seq_o); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(seq); if (res == 0) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += (oparg & 0xFF) + (oparg >> 8); + stack_pointer += 1 + (oparg & 0xFF) + (oparg >> 8); assert(WITHIN_STACK_BOUNDS()); break; } @@ -2002,16 +2114,20 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetAttr(PyStackRef_AsPyObjectBorrow(owner), name, PyStackRef_AsPyObjectBorrow(v)); + _PyStackRef tmp = owner; + owner = PyStackRef_NULL; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + tmp = v; + v = PyStackRef_NULL; + stack_pointer[-2] = v; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(v); - PyStackRef_CLOSE(owner); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (err) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -2023,14 +2139,14 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelAttr(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -2042,14 +2158,14 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_SetItem(GLOBALS(), name, PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -2401,26 +2517,36 @@ pieces = &stack_pointer[-oparg]; STACKREFS_TO_PYOBJECTS(pieces, oparg, pieces_o); if (CONVERSION_FAILED(pieces_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(pieces[_i]); + tmp = pieces[_i]; + pieces[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } PyObject *str_o = _PyUnicode_JoinArray(&_Py_STR(empty), pieces_o, oparg); STACKREFS_TO_PYOBJECTS_CLEANUP(pieces_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(pieces[_i]); + tmp = pieces[_i]; + pieces[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg; + assert(WITHIN_STACK_BOUNDS()); if (str_o == NULL) { - stack_pointer += -oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } str = PyStackRef_FromPyObjectSteal(str_o); - stack_pointer[-oparg] = str; - stack_pointer += 1 - oparg; + stack_pointer[0] = str; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -2482,15 +2608,19 @@ Py_TYPE(iterable)->tp_name); stack_pointer = _PyFrame_GetStackPointer(frame); } - PyStackRef_CLOSE(iterable_st); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable_st); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } assert(Py_IsNone(none_val)); - PyStackRef_CLOSE(iterable_st); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable_st); + stack_pointer = _PyFrame_GetStackPointer(frame); break; } @@ -2504,14 +2634,14 @@ int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -2524,9 +2654,14 @@ PyObject *set_o = PySet_New(NULL); stack_pointer = _PyFrame_GetStackPointer(frame); if (set_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -2539,20 +2674,25 @@ stack_pointer = _PyFrame_GetStackPointer(frame); } } + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg; + assert(WITHIN_STACK_BOUNDS()); if (err != 0) { - stack_pointer += -oparg; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); Py_DECREF(set_o); stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } set = PyStackRef_FromPyObjectSteal(set_o); - stack_pointer[-oparg] = set; - stack_pointer += 1 - oparg; + stack_pointer[0] = set; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -2564,9 +2704,14 @@ values = &stack_pointer[-oparg*2]; STACKREFS_TO_PYOBJECTS(values, oparg*2, values_o); if (CONVERSION_FAILED(values_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg*2; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -oparg*2; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -2578,17 +2723,22 @@ oparg); stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(values_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg*2; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg*2; + assert(WITHIN_STACK_BOUNDS()); if (map_o == NULL) { - stack_pointer += -oparg*2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } map = PyStackRef_FromPyObjectSteal(map_o); - stack_pointer[-oparg*2] = map; - stack_pointer += 1 - oparg*2; + stack_pointer[0] = map; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -2655,14 +2805,18 @@ Py_TYPE(update_o)->tp_name); stack_pointer = _PyFrame_GetStackPointer(frame); } - PyStackRef_CLOSE(update); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(update); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } - PyStackRef_CLOSE(update); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(update); + stack_pointer = _PyFrame_GetStackPointer(frame); break; } @@ -2684,14 +2838,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatKwargsError(tstate, callable_o, update_o); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(update); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(update); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } - PyStackRef_CLOSE(update); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(update); + stack_pointer = _PyFrame_GetStackPointer(frame); break; } @@ -2749,18 +2907,27 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + _PyStackRef tmp = self_st; + self_st = PyStackRef_NULL; + stack_pointer[-1] = self_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-2] = class_st; + PyStackRef_CLOSE(tmp); + tmp = global_super_st; + global_super_st = PyStackRef_NULL; + stack_pointer[-3] = global_super_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(global_super_st); - PyStackRef_CLOSE(class_st); - PyStackRef_CLOSE(self_st); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (attr == NULL) { - stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } attr_st = PyStackRef_FromPyObjectSteal(attr); - stack_pointer[-3] = attr_st; - stack_pointer += -2; + stack_pointer[0] = attr_st; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -2810,13 +2977,26 @@ stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); } - PyStackRef_CLOSE(global_super_st); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = global_super_st; + global_super_st = self_or_null; + stack_pointer[-2] = global_super_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(class_st); - attr = PyStackRef_FromPyObjectSteal(attr_o); - stack_pointer[-3] = attr; - stack_pointer[-2] = self_or_null; + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + attr = PyStackRef_FromPyObjectSteal(attr_o); + stack_pointer[0] = attr; + stack_pointer[1] = self_or_null; + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -2850,13 +3030,17 @@ CALL that it's not a method call. meth | NULL | arg1 | ... | argN */ + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); if (attr_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } self_or_null[0] = PyStackRef_NULL; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } } else { @@ -2864,12 +3048,16 @@ _PyFrame_SetStackPointer(frame, stack_pointer); attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); if (attr_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } attr = PyStackRef_FromPyObjectSteal(attr_o); stack_pointer[-1] = attr; @@ -3095,10 +3283,15 @@ STAT_INC(LOAD_ATTR, hit); attr = PyStackRef_FromPyObjectNew(attr_o); UNLOCK_OBJECT(dict); - PyStackRef_CLOSE(owner); - stack_pointer[-2] = attr; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = attr; break; } @@ -3124,7 +3317,12 @@ attr = PyStackRef_FromPyObjectNew(attr_o); #endif STAT_INC(LOAD_ATTR, hit); - PyStackRef_CLOSE(owner); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-1] = attr; break; } @@ -3154,7 +3352,12 @@ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); attr = PyStackRef_FromPyObjectNew(descr); - PyStackRef_CLOSE(owner); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-1] = attr; break; } @@ -3345,17 +3548,21 @@ assert((oparg >> 5) <= Py_GE); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_RichCompare(left_o, right_o, oparg >> 5); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } if (oparg & 16) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int res_bool = PyObject_IsTrue(res_o); Py_DECREF(res_o); @@ -3367,8 +3574,6 @@ } else { res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); } stack_pointer[0] = res; stack_pointer += 1; @@ -3467,11 +3672,21 @@ right = stack_pointer[-1]; left = stack_pointer[-2]; int res = Py_Is(PyStackRef_AsPyObjectBorrow(left), PyStackRef_AsPyObjectBorrow(right)) ^ oparg; - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); b = res ? PyStackRef_True : PyStackRef_False; - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -3487,17 +3702,23 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyFrame_SetStackPointer(frame, stack_pointer); int res = PySequence_Contains(right_o, left_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -3519,17 +3740,23 @@ // Note: both set and frozenset use the same seq_contains method! _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PySet_Contains((PySetObject *)right_o, left_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -3550,17 +3777,23 @@ STAT_INC(CONTAINS_OP, hit); _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyDict_Contains(right_o, left_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -3578,8 +3811,16 @@ int err = _PyEval_CheckExceptStarTypeValid(tstate, match_type); stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - PyStackRef_CLOSE(exc_value_st); - PyStackRef_CLOSE(match_type_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = match_type_st; + match_type_st = PyStackRef_NULL; + stack_pointer[-1] = match_type_st; + PyStackRef_CLOSE(tmp); + tmp = exc_value_st; + exc_value_st = PyStackRef_NULL; + stack_pointer[-2] = exc_value_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -3589,33 +3830,35 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_ExceptionGroupMatch(frame, exc_value, match_type, &match_o, &rest_o); + _PyStackRef tmp = match_type_st; + match_type_st = PyStackRef_NULL; + stack_pointer[-1] = match_type_st; + PyStackRef_CLOSE(tmp); + tmp = exc_value_st; + exc_value_st = PyStackRef_NULL; + stack_pointer[-2] = exc_value_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(exc_value_st); - PyStackRef_CLOSE(match_type_st); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } assert((match_o == NULL) == (rest_o == NULL)); if (match_o == NULL) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } if (!Py_IsNone(match_o)) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); PyErr_SetHandledException(match_o); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; - assert(WITHIN_STACK_BOUNDS()); } rest = PyStackRef_FromPyObjectSteal(rest_o); match = PyStackRef_FromPyObjectSteal(match_o); - stack_pointer[-2] = rest; - stack_pointer[-1] = match; + stack_pointer[0] = rest; + stack_pointer[1] = match; + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -3632,17 +3875,20 @@ int err = _PyEval_CheckExceptTypeValid(tstate, right_o); stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - PyStackRef_CLOSE(right); - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyErr_GivenExceptionMatches(left_o, right_o); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(right); + stack_pointer = _PyFrame_GetStackPointer(frame); b = res ? PyStackRef_True : PyStackRef_False; - stack_pointer[-1] = b; + stack_pointer[0] = b; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -3658,17 +3904,23 @@ PyObject *res_o = _PyEval_ImportName(tstate, frame, name, PyStackRef_AsPyObjectBorrow(fromlist), PyStackRef_AsPyObjectBorrow(level)); + _PyStackRef tmp = fromlist; + fromlist = PyStackRef_NULL; + stack_pointer[-1] = fromlist; + PyStackRef_CLOSE(tmp); + tmp = level; + level = PyStackRef_NULL; + stack_pointer[-2] = level; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(level); - PyStackRef_CLOSE(fromlist); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -3705,7 +3957,13 @@ } else { b = PyStackRef_False; - PyStackRef_CLOSE(value); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = value; + value = b; + stack_pointer[-1] = value; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = b; } stack_pointer[-1] = b; break; @@ -3750,25 +4008,34 @@ PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); + _PyStackRef tmp = names; + names = PyStackRef_NULL; + stack_pointer[-1] = names; + PyStackRef_CLOSE(tmp); + tmp = type; + type = PyStackRef_NULL; + stack_pointer[-2] = type; + PyStackRef_CLOSE(tmp); + tmp = subject; + subject = PyStackRef_NULL; + stack_pointer[-3] = subject; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(subject); - PyStackRef_CLOSE(type); - PyStackRef_CLOSE(names); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (attrs_o) { assert(PyTuple_CheckExact(attrs_o)); // Success! attrs = PyStackRef_FromPyObjectSteal(attrs_o); } else { if (_PyErr_Occurred(tstate)) { - stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } // Error! attrs = PyStackRef_None; // Failure! } - stack_pointer[-3] = attrs; - stack_pointer += -2; + stack_pointer[0] = attrs; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -3826,14 +4093,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (iter_o == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } iter = PyStackRef_FromPyObjectSteal(iter_o); - stack_pointer[-1] = iter; + stack_pointer[0] = iter; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -3870,7 +4141,13 @@ JUMP_TO_ERROR(); } iter = PyStackRef_FromPyObjectSteal(iter_o); - PyStackRef_CLOSE(iterable); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = iterable; + iterable = iter; + stack_pointer[-1] = iterable; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = iter; } } stack_pointer[-1] = iter; @@ -4276,9 +4553,15 @@ assert((oparg & 1) == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; + stack_pointer[0] = attr; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -4292,9 +4575,15 @@ assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; + stack_pointer[0] = attr; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); break; } @@ -4517,11 +4806,20 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -4534,19 +4832,28 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -4980,7 +5287,9 @@ stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FrameClearAndPop(tstate, shim); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } init_frame = temp; @@ -5040,11 +5349,20 @@ STAT_INC(CALL, hit); STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -5053,19 +5371,28 @@ PyObject *res_o = tp->tp_vectorcall((PyObject *)tp, args_o, total_args, NULL); stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -5160,11 +5487,20 @@ /* res = func(self, args, nargs) */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -5177,19 +5513,28 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -5228,11 +5573,20 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -5242,19 +5596,28 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -5350,11 +5713,19 @@ } res = retval ? PyStackRef_True : PyStackRef_False; assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = callable[0]; + callable[0] = res; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -5463,19 +5834,28 @@ stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -5516,11 +5896,20 @@ int nargs = total_args - 1; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -5532,19 +5921,28 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -5652,11 +6050,20 @@ int nargs = total_args - 1; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -5668,19 +6075,28 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -5876,12 +6292,23 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = kwnames; + kwnames = PyStackRef_NULL; + stack_pointer[-1] = kwnames; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } - PyStackRef_CLOSE(kwnames); + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -3 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); @@ -5901,19 +6328,28 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -6051,17 +6487,22 @@ PyObject *stop_o = PyStackRef_AsPyObjectBorrow(args[1]); PyObject *step_o = oparg == 3 ? PyStackRef_AsPyObjectBorrow(args[2]) : NULL; PyObject *slice_o = PySlice_New(start_o, stop_o, step_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg; + assert(WITHIN_STACK_BOUNDS()); if (slice_o == NULL) { - stack_pointer += -oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } slice = PyStackRef_FromPyObjectSteal(slice_o); - stack_pointer[-oparg] = slice; - stack_pointer += 1 - oparg; + stack_pointer[0] = slice; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -6132,17 +6573,23 @@ value = stack_pointer[-2]; _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Format(PyStackRef_AsPyObjectBorrow(value), PyStackRef_AsPyObjectBorrow(fmt_spec)); + _PyStackRef tmp = fmt_spec; + fmt_spec = PyStackRef_NULL; + stack_pointer[-1] = fmt_spec; + PyStackRef_CLOSE(tmp); + tmp = value; + value = PyStackRef_NULL; + stack_pointer[-2] = value; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(value); - PyStackRef_CLOSE(fmt_spec); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -6173,17 +6620,22 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_BinaryOps[oparg](lhs_o, rhs_o); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(lhs); - PyStackRef_CLOSE(rhs); if (res_o == NULL) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_ERROR(); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = lhs; + lhs = res; + stack_pointer[-2] = lhs; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(rhs); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = res; break; } @@ -6480,7 +6932,12 @@ STAT_INC(LOAD_ATTR, hit); Py_INCREF(attr_o); attr = PyStackRef_FromPyObjectSteal(attr_o); - PyStackRef_CLOSE(owner); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-1] = attr; break; } diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 308cdac3c44608..38fb40831f3735 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -126,6 +126,12 @@ is_jump(cfg_instr *i) _instr__ptr_->i_oparg = 0; \ } while (0); +#define INSTR_SET_LOC(I, LOC) \ + do { \ + cfg_instr *_instr__ptr_ = (I); \ + _instr__ptr_->i_loc = (LOC); \ + } while (0); + /***** Blocks *****/ /* Returns the offset of the next instruction in the current block's @@ -1382,7 +1388,7 @@ get_constant_sequence(basicblock *bb, int start, int size, /* Walk basic block backwards starting from "start" and change "count" number of - non-NOP instructions to NOP's. + non-NOP instructions to NOP's and set their location to NO_LOCATION. */ static void nop_out(basicblock *bb, int start, int count) @@ -1390,10 +1396,12 @@ nop_out(basicblock *bb, int start, int count) assert(start < bb->b_iused); for (; count > 0; start--) { assert(start >= 0); - if (bb->b_instr[start].i_opcode == NOP) { + cfg_instr *instr = &bb->b_instr[start]; + if (instr->i_opcode == NOP) { continue; } - INSTR_SET_OP0(&bb->b_instr[start], NOP); + INSTR_SET_OP0(instr, NOP); + INSTR_SET_LOC(instr, NO_LOCATION); count--; } } @@ -1423,36 +1431,46 @@ fold_tuple_of_constants(basicblock *bb, int n, PyObject *consts, PyObject *const int index = add_const(newconst, consts, const_cache); RETURN_IF_ERROR(index); nop_out(bb, n-1, seq_size); - INSTR_SET_OP1(&bb->b_instr[n], LOAD_CONST, index); + INSTR_SET_OP1(instr, LOAD_CONST, index); return SUCCESS; } #define MIN_CONST_SEQUENCE_SIZE 3 -/* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cN, BUILD_LIST N - with BUILD_LIST 0, LOAD_CONST (c1, c2, ... cN), LIST_EXTEND 1, - or BUILD_SET & SET_UPDATE respectively. +/* +Optimize lists and sets for: + 1. "for" loop, comprehension or "in"/"not in" tests: + Change literal list or set of constants into constant + tuple or frozenset respectively. Change list of + non-constants into tuple. + 2. Constant literal lists/set with length >= MIN_CONST_SEQUENCE_SIZE: + Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cN, BUILD_LIST N + with BUILD_LIST 0, LOAD_CONST (c1, c2, ... cN), LIST_EXTEND 1, + or BUILD_SET & SET_UPDATE respectively. */ static int -optimize_if_const_list_or_set(basicblock *bb, int n, PyObject *consts, PyObject *const_cache) +optimize_lists_and_sets(basicblock *bb, int i, int nextop, + PyObject *consts, PyObject *const_cache) { assert(PyDict_CheckExact(const_cache)); assert(PyList_CheckExact(consts)); - cfg_instr *instr = &bb->b_instr[n]; + cfg_instr *instr = &bb->b_instr[i]; assert(instr->i_opcode == BUILD_LIST || instr->i_opcode == BUILD_SET); + bool contains_or_iter = nextop == GET_ITER || nextop == CONTAINS_OP; int seq_size = instr->i_oparg; - if (seq_size < MIN_CONST_SEQUENCE_SIZE) { + if (seq_size < MIN_CONST_SEQUENCE_SIZE && !contains_or_iter) { return SUCCESS; } PyObject *newconst; - RETURN_IF_ERROR(get_constant_sequence(bb, n-1, seq_size, consts, &newconst)); - if (newconst == NULL) { - /* not a const sequence */ + RETURN_IF_ERROR(get_constant_sequence(bb, i-1, seq_size, consts, &newconst)); + if (newconst == NULL) { /* not a const sequence */ + if (contains_or_iter && instr->i_opcode == BUILD_LIST) { + /* iterate over a tuple instead of list */ + INSTR_SET_OP1(instr, BUILD_TUPLE, instr->i_oparg); + } return SUCCESS; } assert(PyTuple_CheckExact(newconst) && PyTuple_GET_SIZE(newconst) == seq_size); - int build = instr->i_opcode; - int extend = build == BUILD_LIST ? LIST_EXTEND : SET_UPDATE; - if (build == BUILD_SET) { + if (instr->i_opcode == BUILD_SET) { PyObject *frozenset = PyFrozenSet_New(newconst); if (frozenset == NULL) { Py_DECREF(newconst); @@ -1462,39 +1480,21 @@ optimize_if_const_list_or_set(basicblock *bb, int n, PyObject *consts, PyObject } int index = add_const(newconst, consts, const_cache); RETURN_IF_ERROR(index); - nop_out(bb, n-1, seq_size); - assert(n >= 2); - INSTR_SET_OP1(&bb->b_instr[n-2], build, 0); - INSTR_SET_OP1(&bb->b_instr[n-1], LOAD_CONST, index); - INSTR_SET_OP1(&bb->b_instr[n], extend, 1); - return SUCCESS; -} + nop_out(bb, i-1, seq_size); + if (contains_or_iter) { + INSTR_SET_OP1(instr, LOAD_CONST, index); + } + else { + assert(i >= 2); + assert(instr->i_opcode == BUILD_LIST || instr->i_opcode == BUILD_SET); -/* - Walk basic block backwards starting from "start" to collect instruction pair - that loads consts skipping NOP's in between. -*/ -static bool -find_load_const_pair(basicblock *bb, int start, cfg_instr **first, cfg_instr **second) -{ - cfg_instr *second_load_const = NULL; - while (start >= 0) { - cfg_instr *inst = &bb->b_instr[start--]; - if (inst->i_opcode == NOP) { - continue; - } - if (!loads_const(inst->i_opcode)) { - return false; - } - if (second_load_const == NULL) { - second_load_const = inst; - continue; - } - *first = inst; - *second = second_load_const; - return true; + INSTR_SET_LOC(&bb->b_instr[i-2], instr->i_loc); + + INSTR_SET_OP1(&bb->b_instr[i-2], instr->i_opcode, 0); + INSTR_SET_OP1(&bb->b_instr[i-1], LOAD_CONST, index); + INSTR_SET_OP1(&bb->b_instr[i], instr->i_opcode == BUILD_LIST ? LIST_EXTEND : SET_UPDATE, 1); } - return false; + return SUCCESS; } /* Determine opcode & oparg for freshly folded constant. */ @@ -1518,27 +1518,25 @@ newop_from_folded(PyObject *newconst, PyObject *consts, } static int -optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_cache) +optimize_if_const_binop(basicblock *bb, int i, PyObject *consts, PyObject *const_cache) { - cfg_instr *subscr = &bb->b_instr[n]; - assert(subscr->i_opcode == BINARY_OP); - if (subscr->i_oparg != NB_SUBSCR) { + cfg_instr *binop = &bb->b_instr[i]; + assert(binop->i_opcode == BINARY_OP); + if (binop->i_oparg != NB_SUBSCR) { /* TODO: support other binary ops */ return SUCCESS; } - cfg_instr *arg, *idx; - if (!find_load_const_pair(bb, n-1, &arg, &idx)) { + PyObject *pair; + RETURN_IF_ERROR(get_constant_sequence(bb, i-1, 2, consts, &pair)); + if (pair == NULL) { return SUCCESS; } - PyObject *o = NULL, *key = NULL; - if ((o = get_const_value(arg->i_opcode, arg->i_oparg, consts)) == NULL - || (key = get_const_value(idx->i_opcode, idx->i_oparg, consts)) == NULL) - { - goto error; - } - PyObject *newconst = PyObject_GetItem(o, key); - Py_DECREF(o); - Py_DECREF(key); + assert(PyTuple_CheckExact(pair) && PyTuple_Size(pair) == 2); + PyObject *left = PyTuple_GET_ITEM(pair, 0); + PyObject *right = PyTuple_GET_ITEM(pair, 1); + assert(left != NULL && right != NULL); + PyObject *newconst = PyObject_GetItem(left, right); + Py_DECREF(pair); if (newconst == NULL) { if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { return ERROR; @@ -1548,14 +1546,9 @@ optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_ca } int newopcode, newoparg; RETURN_IF_ERROR(newop_from_folded(newconst, consts, const_cache, &newopcode, &newoparg)); - INSTR_SET_OP1(subscr, newopcode, newoparg); - INSTR_SET_OP0(arg, NOP); - INSTR_SET_OP0(idx, NOP); + nop_out(bb, i-1, 2); + INSTR_SET_OP1(binop, newopcode, newoparg); return SUCCESS; -error: - Py_XDECREF(o); - Py_XDECREF(key); - return ERROR; } #define VISITED (-1) @@ -1923,7 +1916,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) break; case BUILD_LIST: case BUILD_SET: - RETURN_IF_ERROR(optimize_if_const_list_or_set(bb, i, consts, const_cache)); + RETURN_IF_ERROR(optimize_lists_and_sets(bb, i, nextop, consts, const_cache)); break; case POP_JUMP_IF_NOT_NONE: case POP_JUMP_IF_NONE: @@ -2056,7 +2049,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts) } break; case BINARY_OP: - RETURN_IF_ERROR(optimize_if_const_op(bb, i, consts, const_cache)); + RETURN_IF_ERROR(optimize_if_const_binop(bb, i, consts, const_cache)); break; } } diff --git a/Python/gc.c b/Python/gc.c index 0fb2f03b0406ad..7faf368f35898a 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -1996,6 +1996,7 @@ Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason) { GCState *gcstate = &tstate->interp->gc; + assert(tstate->current_frame == NULL || tstate->current_frame->stackpointer != NULL); int expected = 0; if (!_Py_atomic_compare_exchange_int(&gcstate->collecting, &expected, 1)) { @@ -2309,11 +2310,12 @@ PyObject * PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) { size_t presize = _PyType_PreHeaderSize(tp); - PyObject *op = gc_alloc(tp, _PyObject_SIZE(tp) + extra_size, presize); + size_t size = _PyObject_SIZE(tp) + extra_size; + PyObject *op = gc_alloc(tp, size, presize); if (op == NULL) { return NULL; } - memset(op, 0, _PyObject_SIZE(tp) + extra_size); + memset((char *)op + sizeof(PyObject), 0, size - sizeof(PyObject)); _PyObject_Init(op, tp); return op; } diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index 9e459da3a44370..694f97d5c57334 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -581,11 +581,13 @@ gc_mark_buffer_len(gc_mark_args_t *args) } // Returns number of free entry slots in buffer +#ifndef NDEBUG static inline unsigned int gc_mark_buffer_avail(gc_mark_args_t *args) { return BUFFER_SIZE - gc_mark_buffer_len(args); } +#endif static inline bool gc_mark_buffer_is_empty(gc_mark_args_t *args) @@ -1074,14 +1076,14 @@ mark_heap_visitor(const mi_heap_t *heap, const mi_heap_area_t *area, return true; } - _PyObject_ASSERT_WITH_MSG(op, gc_get_refs(op) >= 0, - "refcount is too small"); - if (gc_is_alive(op) || !gc_is_unreachable(op)) { // Object was already marked as reachable. return true; } + _PyObject_ASSERT_WITH_MSG(op, gc_get_refs(op) >= 0, + "refcount is too small"); + // GH-129236: If we've seen an active frame without a valid stack pointer, // then we can't collect objects with deferred references because we may // have missed some reference to the object on the stack. In that case, @@ -1178,10 +1180,10 @@ move_legacy_finalizer_reachable(struct collection_state *state); static void gc_prime_from_spans(gc_mark_args_t *args) { - Py_ssize_t space = BUFFER_HI - gc_mark_buffer_len(args); + unsigned int space = BUFFER_HI - gc_mark_buffer_len(args); // there should always be at least this amount of space assert(space <= gc_mark_buffer_avail(args)); - assert(space > 0); + assert(space <= BUFFER_HI); gc_span_t entry = args->spans.stack[--args->spans.size]; // spans on the stack should always have one or more elements assert(entry.start < entry.end); @@ -2593,11 +2595,12 @@ PyObject * PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *tp, size_t extra_size) { size_t presize = _PyType_PreHeaderSize(tp); - PyObject *op = gc_alloc(tp, _PyObject_SIZE(tp) + extra_size, presize); + size_t size = _PyObject_SIZE(tp) + extra_size; + PyObject *op = gc_alloc(tp, size, presize); if (op == NULL) { return NULL; } - memset(op, 0, _PyObject_SIZE(tp) + extra_size); + memset((char *)op + sizeof(PyObject), 0, size - sizeof(PyObject)); _PyObject_Init(op, tp); return op; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index f02e13f5e3fbce..094ca1f3c52a04 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -61,16 +61,23 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_BinaryOps[oparg](lhs_o, rhs_o); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(lhs); - PyStackRef_CLOSE(rhs); if (res_o == NULL) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = lhs; + lhs = res; + stack_pointer[-2] = lhs; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(rhs); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = res; } - stack_pointer[-2] = res; - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -167,7 +174,9 @@ assert(PyLong_CheckExact(left_o)); assert(PyLong_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyLong_Add((PyLongObject *)left_o, (PyLongObject *)right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); if (res_o == NULL) { @@ -279,13 +288,21 @@ STAT_INC(BINARY_OP, hit); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = d->action(left_o, right_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); res = PyStackRef_FromPyObjectSteal(res_o); } - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -324,7 +341,7 @@ // _BINARY_OP_INPLACE_ADD_UNICODE { PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); - PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + PyObject *right_o = PyStackRef_AsPyObjectSteal(right); assert(PyUnicode_CheckExact(left_o)); assert(PyUnicode_CheckExact(right_o)); int next_oparg; @@ -355,11 +372,17 @@ assert(Py_REFCNT(left_o) >= 2); PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyUnicode_Append(&temp, right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); *target_local = PyStackRef_FromPyObjectSteal(temp); - PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc); + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_DECREF(right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (PyStackRef_IsNull(*target_local)) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } #if TIER_ONE // The STORE_FAST is already done. This is done here in tier one, @@ -368,8 +391,6 @@ SKIP_OVER(1); #endif } - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -466,7 +487,9 @@ assert(PyLong_CheckExact(left_o)); assert(PyLong_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyLong_Multiply((PyLongObject *)left_o, (PyLongObject *)right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); if (res_o == NULL) { @@ -514,15 +537,25 @@ _PyErr_SetKeyError(sub); stack_pointer = _PyFrame_GetStackPointer(frame); } - PyStackRef_CLOSE(dict_st); - PyStackRef_CLOSE(sub_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = sub_st; + sub_st = PyStackRef_NULL; + stack_pointer[-1] = sub_st; + PyStackRef_CLOSE(tmp); + tmp = dict_st; + dict_st = PyStackRef_NULL; + stack_pointer[-2] = dict_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (rc <= 0) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } // not found or error res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -895,7 +928,9 @@ assert(PyLong_CheckExact(left_o)); assert(PyLong_CheckExact(right_o)); STAT_INC(BINARY_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyLong_Subtract((PyLongObject *)left_o, (PyLongObject *)right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); if (res_o == NULL) { @@ -1004,9 +1039,14 @@ values = &stack_pointer[-oparg*2]; STACKREFS_TO_PYOBJECTS(values, oparg*2, values_o); if (CONVERSION_FAILED(values_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg*2; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -oparg*2; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -1018,17 +1058,22 @@ oparg); stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(values_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg*2; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg*2; + assert(WITHIN_STACK_BOUNDS()); if (map_o == NULL) { - stack_pointer += -oparg*2; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } map = PyStackRef_FromPyObjectSteal(map_o); - stack_pointer[-oparg*2] = map; - stack_pointer += 1 - oparg*2; + stack_pointer[0] = map; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -1048,9 +1093,14 @@ PyObject *set_o = PySet_New(NULL); stack_pointer = _PyFrame_GetStackPointer(frame); if (set_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -1063,20 +1113,25 @@ stack_pointer = _PyFrame_GetStackPointer(frame); } } + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(values[_i]); + tmp = values[_i]; + values[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg; + assert(WITHIN_STACK_BOUNDS()); if (err != 0) { - stack_pointer += -oparg; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); Py_DECREF(set_o); stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_LABEL(error); } set = PyStackRef_FromPyObjectSteal(set_o); - stack_pointer[-oparg] = set; - stack_pointer += 1 - oparg; + stack_pointer[0] = set; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -1096,17 +1151,22 @@ PyObject *stop_o = PyStackRef_AsPyObjectBorrow(args[1]); PyObject *step_o = oparg == 3 ? PyStackRef_AsPyObjectBorrow(args[2]) : NULL; PyObject *slice_o = PySlice_New(start_o, stop_o, step_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg; + assert(WITHIN_STACK_BOUNDS()); if (slice_o == NULL) { - stack_pointer += -oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } slice = PyStackRef_FromPyObjectSteal(slice_o); - stack_pointer[-oparg] = slice; - stack_pointer += 1 - oparg; + stack_pointer[0] = slice; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -1124,26 +1184,36 @@ pieces = &stack_pointer[-oparg]; STACKREFS_TO_PYOBJECTS(pieces, oparg, pieces_o); if (CONVERSION_FAILED(pieces_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(pieces[_i]); + tmp = pieces[_i]; + pieces[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } PyObject *str_o = _PyUnicode_JoinArray(&_Py_STR(empty), pieces_o, oparg); STACKREFS_TO_PYOBJECTS_CLEANUP(pieces_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(pieces[_i]); + tmp = pieces[_i]; + pieces[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -oparg; + assert(WITHIN_STACK_BOUNDS()); if (str_o == NULL) { - stack_pointer += -oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } str = PyStackRef_FromPyObjectSteal(str_o); - stack_pointer[-oparg] = str; - stack_pointer += 1 - oparg; + stack_pointer[0] = str; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -1279,11 +1349,20 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -1319,14 +1398,23 @@ } } assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -1336,8 +1424,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -1345,12 +1433,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -1454,7 +1542,9 @@ stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FrameClearAndPop(tstate, shim); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_LABEL(error); } init_frame = temp; @@ -1787,11 +1877,20 @@ STAT_INC(CALL, hit); STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -1800,14 +1899,23 @@ PyObject *res_o = tp->tp_vectorcall((PyObject *)tp, args_o, total_args, NULL); stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -1817,8 +1925,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -1826,12 +1934,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -1881,11 +1989,20 @@ /* res = func(self, args, nargs) */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -1898,14 +2015,23 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -1915,8 +2041,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -1924,12 +2050,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -1983,11 +2109,20 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -1997,14 +2132,23 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -2014,8 +2158,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -2023,12 +2167,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -2336,12 +2480,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -2363,15 +2513,23 @@ PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); + _PyStackRef tmp = value1_st; + value1_st = PyStackRef_NULL; + stack_pointer[-1] = value1_st; + PyStackRef_CLOSE(tmp); + tmp = value2_st; + value2_st = PyStackRef_NULL; + stack_pointer[-2] = value2_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(value2_st); - PyStackRef_CLOSE(value1_st); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -2426,11 +2584,19 @@ } res = retval ? PyStackRef_True : PyStackRef_False; assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = callable[0]; + callable[0] = res; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -2548,12 +2714,24 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + stack_pointer[-1] = kwnames; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = kwnames; + kwnames = PyStackRef_NULL; + stack_pointer[-1] = kwnames; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } - PyStackRef_CLOSE(kwnames); + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -3 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -2589,21 +2767,32 @@ } } } - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = kwnames; + kwnames = PyStackRef_NULL; + stack_pointer[-1] = kwnames; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } - PyStackRef_CLOSE(kwnames); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -3 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); } - stack_pointer[-3 - oparg] = res; - stack_pointer += -2 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -2793,12 +2982,23 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = kwnames; + kwnames = PyStackRef_NULL; + stack_pointer[-1] = kwnames; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } - PyStackRef_CLOSE(kwnames); + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -3 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -2818,14 +3018,23 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -2835,8 +3044,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -2844,12 +3053,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -3144,11 +3353,20 @@ int nargs = total_args - 1; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -3160,14 +3378,23 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -3177,8 +3404,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -3186,12 +3413,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -3248,11 +3475,20 @@ int nargs = total_args - 1; STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -3264,14 +3500,23 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -3281,8 +3526,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -3290,12 +3535,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -3474,14 +3719,23 @@ stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -3491,8 +3745,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -3500,12 +3754,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -3560,11 +3814,20 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -3577,14 +3840,23 @@ stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -3594,8 +3866,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -3603,12 +3875,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4030,38 +4302,54 @@ int err = _PyEval_CheckExceptStarTypeValid(tstate, match_type); stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - PyStackRef_CLOSE(exc_value_st); - PyStackRef_CLOSE(match_type_st); - JUMP_TO_LABEL(pop_2_error); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = match_type_st; + match_type_st = PyStackRef_NULL; + stack_pointer[-1] = match_type_st; + PyStackRef_CLOSE(tmp); + tmp = exc_value_st; + exc_value_st = PyStackRef_NULL; + stack_pointer[-2] = exc_value_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + JUMP_TO_LABEL(error); } PyObject *match_o = NULL; PyObject *rest_o = NULL; _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_ExceptionGroupMatch(frame, exc_value, match_type, &match_o, &rest_o); + _PyStackRef tmp = match_type_st; + match_type_st = PyStackRef_NULL; + stack_pointer[-1] = match_type_st; + PyStackRef_CLOSE(tmp); + tmp = exc_value_st; + exc_value_st = PyStackRef_NULL; + stack_pointer[-2] = exc_value_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(exc_value_st); - PyStackRef_CLOSE(match_type_st); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } assert((match_o == NULL) == (rest_o == NULL)); if (match_o == NULL) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } if (!Py_IsNone(match_o)) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); PyErr_SetHandledException(match_o); stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += 2; - assert(WITHIN_STACK_BOUNDS()); } rest = PyStackRef_FromPyObjectSteal(rest_o); match = PyStackRef_FromPyObjectSteal(match_o); - stack_pointer[-2] = rest; - stack_pointer[-1] = match; + stack_pointer[0] = rest; + stack_pointer[1] = match; + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4085,15 +4373,20 @@ int err = _PyEval_CheckExceptTypeValid(tstate, right_o); stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - PyStackRef_CLOSE(right); - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyErr_GivenExceptionMatches(left_o, right_o); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(right); + stack_pointer = _PyFrame_GetStackPointer(frame); b = res ? PyStackRef_True : PyStackRef_False; - stack_pointer[-1] = b; + stack_pointer[0] = b; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4107,14 +4400,14 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(CLEANUP_THROW); - _PyStackRef sub_iter_st; - _PyStackRef last_sent_val_st; + _PyStackRef sub_iter; + _PyStackRef last_sent_val; _PyStackRef exc_value_st; _PyStackRef none; _PyStackRef value; exc_value_st = stack_pointer[-1]; - last_sent_val_st = stack_pointer[-2]; - sub_iter_st = stack_pointer[-3]; + last_sent_val = stack_pointer[-2]; + sub_iter = stack_pointer[-3]; PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); #ifndef Py_TAIL_CALL_INTERP assert(throwflag); @@ -4124,23 +4417,34 @@ int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration); stack_pointer = _PyFrame_GetStackPointer(frame); if (matches) { - none = PyStackRef_None; value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value); - PyStackRef_CLOSE(sub_iter_st); - PyStackRef_CLOSE(last_sent_val_st); - PyStackRef_CLOSE(exc_value_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = sub_iter; + sub_iter = value; + stack_pointer[-3] = sub_iter; + PyStackRef_CLOSE(tmp); + tmp = exc_value_st; + exc_value_st = PyStackRef_NULL; + stack_pointer[-1] = exc_value_st; + PyStackRef_CLOSE(tmp); + tmp = last_sent_val; + last_sent_val = PyStackRef_NULL; + stack_pointer[-2] = last_sent_val; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); + none = PyStackRef_None; } else { _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); monitor_reraise(tstate, frame, this_instr); - stack_pointer = _PyFrame_GetStackPointer(frame); - _PyFrame_SetStackPointer(frame, stack_pointer); JUMP_TO_LABEL(exception_unwind); } - stack_pointer[-3] = none; - stack_pointer[-2] = value; - stack_pointer += -1; + stack_pointer[0] = none; + stack_pointer[1] = value; + stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4184,15 +4488,21 @@ assert((oparg >> 5) <= Py_GE); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_RichCompare(left_o, right_o, oparg >> 5); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } if (oparg & 16) { - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int res_bool = PyObject_IsTrue(res_o); Py_DECREF(res_o); @@ -4204,8 +4514,6 @@ } else { res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[0] = res; @@ -4421,16 +4729,24 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); _PyFrame_SetStackPointer(frame, stack_pointer); int res = PySequence_Contains(right_o, left_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; } - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4462,15 +4778,23 @@ STAT_INC(CONTAINS_OP, hit); _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyDict_Contains(right_o, left_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4503,15 +4827,23 @@ // Note: both set and frozenset use the same seq_contains method! _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PySet_Contains((PySetObject *)right_o, left_o); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res < 0) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4603,12 +4935,14 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelAttr(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4737,14 +5071,20 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub)); + _PyStackRef tmp = sub; + sub = PyStackRef_NULL; + stack_pointer[-1] = sub; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-2] = container; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(container); - PyStackRef_CLOSE(sub); - if (err) { - JUMP_TO_LABEL(pop_2_error); - } stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); + if (err) { + JUMP_TO_LABEL(error); + } DISPATCH(); } @@ -4772,12 +5112,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatKwargsError(tstate, callable_o, update_o); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(update); - JUMP_TO_LABEL(pop_1_error); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); } - PyStackRef_CLOSE(update); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(update); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -4809,12 +5155,18 @@ Py_TYPE(update_o)->tp_name); stack_pointer = _PyFrame_GetStackPointer(frame); } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(update); - JUMP_TO_LABEL(pop_1_error); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); } - PyStackRef_CLOSE(update); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(update); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -4838,20 +5190,26 @@ int matches = PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration); stack_pointer = _PyFrame_GetStackPointer(frame); if (matches) { - PyStackRef_CLOSE(awaitable_st); - PyStackRef_CLOSE(exc_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = exc_st; + exc_st = PyStackRef_NULL; + stack_pointer[-1] = exc_st; + PyStackRef_CLOSE(tmp); + tmp = awaitable_st; + awaitable_st = PyStackRef_NULL; + stack_pointer[-2] = awaitable_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); } else { Py_INCREF(exc); _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetRaisedException(tstate, exc); monitor_reraise(tstate, frame, this_instr); - stack_pointer = _PyFrame_GetStackPointer(frame); - _PyFrame_SetStackPointer(frame, stack_pointer); JUMP_TO_LABEL(exception_unwind); } - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -4892,10 +5250,12 @@ receiver = stack_pointer[-2]; (void)receiver; val = value; - PyStackRef_CLOSE(receiver); stack_pointer[-2] = val; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(receiver); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -5032,15 +5392,23 @@ value = stack_pointer[-2]; _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Format(PyStackRef_AsPyObjectBorrow(value), PyStackRef_AsPyObjectBorrow(fmt_spec)); + _PyStackRef tmp = fmt_spec; + fmt_spec = PyStackRef_NULL; + stack_pointer[-1] = fmt_spec; + PyStackRef_CLOSE(tmp); + tmp = value; + value = PyStackRef_NULL; + stack_pointer[-2] = value; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(value); - PyStackRef_CLOSE(fmt_spec); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -5376,20 +5744,26 @@ "__aiter__ method, got %.100s", type->tp_name); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(obj); - JUMP_TO_LABEL(pop_1_error); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); } _PyFrame_SetStackPointer(frame, stack_pointer); iter_o = (*getter)(obj_o); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(obj); + stack_pointer = _PyFrame_GetStackPointer(frame); if (iter_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } if (Py_TYPE(iter_o)->tp_as_async == NULL || Py_TYPE(iter_o)->tp_as_async->am_anext == NULL) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'async for' received an object from __aiter__ " @@ -5400,7 +5774,9 @@ JUMP_TO_LABEL(error); } iter = PyStackRef_FromPyObjectSteal(iter_o); - stack_pointer[-1] = iter; + stack_pointer[0] = iter; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -5442,12 +5818,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = _PyEval_GetAwaitable(PyStackRef_AsPyObjectBorrow(iterable), oparg); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (iter_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } iter = PyStackRef_FromPyObjectSteal(iter_o); - stack_pointer[-1] = iter; + stack_pointer[0] = iter; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -5466,12 +5848,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (iter_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } iter = PyStackRef_FromPyObjectSteal(iter_o); - stack_pointer[-1] = iter; + stack_pointer[0] = iter; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -5544,7 +5932,13 @@ JUMP_TO_LABEL(error); } iter = PyStackRef_FromPyObjectSteal(iter_o); - PyStackRef_CLOSE(iterable); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = iterable; + iterable = iter; + stack_pointer[-1] = iterable; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = iter; } } stack_pointer[-1] = iter; @@ -5594,15 +5988,23 @@ PyObject *res_o = _PyEval_ImportName(tstate, frame, name, PyStackRef_AsPyObjectBorrow(fromlist), PyStackRef_AsPyObjectBorrow(level)); + _PyStackRef tmp = fromlist; + fromlist = PyStackRef_NULL; + stack_pointer[-1] = fromlist; + PyStackRef_CLOSE(tmp); + tmp = level; + level = PyStackRef_NULL; + stack_pointer[-2] = level; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(level); - PyStackRef_CLOSE(fromlist); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -5714,11 +6116,20 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -5754,14 +6165,23 @@ } } assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp; for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); @@ -5771,8 +6191,8 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -5780,12 +6200,12 @@ if (err != 0) { JUMP_TO_LABEL(error); } - stack_pointer += 1 + oparg; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -6102,12 +6522,24 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + stack_pointer[-1] = kwnames; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = kwnames; + kwnames = PyStackRef_NULL; + stack_pointer[-1] = kwnames; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); } - PyStackRef_CLOSE(kwnames); + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -3 - oparg; assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); @@ -6143,21 +6575,32 @@ } } } - PyStackRef_CLOSE(callable[0]); - PyStackRef_XCLOSE(self_or_null[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = kwnames; + kwnames = PyStackRef_NULL; + stack_pointer[-1] = kwnames; + PyStackRef_CLOSE(tmp); for (int _i = oparg; --_i >= 0;) { - PyStackRef_CLOSE(args[_i]); - } - PyStackRef_CLOSE(kwnames); + tmp = args[_i]; + args[_i] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + } + tmp = self_or_null[0]; + self_or_null[0] = PyStackRef_NULL; + PyStackRef_XCLOSE(tmp); + tmp = callable[0]; + callable[0] = PyStackRef_NULL; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3 - oparg; + assert(WITHIN_STACK_BOUNDS()); if (res_o == NULL) { - stack_pointer += -3 - oparg; - assert(WITHIN_STACK_BOUNDS()); JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); } - stack_pointer[-3 - oparg] = res; - stack_pointer += -2 - oparg; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -6185,9 +6628,11 @@ JUMP_TO_LABEL(error); } } - PyStackRef_CLOSE(value); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -6414,10 +6859,23 @@ frame, this_instr, global_super, arg); stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - PyStackRef_CLOSE(global_super_st); - PyStackRef_CLOSE(class_st); - PyStackRef_CLOSE(self_st); - JUMP_TO_LABEL(pop_3_error); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = self_st; + self_st = PyStackRef_NULL; + stack_pointer[-1] = self_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-2] = class_st; + PyStackRef_CLOSE(tmp); + tmp = global_super_st; + global_super_st = PyStackRef_NULL; + stack_pointer[-3] = global_super_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); + JUMP_TO_LABEL(error); } } // we make no attempt to optimize here; specializations should @@ -6448,15 +6906,26 @@ } } } - PyStackRef_CLOSE(global_super_st); - PyStackRef_CLOSE(class_st); - PyStackRef_CLOSE(self_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = self_st; + self_st = PyStackRef_NULL; + stack_pointer[-1] = self_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-2] = class_st; + PyStackRef_CLOSE(tmp); + tmp = global_super_st; + global_super_st = PyStackRef_NULL; + stack_pointer[-3] = global_super_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (super == NULL) { - JUMP_TO_LABEL(pop_3_error); + JUMP_TO_LABEL(error); } PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr_o = PyObject_GetAttr(super, name); Py_DECREF(super); @@ -6845,11 +7314,21 @@ right = stack_pointer[-1]; left = stack_pointer[-2]; int res = Py_Is(PyStackRef_AsPyObjectBorrow(left), PyStackRef_AsPyObjectBorrow(right)) ^ oparg; - PyStackRef_CLOSE(left); - PyStackRef_CLOSE(right); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = right; + right = PyStackRef_NULL; + stack_pointer[-1] = right; + PyStackRef_CLOSE(tmp); + tmp = left; + left = PyStackRef_NULL; + stack_pointer[-2] = left; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); b = res ? PyStackRef_True : PyStackRef_False; - stack_pointer[-2] = b; - stack_pointer += -1; + stack_pointer[0] = b; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -7095,13 +7574,19 @@ Py_TYPE(iterable)->tp_name); stack_pointer = _PyFrame_GetStackPointer(frame); } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(iterable_st); - JUMP_TO_LABEL(pop_1_error); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); } assert(Py_IsNone(none_val)); - PyStackRef_CLOSE(iterable_st); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable_st); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -7164,22 +7649,34 @@ CALL that it's not a method call. meth | NULL | arg1 | ... | argN */ + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); if (attr_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } self_or_null[0] = PyStackRef_NULL; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } } else { /* Classic, pushes one value. */ _PyFrame_SetStackPointer(frame, stack_pointer); - attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); - stack_pointer = _PyFrame_GetStackPointer(frame); + attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); if (attr_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } attr = PyStackRef_FromPyObjectSteal(attr_o); } @@ -7228,13 +7725,18 @@ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); attr = PyStackRef_FromPyObjectNew(descr); - PyStackRef_CLOSE(owner); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = attr; } // _PUSH_NULL_CONDITIONAL { null = PyStackRef_NULL; } - stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = null; stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); @@ -7290,13 +7792,18 @@ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); attr = PyStackRef_FromPyObjectNew(descr); - PyStackRef_CLOSE(owner); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = attr; } // _PUSH_NULL_CONDITIONAL { null = PyStackRef_NULL; } - stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = null; stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); @@ -7722,10 +8229,16 @@ assert(Py_TYPE(PyStackRef_AsPyObjectBorrow(owner))->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); attr = PyStackRef_FromPyObjectNew(descr); } - stack_pointer[-1] = attr; + stack_pointer[0] = attr; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -7784,10 +8297,16 @@ assert((oparg & 1) == 0); STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(owner); + stack_pointer = _PyFrame_GetStackPointer(frame); attr = PyStackRef_FromPyObjectNew(descr); } - stack_pointer[-1] = attr; + stack_pointer[0] = attr; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -7935,14 +8454,19 @@ attr = PyStackRef_FromPyObjectNew(attr_o); #endif STAT_INC(LOAD_ATTR, hit); - PyStackRef_CLOSE(owner); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = attr; } /* Skip 5 cache entries */ // _PUSH_NULL_CONDITIONAL { null = PyStackRef_NULL; } - stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = null; stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); @@ -8039,14 +8563,19 @@ STAT_INC(LOAD_ATTR, hit); attr = PyStackRef_FromPyObjectNew(attr_o); UNLOCK_OBJECT(dict); - PyStackRef_CLOSE(owner); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = owner; + owner = attr; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = attr; } /* Skip 5 cache entries */ // _PUSH_NULL_CONDITIONAL { null = PyStackRef_NULL; } - stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = null; stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); @@ -8349,16 +8878,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &v_o); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(mod_or_class_dict); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } if (v_o == NULL) { if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) { - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); v_o = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), (PyDictObject *)BUILTINS(), @@ -8379,8 +8910,6 @@ else { /* Slow-path if globals or builtins is not a dict */ /* namespace 1: globals */ - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(GLOBALS(), name, &v_o); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -8405,11 +8934,11 @@ } } } - stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); } v = PyStackRef_FromPyObjectSteal(v_o); - stack_pointer[-1] = v; + stack_pointer[0] = v; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -8775,10 +9304,23 @@ frame, this_instr, global_super, arg); stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - PyStackRef_CLOSE(global_super_st); - PyStackRef_CLOSE(class_st); - PyStackRef_CLOSE(self_st); - JUMP_TO_LABEL(pop_3_error); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = self_st; + self_st = PyStackRef_NULL; + stack_pointer[-1] = self_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-2] = class_st; + PyStackRef_CLOSE(tmp); + tmp = global_super_st; + global_super_st = PyStackRef_NULL; + stack_pointer[-3] = global_super_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); + JUMP_TO_LABEL(error); } } // we make no attempt to optimize here; specializations should @@ -8809,15 +9351,26 @@ } } } - PyStackRef_CLOSE(global_super_st); - PyStackRef_CLOSE(class_st); - PyStackRef_CLOSE(self_st); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = self_st; + self_st = PyStackRef_NULL; + stack_pointer[-1] = self_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-2] = class_st; + PyStackRef_CLOSE(tmp); + tmp = global_super_st; + global_super_st = PyStackRef_NULL; + stack_pointer[-3] = global_super_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (super == NULL) { - JUMP_TO_LABEL(pop_3_error); + JUMP_TO_LABEL(error); } PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr_o = PyObject_GetAttr(super, name); Py_DECREF(super); @@ -8875,16 +9428,27 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + _PyStackRef tmp = self_st; + self_st = PyStackRef_NULL; + stack_pointer[-1] = self_st; + PyStackRef_CLOSE(tmp); + tmp = class_st; + class_st = PyStackRef_NULL; + stack_pointer[-2] = class_st; + PyStackRef_CLOSE(tmp); + tmp = global_super_st; + global_super_st = PyStackRef_NULL; + stack_pointer[-3] = global_super_st; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(global_super_st); - PyStackRef_CLOSE(class_st); - PyStackRef_CLOSE(self_st); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (attr == NULL) { - JUMP_TO_LABEL(pop_3_error); + JUMP_TO_LABEL(error); } attr_st = PyStackRef_FromPyObjectSteal(attr); - stack_pointer[-3] = attr_st; - stack_pointer += -2; + stack_pointer[0] = attr_st; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -8946,13 +9510,26 @@ stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); } - PyStackRef_CLOSE(global_super_st); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = global_super_st; + global_super_st = self_or_null; + stack_pointer[-2] = global_super_st; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(class_st); - attr = PyStackRef_FromPyObjectSteal(attr_o); - stack_pointer[-3] = attr; - stack_pointer[-2] = self_or_null; + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + attr = PyStackRef_FromPyObjectSteal(attr_o); + stack_pointer[0] = attr; + stack_pointer[1] = self_or_null; + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -9068,23 +9645,34 @@ PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); + _PyStackRef tmp = names; + names = PyStackRef_NULL; + stack_pointer[-1] = names; + PyStackRef_CLOSE(tmp); + tmp = type; + type = PyStackRef_NULL; + stack_pointer[-2] = type; + PyStackRef_CLOSE(tmp); + tmp = subject; + subject = PyStackRef_NULL; + stack_pointer[-3] = subject; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(subject); - PyStackRef_CLOSE(type); - PyStackRef_CLOSE(names); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (attrs_o) { assert(PyTuple_CheckExact(attrs_o)); // Success! attrs = PyStackRef_FromPyObjectSteal(attrs_o); } else { if (_PyErr_Occurred(tstate)) { - JUMP_TO_LABEL(pop_3_error); + JUMP_TO_LABEL(error); } // Error! attrs = PyStackRef_None; // Failure! } - stack_pointer[-3] = attrs; - stack_pointer += -2; + stack_pointer[0] = attrs; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -9208,9 +9796,11 @@ INSTRUCTION_STATS(POP_ITER); _PyStackRef value; value = stack_pointer[-1]; - PyStackRef_CLOSE(value); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -9258,7 +9848,13 @@ } else { b = PyStackRef_False; - PyStackRef_CLOSE(value); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = value; + value = b; + stack_pointer[-1] = value; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = b; } } // _POP_JUMP_IF_TRUE @@ -9296,7 +9892,13 @@ } else { b = PyStackRef_False; - PyStackRef_CLOSE(value); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = value; + value = b; + stack_pointer[-1] = value; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-1] = b; } } // _POP_JUMP_IF_FALSE @@ -9344,9 +9946,11 @@ INSTRUCTION_STATS(POP_TOP); _PyStackRef value; value = stack_pointer[-1]; - PyStackRef_CLOSE(value); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -9419,8 +10023,6 @@ assert(oparg == 0); _PyFrame_SetStackPointer(frame, stack_pointer); monitor_reraise(tstate, frame, this_instr); - stack_pointer = _PyFrame_GetStackPointer(frame); - _PyFrame_SetStackPointer(frame, stack_pointer); JUMP_TO_LABEL(exception_unwind); } JUMP_TO_LABEL(error); @@ -9464,8 +10066,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetRaisedException(tstate, exc); monitor_reraise(tstate, frame, this_instr); - stack_pointer = _PyFrame_GetStackPointer(frame); - _PyFrame_SetStackPointer(frame, stack_pointer); JUMP_TO_LABEL(exception_unwind); } @@ -9750,8 +10350,12 @@ JUMPBY(oparg); } else { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); - JUMP_TO_LABEL(pop_1_error); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); } } stack_pointer += -1; @@ -9900,12 +10504,14 @@ int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -9953,12 +10559,14 @@ int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10001,15 +10609,21 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetAttr(PyStackRef_AsPyObjectBorrow(owner), name, PyStackRef_AsPyObjectBorrow(v)); + _PyStackRef tmp = owner; + owner = PyStackRef_NULL; + stack_pointer[-1] = owner; + PyStackRef_CLOSE(tmp); + tmp = v; + v = PyStackRef_NULL; + stack_pointer[-2] = v; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(v); - PyStackRef_CLOSE(owner); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (err) { - JUMP_TO_LABEL(pop_2_error); + JUMP_TO_LABEL(error); } } - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10347,12 +10961,14 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_SetItem(GLOBALS(), name, PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10374,8 +10990,12 @@ _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); - JUMP_TO_LABEL(pop_1_error); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); } if (PyDict_CheckExact(ns)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -10387,12 +11007,14 @@ err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); stack_pointer = _PyFrame_GetStackPointer(frame); } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(v); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10439,14 +11061,24 @@ stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); } - PyStackRef_CLOSE(v); - PyStackRef_CLOSE(container); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = container; + container = PyStackRef_NULL; + stack_pointer[-1] = container; + PyStackRef_CLOSE(tmp); + tmp = v; + v = PyStackRef_NULL; + stack_pointer[-2] = v; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); if (err) { - JUMP_TO_LABEL(pop_4_error); + JUMP_TO_LABEL(error); } } - stack_pointer += -4; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10488,16 +11120,25 @@ /* container[sub] = v */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v)); + _PyStackRef tmp = sub; + sub = PyStackRef_NULL; + stack_pointer[-1] = sub; + PyStackRef_CLOSE(tmp); + tmp = container; + container = PyStackRef_NULL; + stack_pointer[-2] = container; + PyStackRef_CLOSE(tmp); + tmp = v; + v = PyStackRef_NULL; + stack_pointer[-3] = v; + PyStackRef_CLOSE(tmp); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(v); - PyStackRef_CLOSE(container); - PyStackRef_CLOSE(sub); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); if (err) { - JUMP_TO_LABEL(pop_3_error); + JUMP_TO_LABEL(error); } } - stack_pointer += -3; - assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10663,13 +11304,19 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } res = err ? PyStackRef_True : PyStackRef_False; } - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10703,10 +11350,16 @@ // _REPLACE_WITH_TRUE { value = owner; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); res = PyStackRef_True; } - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10762,8 +11415,14 @@ res = PyStackRef_False; } else { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); res = PyStackRef_True; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } stack_pointer[-1] = res; DISPATCH(); @@ -10793,7 +11452,12 @@ } STAT_INC(TO_BOOL, hit); res = PyList_GET_SIZE(value_o) ? PyStackRef_True : PyStackRef_False; - PyStackRef_CLOSE(value); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = value; + value = res; + stack_pointer[-1] = value; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-1] = res; DISPATCH(); } @@ -10855,8 +11519,14 @@ } else { assert(Py_SIZE(value_o)); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); res = PyStackRef_True; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } stack_pointer[-1] = res; DISPATCH(); @@ -10876,12 +11546,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Invert(PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10899,12 +11575,18 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Negative(PyStackRef_AsPyObjectBorrow(value)); stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } res = PyStackRef_FromPyObjectSteal(res_o); - stack_pointer[-1] = res; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10935,18 +11617,20 @@ next_instr += 1; INSTRUCTION_STATS(UNPACK_EX); _PyStackRef seq; - _PyStackRef *right; + _PyStackRef *top; seq = stack_pointer[-1]; - right = &stack_pointer[(oparg & 0xFF)]; - _PyStackRef *top = right + (oparg >> 8); + top = &stack_pointer[(oparg & 0xFF) + (oparg >> 8)]; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg & 0xFF, oparg >> 8, top); + int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg & 0xFF, oparg >> 8, top); + Py_DECREF(seq_o); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(seq); if (res == 0) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } - stack_pointer += (oparg & 0xFF) + (oparg >> 8); + stack_pointer += 1 + (oparg & 0xFF) + (oparg >> 8); assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -10963,7 +11647,7 @@ _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; _PyStackRef seq; - _PyStackRef *output; + _PyStackRef *top; // _SPECIALIZE_UNPACK_SEQUENCE { seq = stack_pointer[-1]; @@ -10985,17 +11669,19 @@ } // _UNPACK_SEQUENCE { - output = &stack_pointer[-1]; - _PyStackRef *top = output + oparg; + top = &stack_pointer[-1 + oparg]; + PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); - int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg, -1, top); + int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg, -1, top); + Py_DECREF(seq_o); stack_pointer = _PyFrame_GetStackPointer(frame); - PyStackRef_CLOSE(seq); if (res == 0) { - JUMP_TO_LABEL(pop_1_error); + JUMP_TO_LABEL(error); } } - stack_pointer += -1 + oparg; + stack_pointer += oparg; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -11041,8 +11727,12 @@ *values++ = PyStackRef_FromPyObjectNew(items[i]); } UNLOCK_OBJECT(seq_o); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(seq); - stack_pointer += -1 + oparg; + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += oparg; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -11079,8 +11769,12 @@ for (int i = oparg; --i >= 0; ) { *values++ = PyStackRef_FromPyObjectNew(items[i]); } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(seq); - stack_pointer += -1 + oparg; + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += oparg; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -11116,11 +11810,13 @@ STAT_INC(UNPACK_SEQUENCE, hit); val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0)); val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1)); - PyStackRef_CLOSE(seq); stack_pointer[-1] = val1; stack_pointer[0] = val0; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(seq); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -11310,8 +12006,6 @@ JUMP_TO_LABEL(error); } _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_MonitorRaise(tstate, frame, next_instr-1); - stack_pointer = _PyFrame_GetStackPointer(frame); - _PyFrame_SetStackPointer(frame, stack_pointer); JUMP_TO_LABEL(exception_unwind); } @@ -11403,8 +12097,12 @@ JUMP_TO_LABEL(error); JUMP_TO_LABEL(exit_unwind); } next_instr = frame->instr_ptr; - LLTRACE_RESUME_FRAME(); #ifdef Py_DEBUG + int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); + if (lltrace < 0) { + JUMP_TO_LABEL(exit_unwind); + } + frame->lltrace = lltrace; /* _PyEval_EvalFrameDefault() must not be called with an exception set, because it can clear it (directly or indirectly) and so the caller loses its exception */ diff --git a/Python/initconfig.c b/Python/initconfig.c index 4db77ef47d2362..1733ed05a3e8d9 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -305,6 +305,8 @@ The following implementation-specific options are available:\n\ -X no_debug_ranges: don't include extra location information in code objects;\n\ also PYTHONNODEBUGRANGES\n\ -X perf: support the Linux \"perf\" profiler; also PYTHONPERFSUPPORT=1\n\ +-X perf_jit: support the Linux \"perf\" profiler with DWARF support;\n\ + also PYTHON_PERF_JIT_SUPPORT=1\n\ " #ifdef Py_DEBUG "-X presite=MOD: import this module before site; also PYTHON_PRESITE\n" diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 0e7b4810726434..12fd35f43562ae 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -185,8 +185,7 @@ is_instrumented(int opcode) { assert(opcode != 0); assert(opcode != RESERVED); - assert(opcode != ENTER_EXECUTOR); - return opcode >= MIN_INSTRUMENTED_OPCODE; + return opcode != ENTER_EXECUTOR && opcode >= MIN_INSTRUMENTED_OPCODE; } #ifndef NDEBUG diff --git a/Python/optimizer.c b/Python/optimizer.c index bef5728349a612..d86d58d82e391b 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -671,7 +671,7 @@ translate_bytecode_to_trace( if (trace_stack_depth == 0) { DPRINTF(2, "Trace stack underflow\n"); OPT_STAT_INC(trace_stack_underflow); - goto done; + return 0; } } uint32_t orig_oparg = oparg; // For OPARG_TOP/BOTTOM diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index fd8486785ed8db..51d0fa63e64bc5 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -273,14 +273,16 @@ { assert(PyLong_CheckExact(sym_get_const(left))); assert(PyLong_CheckExact(sym_get_const(right))); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); PyObject *temp = _PyLong_Multiply((PyLongObject *)sym_get_const(left), (PyLongObject *)sym_get_const(right)); if (temp == NULL) { goto error; } res = sym_new_const(ctx, temp); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); // TODO gh-115506: @@ -306,14 +308,16 @@ { assert(PyLong_CheckExact(sym_get_const(left))); assert(PyLong_CheckExact(sym_get_const(right))); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); PyObject *temp = _PyLong_Add((PyLongObject *)sym_get_const(left), (PyLongObject *)sym_get_const(right)); if (temp == NULL) { goto error; } res = sym_new_const(ctx, temp); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); // TODO gh-115506: @@ -339,14 +343,16 @@ { assert(PyLong_CheckExact(sym_get_const(left))); assert(PyLong_CheckExact(sym_get_const(right))); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); PyObject *temp = _PyLong_Subtract((PyLongObject *)sym_get_const(left), (PyLongObject *)sym_get_const(right)); if (temp == NULL) { goto error; } res = sym_new_const(ctx, temp); - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); // TODO gh-115506: diff --git a/Python/pythonrun.c b/Python/pythonrun.c index ae0df9685ac159..945e267ef72c6f 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -589,8 +589,13 @@ parse_exit_code(PyObject *code, int *exitcode_p) } int -_Py_HandleSystemExit(int *exitcode_p) +_Py_HandleSystemExitAndKeyboardInterrupt(int *exitcode_p) { + if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { + _Py_atomic_store_int(&_PyRuntime.signals.unhandled_keyboard_interrupt, 1); + return 0; + } + int inspect = _Py_GetConfig()->inspect; if (inspect) { /* Don't exit if -i flag was given. This flag is set to 0 @@ -646,7 +651,7 @@ static void handle_system_exit(void) { int exitcode; - if (_Py_HandleSystemExit(&exitcode)) { + if (_Py_HandleSystemExitAndKeyboardInterrupt(&exitcode)) { Py_Exit(exitcode); } } @@ -1105,8 +1110,6 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) } } - int unhandled_keyboard_interrupt = _PyRuntime.signals.unhandled_keyboard_interrupt; - // Try first with the stdlib traceback module PyObject *print_exception_fn = PyImport_ImportModuleAttrString( "traceback", @@ -1120,11 +1123,9 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) Py_XDECREF(print_exception_fn); if (result) { Py_DECREF(result); - _PyRuntime.signals.unhandled_keyboard_interrupt = unhandled_keyboard_interrupt; return; } fallback: - _PyRuntime.signals.unhandled_keyboard_interrupt = unhandled_keyboard_interrupt; #ifdef Py_DEBUG if (PyErr_Occurred()) { PyErr_FormatUnraisable( @@ -1297,20 +1298,6 @@ flush_io(void) static PyObject * run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, PyObject *locals) { - PyObject *v; - /* - * We explicitly re-initialize _Py_UnhandledKeyboardInterrupt every eval - * _just in case_ someone is calling into an embedded Python where they - * don't care about an uncaught KeyboardInterrupt exception (why didn't they - * leave config.install_signal_handlers set to 0?!?) but then later call - * Py_Main() itself (which _checks_ this flag and dies with a signal after - * its interpreter exits). We don't want a previous embedded interpreter's - * uncaught exception to trigger an unexplained signal exit from a future - * Py_Main() based one. - */ - // XXX Isn't this dealt with by the move to _PyRuntimeState? - _PyRuntime.signals.unhandled_keyboard_interrupt = 0; - /* Set globals['__builtins__'] if it doesn't exist */ if (!globals || !PyDict_Check(globals)) { PyErr_SetString(PyExc_SystemError, "globals must be a real dict"); @@ -1328,11 +1315,7 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py } } - v = PyEval_EvalCode((PyObject*)co, globals, locals); - if (!v && _PyErr_Occurred(tstate) == PyExc_KeyboardInterrupt) { - _PyRuntime.signals.unhandled_keyboard_interrupt = 1; - } - return v; + return PyEval_EvalCode((PyObject*)co, globals, locals); } static PyObject * diff --git a/README.rst b/README.rst index 6f74bc3f9ed7ef..0496d231ca7dde 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.14.0 alpha 4 +This is Python version 3.14.0 alpha 5 ===================================== .. image:: https://github.com/python/cpython/actions/workflows/build.yml/badge.svg?branch=main&event=push diff --git a/Tools/build/compute-changes.py b/Tools/build/compute-changes.py index 105ba58cc9d941..86c447dd4f64e0 100644 --- a/Tools/build/compute-changes.py +++ b/Tools/build/compute-changes.py @@ -21,11 +21,27 @@ GITHUB_DEFAULT_BRANCH = os.environ["GITHUB_DEFAULT_BRANCH"] GITHUB_CODEOWNERS_PATH = Path(".github/CODEOWNERS") GITHUB_WORKFLOWS_PATH = Path(".github/workflows") + CONFIGURATION_FILE_NAMES = frozenset({ ".pre-commit-config.yaml", ".ruff.toml", "mypy.ini", }) +UNIX_BUILD_SYSTEM_FILE_NAMES = frozenset({ + Path("aclocal.m4"), + Path("config.guess"), + Path("config.sub"), + Path("configure"), + Path("configure.ac"), + Path("install-sh"), + Path("Makefile.pre.in"), + Path("Modules/makesetup"), + Path("Modules/Setup"), + Path("Modules/Setup.bootstrap.in"), + Path("Modules/Setup.stdlib.in"), + Path("Tools/build/regen-configure.sh"), +}) + SUFFIXES_C_OR_CPP = frozenset({".c", ".h", ".cpp"}) SUFFIXES_DOCUMENTATION = frozenset({".rst", ".md"}) @@ -36,6 +52,7 @@ class Outputs: run_docs: bool = False run_tests: bool = False run_windows_msi: bool = False + run_windows_tests: bool = False def compute_changes() -> None: @@ -53,6 +70,8 @@ def compute_changes() -> None: if outputs.run_tests: print("Run tests") + if outputs.run_windows_tests: + print("Run Windows tests") if outputs.run_ci_fuzz: print("Run CIFuzz tests") @@ -98,6 +117,7 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs: run_tests = False run_ci_fuzz = False run_docs = False + run_windows_tests = False run_windows_msi = False for file in changed_files: @@ -120,6 +140,9 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs: ): run_tests = True + if file not in UNIX_BUILD_SYSTEM_FILE_NAMES: + run_windows_tests = True + # The fuzz tests are pretty slow so they are executed only for PRs # changing relevant files. if file.suffix in SUFFIXES_C_OR_CPP: @@ -142,6 +165,7 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs: run_ci_fuzz=run_ci_fuzz, run_docs=run_docs, run_tests=run_tests, + run_windows_tests=run_windows_tests, run_windows_msi=run_windows_msi, ) @@ -172,6 +196,7 @@ def write_github_output(outputs: Outputs) -> None: f.write(f"run-ci-fuzz={bool_lower(outputs.run_ci_fuzz)}\n") f.write(f"run-docs={bool_lower(outputs.run_docs)}\n") f.write(f"run-tests={bool_lower(outputs.run_tests)}\n") + f.write(f"run-windows-tests={bool_lower(outputs.run_windows_tests)}\n") f.write(f"run-windows-msi={bool_lower(outputs.run_windows_msi)}\n") diff --git a/Tools/build/generate-build-details.py b/Tools/build/generate-build-details.py new file mode 100644 index 00000000000000..edf6d3e88da8d4 --- /dev/null +++ b/Tools/build/generate-build-details.py @@ -0,0 +1,192 @@ +"""Generate build-details.json (see PEP 739).""" + +# Script initially imported from: +# https://github.com/FFY00/python-instrospection/blob/main/python_introspection/scripts/generate-build-details.py + +import argparse +import collections +import importlib.machinery +import json +import os +import sys +import sysconfig +import traceback +import warnings + + +if False: # TYPE_CHECKING + pass + + +def version_info_to_dict(obj): # (object) -> dict[str, Any] + field_names = ('major', 'minor', 'micro', 'releaselevel', 'serial') + return {field: getattr(obj, field) for field in field_names} + + +def get_dict_key(container, key): # (dict[str, Any], str) -> dict[str, Any] + for part in key.split('.'): + container = container[part] + return container + + +def generate_data(schema_version): + """Generate the build-details.json data (PEP 739). + + :param schema_version: The schema version of the data we want to generate. + """ + + if schema_version != '1.0': + raise ValueError(f'Unsupported schema_version: {schema_version}') + + data = collections.defaultdict(lambda: collections.defaultdict(dict)) + + data['schema_version'] = schema_version + + data['base_prefix'] = sysconfig.get_config_var('installed_base') + #data['base_interpreter'] = sys._base_executable + data['base_interpreter'] = os.path.join( + sysconfig.get_path('scripts'), + 'python' + sysconfig.get_config_var('VERSION'), + ) + data['platform'] = sysconfig.get_platform() + + data['language']['version'] = sysconfig.get_python_version() + data['language']['version_info'] = version_info_to_dict(sys.version_info) + + data['implementation'] = vars(sys.implementation) + data['implementation']['version'] = version_info_to_dict(sys.implementation.version) + # Fix cross-compilation + if '_multiarch' in data['implementation']: + data['implementation']['_multiarch'] = sysconfig.get_config_var('MULTIARCH') + + data['abi']['flags'] = list(sys.abiflags) + + data['suffixes']['source'] = importlib.machinery.SOURCE_SUFFIXES + data['suffixes']['bytecode'] = importlib.machinery.BYTECODE_SUFFIXES + #data['suffixes']['optimized_bytecode'] = importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES + #data['suffixes']['debug_bytecode'] = importlib.machinery.DEBUG_BYTECODE_SUFFIXES + data['suffixes']['extensions'] = importlib.machinery.EXTENSION_SUFFIXES + + LIBDIR = sysconfig.get_config_var('LIBDIR') + LDLIBRARY = sysconfig.get_config_var('LDLIBRARY') + LIBRARY = sysconfig.get_config_var('LIBRARY') + PY3LIBRARY = sysconfig.get_config_var('PY3LIBRARY') + LIBPYTHON = sysconfig.get_config_var('LIBPYTHON') + LIBPC = sysconfig.get_config_var('LIBPC') + INCLUDEDIR = sysconfig.get_config_var('INCLUDEDIR') + + if os.name == 'posix': + # On POSIX, LIBRARY is always the static library, while LDLIBRARY is the + # dynamic library if enabled, otherwise it's the static library. + # If LIBRARY != LDLIBRARY, support for the dynamic library is enabled. + has_dynamic_library = LDLIBRARY != LIBRARY + has_static_library = sysconfig.get_config_var('STATIC_LIBPYTHON') + elif os.name == 'nt': + # Windows can only use a dynamic library or a static library. + # If it's using a dynamic library, sys.dllhandle will be set. + # Static builds on Windows are not really well supported, though. + # More context: https://github.com/python/cpython/issues/110234 + has_dynamic_library = hasattr(sys, 'dllhandle') + has_static_library = not has_dynamic_library + else: + raise NotADirectoryError(f'Unknown platform: {os.name}') + + # On POSIX, EXT_SUFFIX is set regardless if extension modules are supported + # or not, and on Windows older versions of CPython only set EXT_SUFFIX when + # extension modules are supported, but newer versions of CPython set it + # regardless. + # + # We only want to set abi.extension_suffix and stable_abi_suffix if + # extension modules are supported. + if has_dynamic_library: + data['abi']['extension_suffix'] = sysconfig.get_config_var('EXT_SUFFIX') + + # EXTENSION_SUFFIXES has been constant for a long time, and currently we + # don't have a better information source to find the stable ABI suffix. + for suffix in importlib.machinery.EXTENSION_SUFFIXES: + if suffix.startswith('.abi'): + data['abi']['stable_abi_suffix'] = suffix + break + + data['libpython']['dynamic'] = os.path.join(LIBDIR, LDLIBRARY) + # FIXME: Not sure if windows has a different dll for the stable ABI, and + # even if it does, currently we don't have a way to get its name. + if PY3LIBRARY: + data['libpython']['dynamic_stableabi'] = os.path.join(LIBDIR, PY3LIBRARY) + + # Os POSIX, this is defined by the LIBPYTHON Makefile variable not being + # empty. On Windows, don't link extensions — LIBPYTHON won't be defined, + data['libpython']['link_extensions'] = bool(LIBPYTHON) + + if has_static_library: + data['libpython']['static'] = os.path.join(LIBDIR, LIBRARY) + + data['c_api']['include'] = INCLUDEDIR + if LIBPC: + data['c_api']['pkgconfig_path'] = LIBPC + + return data + + +def make_paths_relative(data, config_path=None): # (dict[str, Any], str | None) -> None + # Make base_prefix relative to the config_path directory + if config_path: + data['base_prefix'] = os.path.relpath(data['base_prefix'], os.path.dirname(config_path)) + # Update path values to make them relative to base_prefix + PATH_KEYS = [ + 'base_interpreter', + 'libpython.dynamic', + 'libpython.dynamic_stableabi', + 'libpython.static', + 'c_api.headers', + 'c_api.pkgconfig_path', + ] + for entry in PATH_KEYS: + parent, _, child = entry.rpartition('.') + # Get the key container object + try: + container = data + for part in parent.split('.'): + container = container[part] + current_path = container[child] + except KeyError: + continue + # Get the relative path + new_path = os.path.relpath(current_path, data['base_prefix']) + # Join '.' so that the path is formated as './path' instead of 'path' + new_path = os.path.join('.', new_path) + container[child] = new_path + + +def main(): # () -> None + parser = argparse.ArgumentParser(exit_on_error=False) + parser.add_argument('location') + parser.add_argument( + '--schema-version', + default='1.0', + help='Schema version of the build-details.json file to generate.', + ) + parser.add_argument( + '--relative-paths', + action='store_true', + help='Whether to specify paths as absolute, or as relative paths to ``base_prefix``.', + ) + parser.add_argument( + '--config-file-path', + default=None, + help='If specified, ``base_prefix`` will be set as a relative path to the given config file path.', + ) + + args = parser.parse_args() + + data = generate_data(args.schema_version) + if args.relative_paths: + make_paths_relative(data, args.config_file_path) + + json_output = json.dumps(data, indent=2) + with open(args.location, 'w') as f: + print(json_output, file=f) + + +if __name__ == '__main__': + main() diff --git a/Tools/c-analyzer/TODO b/Tools/c-analyzer/TODO index edd0c4bc7fdaa6..d509489176b945 100644 --- a/Tools/c-analyzer/TODO +++ b/Tools/c-analyzer/TODO @@ -532,7 +532,7 @@ Python/pythonrun.c:PyId_stdin _Py_IDENTIFIER( Python/pythonrun.c:PyId_stdout _Py_IDENTIFIER(stdout) Python/pythonrun.c:PyRun_InteractiveOneObjectEx():PyId___main__ _Py_IDENTIFIER(__main__) Python/pythonrun.c:PyRun_InteractiveOneObjectEx():PyId_encoding _Py_IDENTIFIER(encoding) -Python/pythonrun.c:_Py_HandleSystemExit():PyId_code _Py_IDENTIFIER(code) +Python/pythonrun.c:_Py_HandleSystemExitAndKeyboardInterrupt():PyId_code _Py_IDENTIFIER(code) Python/pythonrun.c:parse_syntax_error():PyId_filename _Py_IDENTIFIER(filename) Python/pythonrun.c:parse_syntax_error():PyId_lineno _Py_IDENTIFIER(lineno) Python/pythonrun.c:parse_syntax_error():PyId_msg _Py_IDENTIFIER(msg) diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index c127d0334d9cf8..295bcc87b2cadf 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -602,7 +602,6 @@ def has_error_without_pop(op: parser.CodeDef) -> bool: "PyTuple_GET_ITEM", "PyTuple_GET_SIZE", "PyType_HasFeature", - "PyUnicode_Append", "PyUnicode_Concat", "PyUnicode_GET_LENGTH", "PyUnicode_READ_CHAR", @@ -619,7 +618,6 @@ def has_error_without_pop(op: parser.CodeDef) -> bool: "_PyCode_CODE", "_PyDictValues_AddToInsertionOrder", "_PyErr_Occurred", - "_PyEval_FrameClearAndPop", "_PyFloat_FromDouble_ConsumeInputs", "_PyFrame_GetBytecode", "_PyFrame_GetCode", @@ -633,15 +631,12 @@ def has_error_without_pop(op: parser.CodeDef) -> bool: "_PyList_AppendTakeRef", "_PyList_FromStackRefStealOnSuccess", "_PyList_ITEMS", - "_PyLong_Add", "_PyLong_CompactValue", "_PyLong_DigitCount", "_PyLong_IsCompact", "_PyLong_IsNegative", "_PyLong_IsNonNegativeCompact", "_PyLong_IsZero", - "_PyLong_Multiply", - "_PyLong_Subtract", "_PyManagedDictPointer_IsValues", "_PyObject_GC_IS_TRACKED", "_PyObject_GC_MAY_BE_TRACKED", diff --git a/Tools/cases_generator/cwriter.py b/Tools/cases_generator/cwriter.py index 8cba9127fa3071..07a785e4312fa6 100644 --- a/Tools/cases_generator/cwriter.py +++ b/Tools/cases_generator/cwriter.py @@ -15,6 +15,8 @@ def __init__(self, out: TextIO, indent: int, line_directives: bool): self.line_directives = line_directives self.last_token = None self.newline = True + self.pending_spill = False + self.pending_reload = False def set_position(self, tkn: Token) -> None: if self.last_token is not None: @@ -33,6 +35,7 @@ def set_position(self, tkn: Token) -> None: self.newline = False def emit_at(self, txt: str, where: Token) -> None: + self.maybe_write_spill() self.set_position(where) self.out.write(txt) @@ -109,6 +112,7 @@ def emit_str(self, txt: str) -> None: self.last_token = None def emit(self, txt: str | Token) -> None: + self.maybe_write_spill() if isinstance(txt, Token): self.emit_token(txt) elif isinstance(txt, str): @@ -122,6 +126,28 @@ def start_line(self) -> None: self.newline = True self.last_token = None + def emit_spill(self) -> None: + if self.pending_reload: + self.pending_reload = False + return + assert not self.pending_spill + self.pending_spill = True + + def maybe_write_spill(self) -> None: + if self.pending_spill: + self.pending_spill = False + self.emit_str("_PyFrame_SetStackPointer(frame, stack_pointer);\n") + elif self.pending_reload: + self.pending_reload = False + self.emit_str("stack_pointer = _PyFrame_GetStackPointer(frame);\n") + + def emit_reload(self) -> None: + if self.pending_spill: + self.pending_spill = False + return + assert not self.pending_reload + self.pending_reload = True + @contextlib.contextmanager def header_guard(self, name: str) -> Iterator[None]: self.out.write( diff --git a/Tools/cases_generator/generators_common.py b/Tools/cases_generator/generators_common.py index cd52f181b60e43..6b2ef51b29f4eb 100644 --- a/Tools/cases_generator/generators_common.py +++ b/Tools/cases_generator/generators_common.py @@ -243,29 +243,13 @@ def decref_inputs( next(tkn_iter) next(tkn_iter) next(tkn_iter) - self.out.emit_at("", tkn) - for var in storage.inputs: - if not var.defined: - continue - if var.name == "null": - continue - close = "PyStackRef_CLOSE" - if "null" in var.name or var.condition and var.condition != "1": - close = "PyStackRef_XCLOSE" - if var.size: - if var.size == "1": - self.out.emit(f"{close}({var.name}[0]);\n") - else: - self.out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n") - self.out.emit(f"{close}({var.name}[_i]);\n") - self.out.emit("}\n") - elif var.condition: - if var.condition != "0": - self.out.emit(f"{close}({var.name});\n") - else: - self.out.emit(f"{close}({var.name});\n") - for input in storage.inputs: - input.defined = False + try: + storage.close_inputs(self.out) + except StackError as ex: + raise analysis_error(ex.args[0], tkn) + except Exception as ex: + ex.args = (ex.args[0] + str(tkn),) + raise return True def kill_inputs( @@ -301,7 +285,9 @@ def kill( var.defined = False break else: - raise analysis_error(f"'{name}' is not a live input-only variable", name_tkn) + raise analysis_error( + f"'{name}' is not a live input-only variable", name_tkn + ) return True def stackref_kill( @@ -344,7 +330,7 @@ def stackref_close_specialized( self.out.emit(comma) dealloc = next(tkn_iter) if dealloc.kind != "IDENTIFIER": - raise analysis_error("Expected identifier", dealloc) + raise analysis_error("Expected identifier", dealloc) self.out.emit(dealloc) if name.kind == "IDENTIFIER": escapes = dealloc.text not in NON_ESCAPING_DEALLOCS @@ -518,7 +504,7 @@ def _emit_if( self.emit(next(tkn_iter)) maybe_if = tkn_iter.peek() if maybe_if and maybe_if.kind == "IF": - #Emit extra braces around the if to get scoping right + # Emit extra braces around the if to get scoping right self.emit(" {\n") self.emit(next(tkn_iter)) else_reachable, rbrace, else_storage = self._emit_if(tkn_iter, uop, storage, inst) diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index 6c33debd58e1fe..b679ec84707aae 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -154,11 +154,11 @@ def write_uop( var.defined = False storage = emitter.emit_tokens(override, storage, None) out.start_line() - storage.flush(out, cast_type="JitOptSymbol *") + storage.flush(out) else: emit_default(out, uop, stack) out.start_line() - stack.flush(out, cast_type="JitOptSymbol *") + stack.flush(out) except StackError as ex: raise analysis_error(ex.args[0], prototype.body[0]) # from None @@ -201,7 +201,7 @@ def generate_abstract_interpreter( declare_variables(override, out, skip_inputs=False) else: declare_variables(uop, out, skip_inputs=True) - stack = Stack(False) + stack = Stack(extract_bits=False, cast_type="JitOptSymbol *") write_uop(override, uop, out, stack, debug, skip_inputs=(override is None)) out.start_line() out.emit("break;\n") diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py index 729973f1e32758..7866857023f952 100644 --- a/Tools/cases_generator/stack.py +++ b/Tools/cases_generator/stack.py @@ -224,12 +224,13 @@ def array_or_scalar(var: StackItem | Local) -> str: return "array" if var.is_array() else "scalar" class Stack: - def __init__(self, extract_bits: bool=True) -> None: + def __init__(self, extract_bits: bool=True, cast_type: str = "uintptr_t") -> None: self.top_offset = StackOffset.empty() self.base_offset = StackOffset.empty() self.variables: list[Local] = [] self.defined: set[str] = set() self.extract_bits = extract_bits + self.cast_type = cast_type def pop(self, var: StackItem) -> tuple[str, Local]: self.top_offset.pop(var) @@ -298,8 +299,8 @@ def _do_emit( out: CWriter, var: StackItem, base_offset: StackOffset, - cast_type: str = "uintptr_t", - extract_bits: bool = True, + cast_type: str, + extract_bits: bool, ) -> None: cast = f"({cast_type})" if var.type else "" bits = ".bits" if cast and extract_bits else "" @@ -315,9 +316,7 @@ def _adjust_stack_pointer(self, out: CWriter, number: str) -> None: out.emit(f"stack_pointer += {number};\n") out.emit("assert(WITHIN_STACK_BOUNDS());\n") - def flush( - self, out: CWriter, cast_type: str = "uintptr_t" - ) -> None: + def flush(self, out: CWriter) -> None: out.start_line() var_offset = self.base_offset.copy() for var in self.variables: @@ -325,7 +324,7 @@ def flush( var.defined and not var.in_memory ): - Stack._do_emit(out, var.item, var_offset, cast_type, self.extract_bits) + Stack._do_emit(out, var.item, var_offset, self.cast_type, self.extract_bits) var.in_memory = True var_offset.push(var.item) number = self.top_offset.to_c() @@ -347,7 +346,7 @@ def as_comment(self) -> str: ) def copy(self) -> "Stack": - other = Stack(self.extract_bits) + other = Stack(self.extract_bits, self.cast_type) other.top_offset = self.top_offset.copy() other.base_offset = self.base_offset.copy() other.variables = [var.copy() for var in self.variables] @@ -508,17 +507,26 @@ def locals_cached(self) -> bool: return True return False - def flush(self, out: CWriter, cast_type: str = "uintptr_t") -> None: + def flush(self, out: CWriter) -> None: self.clear_dead_inputs() self._push_defined_outputs() - self.stack.flush(out, cast_type) + self.stack.flush(out) def save(self, out: CWriter) -> None: assert self.spilled >= 0 if self.spilled == 0: self.flush(out) out.start_line() - out.emit("_PyFrame_SetStackPointer(frame, stack_pointer);\n") + out.emit_spill() + self.spilled += 1 + + def save_inputs(self, out: CWriter) -> None: + assert self.spilled >= 0 + if self.spilled == 0: + self.clear_dead_inputs() + self.stack.flush(out) + out.start_line() + out.emit_spill() self.spilled += 1 def reload(self, out: CWriter) -> None: @@ -528,7 +536,7 @@ def reload(self, out: CWriter) -> None: self.spilled -= 1 if self.spilled == 0: out.start_line() - out.emit("stack_pointer = _PyFrame_GetStackPointer(frame);\n") + out.emit_reload() @staticmethod def for_uop(stack: Stack, uop: Uop) -> tuple[list[str], "Storage"]: @@ -637,3 +645,91 @@ def as_comment(self) -> str: outputs = ", ".join([var.compact_str() for var in self.outputs]) peeks = ", ".join([var.name for var in self.peeks]) return f"{stack_comment[:-2]}{next_line}inputs: {inputs}{next_line}outputs: {outputs}{next_line}peeks: {peeks} */" + + def close_inputs(self, out: CWriter) -> None: + tmp_defined = False + def close_named(close: str, name: str, overwrite: str) -> None: + nonlocal tmp_defined + if overwrite: + if not tmp_defined: + out.emit("_PyStackRef ") + tmp_defined = True + out.emit(f"tmp = {name};\n") + out.emit(f"{name} = {overwrite};\n") + if not var.is_array(): + var.in_memory = False + self.flush(out) + out.emit(f"{close}(tmp);\n") + else: + out.emit(f"{close}({name});\n") + + def close_variable(var: Local, overwrite: str) -> None: + nonlocal tmp_defined + close = "PyStackRef_CLOSE" + if "null" in var.name or var.condition and var.condition != "1": + close = "PyStackRef_XCLOSE" + if var.size: + if var.size == "1": + close_named(close, f"{var.name}[0]", overwrite) + else: + if overwrite and not tmp_defined: + out.emit("_PyStackRef tmp;\n") + tmp_defined = True + out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n") + close_named(close, f"{var.name}[_i]", overwrite) + out.emit("}\n") + else: + if var.condition and var.condition == "0": + return + close_named(close, var.name, overwrite) + + self.clear_dead_inputs() + if not self.inputs: + return + output: Local | None = None + for var in self.outputs: + if var.is_array(): + if len(self.inputs) > 1: + raise StackError("Cannot call DECREF_INPUTS with multiple live input(s) and array output") + elif var.defined: + if output is not None: + raise StackError("Cannot call DECREF_INPUTS with more than one live output") + output = var + self.save_inputs(out) + if output is not None: + lowest = self.inputs[0] + if lowest.is_array(): + try: + size = int(lowest.size) + except: + size = -1 + if size <= 0: + raise StackError("Cannot call DECREF_INPUTS with non fixed size array as lowest input on stack") + if size > 1: + raise StackError("Cannot call DECREF_INPUTS with array size > 1 as lowest input on stack") + output.defined = False + close_variable(lowest, output.name) + else: + lowest.in_memory = False + output.defined = False + close_variable(lowest, output.name) + to_close = self.inputs[: 0 if output is not None else None: -1] + if len(to_close) == 1 and not to_close[0].is_array(): + self.reload(out) + to_close[0].defined = False + self.flush(out) + self.save_inputs(out) + close_variable(to_close[0], "") + self.reload(out) + else: + for var in to_close: + assert var.defined or var.is_array() + close_variable(var, "PyStackRef_NULL") + self.reload(out) + for var in self.inputs: + var.defined = False + if output is not None: + output.defined = True + # MyPy false positive + lowest.defined = False # type: ignore[possibly-undefined] + self.flush(out) diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index d8a0e379ab82cb..4177d46048f9b9 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -67,7 +67,8 @@ -k word --keyword=word Keywords to look for in addition to the default set, which are: - %(DEFAULTKEYWORDS)s + _, gettext, ngettext, pgettext, npgettext, dgettext, dngettext, + dpgettext, and dnpgettext. You can have multiple -k flags on the command line. @@ -140,8 +141,6 @@ import os import sys import time -import tokenize -from collections import defaultdict from dataclasses import dataclass, field from operator import itemgetter @@ -171,7 +170,7 @@ def usage(code, msg=''): - print(__doc__ % globals(), file=sys.stderr) + print(__doc__, file=sys.stderr) if msg: print(msg, file=sys.stderr) sys.exit(code) @@ -206,15 +205,6 @@ def escape_nonascii(s, encoding): return ''.join(escapes[b] for b in s.encode(encoding)) -def is_literal_string(s): - return s[0] in '\'"' or (s[0] in 'rRuU' and s[1] in '\'"') - - -def safe_eval(s): - # unwrap quotes, safely - return eval(s, {'__builtins__':{}}, {}) - - def normalize(s, encoding): # This converts the various Python string types into a format that is # appropriate for .po files, namely much closer to C style. @@ -296,11 +286,6 @@ def getFilesForName(name): } -def matches_spec(message, spec): - """Check if a message has all the keys defined by the keyword spec.""" - return all(key in message for key in spec.values()) - - @dataclass(frozen=True) class Location: filename: str @@ -325,203 +310,91 @@ def add_location(self, filename, lineno, msgid_plural=None, *, is_docstring=Fals self.is_docstring |= is_docstring -class TokenEater: +class GettextVisitor(ast.NodeVisitor): def __init__(self, options): - self.__options = options - self.__messages = {} - self.__state = self.__waiting - self.__data = defaultdict(str) - self.__curr_arg = 0 - self.__curr_keyword = None - self.__lineno = -1 - self.__freshmodule = 1 - self.__curfile = None - self.__enclosurecount = 0 - - def __call__(self, ttype, tstring, stup, etup, line): - # dispatch -## import token -## print('ttype:', token.tok_name[ttype], 'tstring:', tstring, -## file=sys.stderr) - self.__state(ttype, tstring, stup[0]) - - @property - def messages(self): - return self.__messages - - def __waiting(self, ttype, tstring, lineno): - opts = self.__options - # Do docstring extractions, if enabled - if opts.docstrings and not opts.nodocstrings.get(self.__curfile): - # module docstring? - if self.__freshmodule: - if ttype == tokenize.STRING and is_literal_string(tstring): - self.__addentry({'msgid': safe_eval(tstring)}, lineno, is_docstring=True) - self.__freshmodule = 0 - return - if ttype in (tokenize.COMMENT, tokenize.NL, tokenize.ENCODING): - return - self.__freshmodule = 0 - # class or func/method docstring? - if ttype == tokenize.NAME and tstring in ('class', 'def'): - self.__state = self.__suiteseen - return - if ttype == tokenize.NAME and tstring in ('class', 'def'): - self.__state = self.__ignorenext + super().__init__() + self.options = options + self.filename = None + self.messages = {} + + def visit_file(self, node, filename): + self.filename = filename + self.visit(node) + + def visit_Module(self, node): + self._extract_docstring(node) + self.generic_visit(node) + + visit_ClassDef = visit_FunctionDef = visit_AsyncFunctionDef = visit_Module + + def visit_Call(self, node): + self._extract_message(node) + self.generic_visit(node) + + def _extract_docstring(self, node): + if (not self.options.docstrings or + self.options.nodocstrings.get(self.filename)): return - if ttype == tokenize.NAME and tstring in opts.keywords: - self.__state = self.__keywordseen - self.__curr_keyword = tstring + + docstring = ast.get_docstring(node) + if docstring is not None: + lineno = node.body[0].lineno # The first statement is the docstring + self._add_message(lineno, docstring, is_docstring=True) + + def _extract_message(self, node): + func_name = self._get_func_name(node) + spec = self.options.keywords.get(func_name) + if spec is None: + return + + max_index = max(spec) + has_var_positional = any(isinstance(arg, ast.Starred) for + arg in node.args[:max_index+1]) + if has_var_positional: + print(f'*** {self.filename}:{node.lineno}: Variable positional ' + f'arguments are not allowed in gettext calls', file=sys.stderr) return - if ttype == tokenize.STRING: - maybe_fstring = ast.parse(tstring, mode='eval').body - if not isinstance(maybe_fstring, ast.JoinedStr): - return - for value in filter(lambda node: isinstance(node, ast.FormattedValue), - maybe_fstring.values): - for call in filter(lambda node: isinstance(node, ast.Call), - ast.walk(value)): - func = call.func - if isinstance(func, ast.Name): - func_name = func.id - elif isinstance(func, ast.Attribute): - func_name = func.attr - else: - continue - - if func_name not in opts.keywords: - continue - if len(call.args) != 1: - print(( - '*** %(file)s:%(lineno)s: Seen unexpected amount of' - ' positional arguments in gettext call: %(source_segment)s' - ) % { - 'source_segment': ast.get_source_segment(tstring, call) or tstring, - 'file': self.__curfile, - 'lineno': lineno - }, file=sys.stderr) - continue - if call.keywords: - print(( - '*** %(file)s:%(lineno)s: Seen unexpected keyword arguments' - ' in gettext call: %(source_segment)s' - ) % { - 'source_segment': ast.get_source_segment(tstring, call) or tstring, - 'file': self.__curfile, - 'lineno': lineno - }, file=sys.stderr) - continue - arg = call.args[0] - if not isinstance(arg, ast.Constant): - print(( - '*** %(file)s:%(lineno)s: Seen unexpected argument type' - ' in gettext call: %(source_segment)s' - ) % { - 'source_segment': ast.get_source_segment(tstring, call) or tstring, - 'file': self.__curfile, - 'lineno': lineno - }, file=sys.stderr) - continue - if isinstance(arg.value, str): - self.__curr_keyword = func_name - self.__addentry({'msgid': arg.value}, lineno) - - def __suiteseen(self, ttype, tstring, lineno): - # skip over any enclosure pairs until we see the colon - if ttype == tokenize.OP: - if tstring == ':' and self.__enclosurecount == 0: - # we see a colon and we're not in an enclosure: end of def - self.__state = self.__suitedocstring - elif tstring in '([{': - self.__enclosurecount += 1 - elif tstring in ')]}': - self.__enclosurecount -= 1 - - def __suitedocstring(self, ttype, tstring, lineno): - # ignore any intervening noise - if ttype == tokenize.STRING and is_literal_string(tstring): - self.__addentry({'msgid': safe_eval(tstring)}, lineno, is_docstring=True) - self.__state = self.__waiting - elif ttype not in (tokenize.NEWLINE, tokenize.INDENT, - tokenize.COMMENT): - # there was no class docstring - self.__state = self.__waiting - - def __keywordseen(self, ttype, tstring, lineno): - if ttype == tokenize.OP and tstring == '(': - self.__data.clear() - self.__curr_arg = 0 - self.__enclosurecount = 0 - self.__lineno = lineno - self.__state = self.__openseen - else: - self.__state = self.__waiting - - def __openseen(self, ttype, tstring, lineno): - spec = self.__options.keywords[self.__curr_keyword] - arg_type = spec.get(self.__curr_arg) - expect_string_literal = arg_type is not None - - if ttype == tokenize.OP and self.__enclosurecount == 0: - if tstring == ')': - # We've seen the last of the translatable strings. Record the - # line number of the first line of the strings and update the list - # of messages seen. Reset state for the next batch. If there - # were no strings inside _(), then just ignore this entry. - if self.__data: - self.__addentry(self.__data) - self.__state = self.__waiting - return - elif tstring == ',': - # Advance to the next argument - self.__curr_arg += 1 - return - if expect_string_literal: - if ttype == tokenize.STRING and is_literal_string(tstring): - self.__data[arg_type] += safe_eval(tstring) - elif ttype not in (tokenize.COMMENT, tokenize.INDENT, tokenize.DEDENT, - tokenize.NEWLINE, tokenize.NL): - # We are inside an argument which is a translatable string and - # we encountered a token that is not a string. This is an error. - self.warn_unexpected_token(tstring) - self.__enclosurecount = 0 - self.__state = self.__waiting - elif ttype == tokenize.OP: - if tstring in '([{': - self.__enclosurecount += 1 - elif tstring in ')]}': - self.__enclosurecount -= 1 - - def __ignorenext(self, ttype, tstring, lineno): - self.__state = self.__waiting - - def __addentry(self, msg, lineno=None, *, is_docstring=False): - msgid = msg.get('msgid') - if msgid in self.__options.toexclude: + if max_index >= len(node.args): + print(f'*** {self.filename}:{node.lineno}: Expected at least ' + f'{max(spec) + 1} positional argument(s) in gettext call, ' + f'got {len(node.args)}', file=sys.stderr) return - if not is_docstring: - spec = self.__options.keywords[self.__curr_keyword] - if not matches_spec(msg, spec): + + msg_data = {} + for position, arg_type in spec.items(): + arg = node.args[position] + if not self._is_string_const(arg): + print(f'*** {self.filename}:{arg.lineno}: Expected a string ' + f'constant for argument {position + 1}, ' + f'got {ast.unparse(arg)}', file=sys.stderr) return - if lineno is None: - lineno = self.__lineno - msgctxt = msg.get('msgctxt') - msgid_plural = msg.get('msgid_plural') + msg_data[arg_type] = arg.value + + lineno = node.lineno + self._add_message(lineno, **msg_data) + + def _add_message( + self, lineno, msgid, msgid_plural=None, msgctxt=None, *, + is_docstring=False): + if msgid in self.options.toexclude: + return + key = self._key_for(msgid, msgctxt) - if key in self.__messages: - self.__messages[key].add_location( - self.__curfile, + message = self.messages.get(key) + if message: + message.add_location( + self.filename, lineno, msgid_plural, is_docstring=is_docstring, ) else: - self.__messages[key] = Message( + self.messages[key] = Message( msgid=msgid, msgid_plural=msgid_plural, msgctxt=msgctxt, - locations={Location(self.__curfile, lineno)}, + locations={Location(self.filename, lineno)}, is_docstring=is_docstring, ) @@ -531,19 +404,17 @@ def _key_for(msgid, msgctxt=None): return (msgctxt, msgid) return msgid - def warn_unexpected_token(self, token): - print(( - '*** %(file)s:%(lineno)s: Seen unexpected token "%(token)s"' - ) % { - 'token': token, - 'file': self.__curfile, - 'lineno': self.__lineno - }, file=sys.stderr) - - def set_filename(self, filename): - self.__curfile = filename - self.__freshmodule = 1 + def _get_func_name(self, node): + match node.func: + case ast.Name(id=id): + return id + case ast.Attribute(attr=attr): + return attr + case _: + return None + def _is_string_const(self, node): + return isinstance(node, ast.Constant) and isinstance(node.value, str) def write_pot_file(messages, options, fp): timestamp = time.strftime('%Y-%m-%d %H:%M%z') @@ -717,31 +588,24 @@ class Options: args = expanded # slurp through all the files - eater = TokenEater(options) + visitor = GettextVisitor(options) for filename in args: if filename == '-': if options.verbose: print('Reading standard input') - fp = sys.stdin.buffer - closep = 0 + source = sys.stdin.buffer.read() else: if options.verbose: print(f'Working on {filename}') - fp = open(filename, 'rb') - closep = 1 + with open(filename, 'rb') as fp: + source = fp.read() + try: - eater.set_filename(filename) - try: - tokens = tokenize.tokenize(fp.readline) - for _token in tokens: - eater(*_token) - except tokenize.TokenError as e: - print('%s: %s, line %d, column %d' % ( - e.args[0], filename, e.args[1][0], e.args[1][1]), - file=sys.stderr) - finally: - if closep: - fp.close() + module_tree = ast.parse(source) + except SyntaxError: + continue + + visitor.visit_file(module_tree, filename) # write the output if options.outfile == '-': @@ -753,7 +617,7 @@ class Options: fp = open(options.outfile, 'w') closep = 1 try: - write_pot_file(eater.messages, options, fp) + write_pot_file(visitor.messages, options, fp) finally: if closep: fp.close() diff --git a/Tools/jit/_writer.py b/Tools/jit/_writer.py index 5588784544ee00..090b52660f009c 100644 --- a/Tools/jit/_writer.py +++ b/Tools/jit/_writer.py @@ -49,15 +49,16 @@ def _dump_stencil(opname: str, group: _stencils.StencilGroup) -> typing.Iterator for part, stencil in [("code", group.code), ("data", group.data)]: for line in stencil.disassembly: yield f" // {line}" - if stencil.body: + stripped = stencil.body.rstrip(b"\x00") + if stripped: yield f" const unsigned char {part}_body[{len(stencil.body)}] = {{" - for i in range(0, len(stencil.body), 8): - row = " ".join(f"{byte:#04x}," for byte in stencil.body[i : i + 8]) + for i in range(0, len(stripped), 8): + row = " ".join(f"{byte:#04x}," for byte in stripped[i : i + 8]) yield f" {row}" yield " };" # Data is written first (so relaxations in the code work properly): for part, stencil in [("data", group.data), ("code", group.code)]: - if stencil.body: + if stencil.body.rstrip(b"\x00"): yield f" memcpy({part}, {part}_body, sizeof({part}_body));" skip = False stencil.holes.sort(key=lambda hole: hole.offset) diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt index c2509cae7b9e9d..e4cf2a76db35cc 100644 --- a/Tools/tsan/suppressions_free_threading.txt +++ b/Tools/tsan/suppressions_free_threading.txt @@ -49,5 +49,8 @@ race_top:rangeiter_next # gh-129748: test.test_free_threading.test_slots.TestSlots.test_object race_top:mi_block_set_nextx +# gh-127266: type slot updates are not thread-safe (test_opcache.test_load_attr_method_lazy_dict) +race_top:update_one_slot + # https://gist.github.com/mpage/6962e8870606cfc960e159b407a0cb40 thread:pthread_create diff --git a/configure b/configure index d46bc563a67245..453b0123ded0a4 100755 --- a/configure +++ b/configure @@ -29284,18 +29284,6 @@ esac fi -# Do not enable tail-calling interpreter if tier 2 is enabled. -if ${tier2_flags:+false} : -then : - - case "$ac_cv_tail_call" in yes*) - -printf "%s\n" "#define Py_TAIL_CALL_INTERP 1" >>confdefs.h - - esac - -fi - case $ac_sys_system in AIX*) diff --git a/configure.ac b/configure.ac index faa8909530389d..234ae90616af62 100644 --- a/configure.ac +++ b/configure.ac @@ -7033,19 +7033,6 @@ fi ], [AC_MSG_RESULT([no value specified])]) -# Do not enable tail-calling interpreter if tier 2 is enabled. -AS_VAR_IF( - [tier2_flags], - [], - [ - case "$ac_cv_tail_call" in yes*) - AC_DEFINE([Py_TAIL_CALL_INTERP], [1], - [Define if the C compiler supports efficient proper tail calls.]) - esac - ], - [] -) - case $ac_sys_system in AIX*) diff --git a/iOS/testbed/__main__.py b/iOS/testbed/__main__.py index b4499f5ac171a8..08fbe90a1c6aef 100644 --- a/iOS/testbed/__main__.py +++ b/iOS/testbed/__main__.py @@ -230,33 +230,69 @@ def clone_testbed( shutil.copytree(source, target, symlinks=True) print(" done") + xc_framework_path = target / "Python.xcframework" + sim_framework_path = xc_framework_path / "ios-arm64_x86_64-simulator" if framework is not None: if framework.suffix == ".xcframework": print(" Installing XCFramework...", end="", flush=True) - xc_framework_path = (target / "Python.xcframework").resolve() if xc_framework_path.is_dir(): shutil.rmtree(xc_framework_path) else: - xc_framework_path.unlink() + xc_framework_path.unlink(missing_ok=True) xc_framework_path.symlink_to( framework.relative_to(xc_framework_path.parent, walk_up=True) ) print(" done") else: print(" Installing simulator framework...", end="", flush=True) - sim_framework_path = ( - target / "Python.xcframework" / "ios-arm64_x86_64-simulator" - ).resolve() if sim_framework_path.is_dir(): shutil.rmtree(sim_framework_path) else: - sim_framework_path.unlink() + sim_framework_path.unlink(missing_ok=True) sim_framework_path.symlink_to( framework.relative_to(sim_framework_path.parent, walk_up=True) ) print(" done") else: - print(" Using pre-existing iOS framework.") + if ( + xc_framework_path.is_symlink() + and not xc_framework_path.readlink().is_absolute() + ): + # XCFramework is a relative symlink. Rewrite the symlink relative + # to the new location. + print(" Rewriting symlink to XCframework...", end="", flush=True) + orig_xc_framework_path = ( + source + / xc_framework_path.readlink() + ).resolve() + xc_framework_path.unlink() + xc_framework_path.symlink_to( + orig_xc_framework_path.relative_to( + xc_framework_path.parent, walk_up=True + ) + ) + print(" done") + elif ( + sim_framework_path.is_symlink() + and not sim_framework_path.readlink().is_absolute() + ): + print(" Rewriting symlink to simulator framework...", end="", flush=True) + # Simulator framework is a relative symlink. Rewrite the symlink + # relative to the new location. + orig_sim_framework_path = ( + source + / "Python.XCframework" + / sim_framework_path.readlink() + ).resolve() + sim_framework_path.unlink() + sim_framework_path.symlink_to( + orig_sim_framework_path.relative_to( + sim_framework_path.parent, walk_up=True + ) + ) + print(" done") + else: + print(" Using pre-existing iOS framework.") for app_src in apps: print(f" Installing app {app_src.name!r}...", end="", flush=True) @@ -372,8 +408,8 @@ def main(): if context.subcommand == "clone": clone_testbed( - source=Path(__file__).parent, - target=Path(context.location), + source=Path(__file__).parent.resolve(), + target=Path(context.location).resolve(), framework=Path(context.framework).resolve() if context.framework else None, apps=[Path(app) for app in context.apps], ) diff --git a/pyconfig.h.in b/pyconfig.h.in index 9ea01ad3fc0a31..4295b4f5ea5fbd 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1718,7 +1718,7 @@ /* The version of SunOS/Solaris as reported by `uname -r' without the dot. */ #undef Py_SUNOS_VERSION -/* Define if the C compiler supports efficient proper tail calls. */ +/* Define if you want to use tail-calling interpreters in CPython. */ #undef Py_TAIL_CALL_INTERP /* Define if you want to enable tracing references for debugging purpose */