diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d40519e40d3cc2..d218f029a990bf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -22,6 +22,7 @@ configure* @erlend-aasland @corona10 **/*hamt* @1st1 Objects/set* @rhettinger Objects/dict* @methane @markshannon +Objects/typevarobject.c @JelleZijlstra Objects/type* @markshannon Objects/codeobject.c @markshannon Objects/frameobject.c @markshannon @@ -33,6 +34,7 @@ Python/flowgraph.c @markshannon @iritkatriel Python/ast_opt.c @isidentical Lib/test/test_patma.py @brandtbucher Lib/test/test_peepholer.py @brandtbucher +Lib/test/test_type_*.py @JelleZijlstra # Exceptions Lib/traceback.py @iritkatriel @@ -95,6 +97,8 @@ Include/pytime.h @pganssle @abalkin /Tools/peg_generator/ @pablogsal @lysnikolaou /Lib/test/test_peg_generator/ @pablogsal @lysnikolaou /Grammar/python.gram @pablogsal @lysnikolaou +/Lib/tokenize.py @pablogsal @lysnikolaou +/Lib/test/test_tokenize.py @pablogsal @lysnikolaou # AST Python/ast.c @isidentical diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 69b78e5567adb1..b9797192dba054 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ on: push: branches: - 'main' + - '3.12' - '3.11' - '3.10' - '3.9' @@ -16,6 +17,7 @@ on: pull_request: branches: - 'main' + - '3.12' - '3.11' - '3.10' - '3.9' @@ -368,6 +370,14 @@ jobs: echo "HYPOVENV=${VENV_LOC}" >> $GITHUB_ENV echo "VENV_PYTHON=${VENV_PYTHON}" >> $GITHUB_ENV ./python -m venv $VENV_LOC && $VENV_PYTHON -m pip install -U hypothesis + - name: 'Restore Hypothesis database' + id: cache-hypothesis-database + uses: actions/cache@v3 + with: + path: ./hypothesis + key: hypothesis-database-${{ github.head_ref || github.run_id }} + restore-keys: | + - hypothesis-database- - name: "Run tests" working-directory: ${{ env.CPYTHON_BUILDDIR }} run: | @@ -388,6 +398,11 @@ jobs: -x test_subprocess \ -x test_signal \ -x test_sysconfig + - uses: actions/upload-artifact@v3 + if: always() + with: + name: hypothesis-example-db + path: .hypothesis/examples/ build_asan: diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 3f7550cc72943b..ec900ce68a1dde 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -5,6 +5,7 @@ on: #push: # branches: # - 'main' + # - '3.12' # - '3.11' # - '3.10' # - '3.9' @@ -15,6 +16,7 @@ on: pull_request: branches: - 'main' + - '3.12' - '3.11' - '3.10' - '3.9' diff --git a/.gitignore b/.gitignore index d9c4a7972f076d..dddf28da016192 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,10 @@ *.gc?? *.profclang? *.profraw +# Copies of binaries before BOLT optimizations. +*.prebolt +# BOLT profile data. +*.fdata *.dyn .gdb_history .purify @@ -57,7 +61,6 @@ Doc/.venv/ Doc/env/ Doc/.env/ Include/pydtrace_probes.h -Lib/lib2to3/*.pickle Lib/site-packages/* !Lib/site-packages/README.txt Lib/test/data/* @@ -124,6 +127,7 @@ Tools/unicode/data/ /platform /profile-clean-stamp /profile-run-stamp +/profile-bolt-stamp /Python/deepfreeze/*.c /pybuilddir.txt /pyconfig.h diff --git a/Doc/c-api/frame.rst b/Doc/c-api/frame.rst index 1ac8f03d6e48f8..9f7addfbbf3cb4 100644 --- a/Doc/c-api/frame.rst +++ b/Doc/c-api/frame.rst @@ -130,3 +130,38 @@ See also :ref:`Reflection `. .. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame) Return the line number that *frame* is currently executing. + + + +Internal Frames +--------------- + +Unless using :pep:`523`, you will not need this. + +.. c:struct:: _PyInterpreterFrame + + The interpreter's internal frame representation. + + .. versionadded:: 3.11 + +.. c:function:: PyObject* PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame); + + Return a :term:`strong reference` to the code object for the frame. + + .. versionadded:: 3.12 + + +.. c:function:: int PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame); + + Return the byte offset into the last executed instruction. + + .. versionadded:: 3.12 + + +.. c:function:: int PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame); + + Return the currently executing line number, or -1 if there is no line number. + + .. versionadded:: 3.12 + + diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 4a71c89ad85d31..5c1d026a330ae7 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -322,3 +322,27 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. with :c:func:`PyLong_FromVoidPtr`. Returns ``NULL`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. + + +.. c:function:: int PyUnstable_Long_IsCompact(const PyLongObject* op) + + Return 1 if *op* is compact, 0 otherwise. + + This function makes it possible for performance-critical code to implement + a “fast path” for small integers. For compact values use + :c:func:`PyUnstable_Long_CompactValue`; for others fall back to a + :c:func:`PyLong_As* ` function or + :c:func:`calling ` :meth:`int.to_bytes`. + + The speedup is expected to be negligible for most users. + + Exactly what values are considered compact is an implementation detail + and is subject to change. + +.. c:function:: Py_ssize_t PyUnstable_Long_CompactValue(const PyLongObject* op) + + If *op* is compact, as determined by :c:func:`PyUnstable_Long_IsCompact`, + return its value. + + Otherwise, the return value is undefined. + diff --git a/Doc/c-api/perfmaps.rst b/Doc/c-api/perfmaps.rst new file mode 100644 index 00000000000000..3d44d2eb6bf41d --- /dev/null +++ b/Doc/c-api/perfmaps.rst @@ -0,0 +1,50 @@ +.. highlight:: c + +.. _perfmaps: + +Support for Perf Maps +---------------------- + +On supported platforms (as of this writing, only Linux), the runtime can take +advantage of *perf map files* to make Python functions visible to an external +profiling tool (such as `perf `_). +A running process may create a file in the ``/tmp`` directory, which contains entries +that can map a section of executable code to a name. This interface is described in the +`documentation of the Linux Perf tool `_. + +In Python, these helper APIs can be used by libraries and features that rely +on generating machine code on the fly. + +Note that holding the Global Interpreter Lock (GIL) is not required for these APIs. + +.. c:function:: int PyUnstable_PerfMapState_Init(void) + + Open the ``/tmp/perf-$pid.map`` file, unless it's already opened, and create + a lock to ensure thread-safe writes to the file (provided the writes are + done through :c:func:`PyUnstable_WritePerfMapEntry`). Normally, there's no need + to call this explicitly; just use :c:func:`PyUnstable_WritePerfMapEntry` + and it will initialize the state on first call. + + Returns ``0`` on success, ``-1`` on failure to create/open the perf map file, + or ``-2`` on failure to create a lock. Check ``errno`` for more information + about the cause of a failure. + +.. c:function:: int PyUnstable_WritePerfMapEntry(const void *code_addr, unsigned int code_size, const char *entry_name) + + Write one single entry to the ``/tmp/perf-$pid.map`` file. This function is + thread safe. Here is what an example entry looks like:: + + # address size name + 7f3529fcf759 b py::bar:/run/t.py + + Will call :c:func:`PyUnstable_PerfMapState_Init` before writing the entry, if + the perf map file is not already opened. Returns ``0`` on success, or the + same error codes as :c:func:`PyUnstable_PerfMapState_Init` on failure. + +.. c:function:: void PyUnstable_PerfMapState_Fini(void) + + Close the perf map file opened by :c:func:`PyUnstable_PerfMapState_Init`. + This is called by the runtime itself during interpreter shut-down. In + general, there shouldn't be a reason to explicitly call this, except to + handle specific scenarios such as forking. diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index ab3a2e274d9395..6771f378bfbc31 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -394,98 +394,149 @@ APIs: arguments, calculate the size of the resulting Python Unicode string and return a string with the values formatted into it. The variable arguments must be C types and must correspond exactly to the format characters in the *format* - ASCII-encoded string. The following format characters are allowed: - - .. % This should be exactly the same as the table in PyErr_Format. - - .. tabularcolumns:: |l|l|L| - - +-------------------+---------------------+----------------------------------+ - | Format Characters | Type | Comment | - +===================+=====================+==================================+ - | :attr:`%%` | *n/a* | The literal % character. | - +-------------------+---------------------+----------------------------------+ - | :attr:`%c` | int | A single character, | - | | | represented as a C int. | - +-------------------+---------------------+----------------------------------+ - | :attr:`%d` | int | Equivalent to | - | | | ``printf("%d")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%u` | unsigned int | Equivalent to | - | | | ``printf("%u")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%ld` | long | Equivalent to | - | | | ``printf("%ld")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%li` | long | Equivalent to | - | | | ``printf("%li")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%lu` | unsigned long | Equivalent to | - | | | ``printf("%lu")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%lld` | long long | Equivalent to | - | | | ``printf("%lld")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%lli` | long long | Equivalent to | - | | | ``printf("%lli")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%llu` | unsigned long long | Equivalent to | - | | | ``printf("%llu")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%zd` | :c:type:`\ | Equivalent to | - | | Py_ssize_t` | ``printf("%zd")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%zi` | :c:type:`\ | Equivalent to | - | | Py_ssize_t` | ``printf("%zi")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%zu` | size_t | Equivalent to | - | | | ``printf("%zu")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%i` | int | Equivalent to | - | | | ``printf("%i")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%x` | int | Equivalent to | - | | | ``printf("%x")``. [1]_ | - +-------------------+---------------------+----------------------------------+ - | :attr:`%s` | const char\* | A null-terminated C character | - | | | array. | - +-------------------+---------------------+----------------------------------+ - | :attr:`%p` | const void\* | The hex representation of a C | - | | | pointer. Mostly equivalent to | - | | | ``printf("%p")`` except that | - | | | it is guaranteed to start with | - | | | the literal ``0x`` regardless | - | | | of what the platform's | - | | | ``printf`` yields. | - +-------------------+---------------------+----------------------------------+ - | :attr:`%A` | PyObject\* | The result of calling | - | | | :func:`ascii`. | - +-------------------+---------------------+----------------------------------+ - | :attr:`%U` | PyObject\* | A Unicode object. | - +-------------------+---------------------+----------------------------------+ - | :attr:`%V` | PyObject\*, | A Unicode object (which may be | - | | const char\* | ``NULL``) and a null-terminated | - | | | C character array as a second | - | | | parameter (which will be used, | - | | | if the first parameter is | - | | | ``NULL``). | - +-------------------+---------------------+----------------------------------+ - | :attr:`%S` | PyObject\* | The result of calling | - | | | :c:func:`PyObject_Str`. | - +-------------------+---------------------+----------------------------------+ - | :attr:`%R` | PyObject\* | The result of calling | - | | | :c:func:`PyObject_Repr`. | - +-------------------+---------------------+----------------------------------+ + ASCII-encoded string. + + A conversion specifier contains two or more characters and has the following + components, which must occur in this order: + + #. The ``'%'`` character, which marks the start of the specifier. + + #. Conversion flags (optional), which affect the result of some conversion + types. + + #. Minimum field width (optional). + If specified as an ``'*'`` (asterisk), the actual width is given in the + next argument, which must be of type :c:expr:`int`, and the object to + convert comes after the minimum field width and optional precision. + + #. Precision (optional), given as a ``'.'`` (dot) followed by the precision. + If specified as ``'*'`` (an asterisk), the actual precision is given in + the next argument, which must be of type :c:expr:`int`, and the value to + convert comes after the precision. + + #. Length modifier (optional). + + #. Conversion type. + + The conversion flag characters are: + + .. tabularcolumns:: |l|L| + + +-------+-------------------------------------------------------------+ + | Flag | Meaning | + +=======+=============================================================+ + | ``0`` | The conversion will be zero padded for numeric values. | + +-------+-------------------------------------------------------------+ + | ``-`` | The converted value is left adjusted (overrides the ``0`` | + | | flag if both are given). | + +-------+-------------------------------------------------------------+ + + The length modifiers for following integer conversions (``d``, ``i``, + ``o``, ``u``, ``x``, or ``X``) specify the type of the argument + (:c:expr:`int` by default): + + .. tabularcolumns:: |l|L| + + +----------+-----------------------------------------------------+ + | Modifier | Types | + +==========+=====================================================+ + | ``l`` | :c:expr:`long` or :c:expr:`unsigned long` | + +----------+-----------------------------------------------------+ + | ``ll`` | :c:expr:`long long` or :c:expr:`unsigned long long` | + +----------+-----------------------------------------------------+ + | ``j`` | :c:expr:`intmax_t` or :c:expr:`uintmax_t` | + +----------+-----------------------------------------------------+ + | ``z`` | :c:expr:`size_t` or :c:expr:`ssize_t` | + +----------+-----------------------------------------------------+ + | ``t`` | :c:expr:`ptrdiff_t` | + +----------+-----------------------------------------------------+ + + The length modifier ``l`` for following conversions ``s`` or ``V`` specify + that the type of the argument is :c:expr:`const wchar_t*`. + + The conversion specifiers are: + + .. list-table:: + :widths: auto + :header-rows: 1 + + * - Conversion Specifier + - Type + - Comment + + * - ``%`` + - *n/a* + - The literal ``%`` character. + + * - ``d``, ``i`` + - Specified by the length modifier + - The decimal representation of a signed C integer. + + * - ``u`` + - Specified by the length modifier + - The decimal representation of an unsigned C integer. + + * - ``o`` + - Specified by the length modifier + - The octal representation of an unsigned C integer. + + * - ``x`` + - Specified by the length modifier + - The hexadecimal representation of an unsigned C integer (lowercase). + + * - ``X`` + - Specified by the length modifier + - The hexadecimal representation of an unsigned C integer (uppercase). + + * - ``c`` + - :c:expr:`int` + - A single character. + + * - ``s`` + - :c:expr:`const char*` or :c:expr:`const wchar_t*` + - A null-terminated C character array. + + * - ``p`` + - :c:expr:`const void*` + - The hex representation of a C pointer. + Mostly equivalent to ``printf("%p")`` except that it is guaranteed to + start with the literal ``0x`` regardless of what the platform's + ``printf`` yields. + + * - ``A`` + - :c:expr:`PyObject*` + - The result of calling :func:`ascii`. + + * - ``U`` + - :c:expr:`PyObject*` + - A Unicode object. + + * - ``V`` + - :c:expr:`PyObject*`, :c:expr:`const char*` or :c:expr:`const wchar_t*` + - A Unicode object (which may be ``NULL``) and a null-terminated + C character array as a second parameter (which will be used, + if the first parameter is ``NULL``). + + * - ``S`` + - :c:expr:`PyObject*` + - The result of calling :c:func:`PyObject_Str`. + + * - ``R`` + - :c:expr:`PyObject*` + - The result of calling :c:func:`PyObject_Repr`. .. note:: The width formatter unit is number of characters rather than bytes. - The precision formatter unit is number of bytes for ``"%s"`` and + The precision formatter unit is number of bytes or :c:expr:`wchar_t` + items (if the length modifier ``l`` is used) for ``"%s"`` and ``"%V"`` (if the ``PyObject*`` argument is ``NULL``), and a number of characters for ``"%A"``, ``"%U"``, ``"%S"``, ``"%R"`` and ``"%V"`` (if the ``PyObject*`` argument is not ``NULL``). - .. [1] For integer specifiers (d, u, ld, li, lu, lld, lli, llu, zd, zi, - zu, i, x): the 0-conversion flag has effect even when a precision is given. + .. note:: + Unlike to C :c:func:`printf` the ``0`` flag has effect even when + a precision is given for integer conversions (``d``, ``i``, ``u``, ``o``, + ``x``, or ``X``). .. versionchanged:: 3.2 Support for ``"%lld"`` and ``"%llu"`` added. @@ -498,6 +549,13 @@ APIs: ``"%V"``, ``"%S"``, ``"%R"`` added. .. versionchanged:: 3.12 + Support for conversion specifiers ``o`` and ``X``. + Support for length modifiers ``j`` and ``t``. + Length modifiers are now applied to all integer conversions. + Length modifier ``l`` is now applied to conversion specifiers ``s`` and ``V``. + Support for variable width and precision ``*``. + Support for flag ``-``. + An unrecognized format character now sets a :exc:`SystemError`. In previous versions it caused all the rest of the format string to be copied as-is to the result string, and any extra arguments discarded. diff --git a/Doc/c-api/utilities.rst b/Doc/c-api/utilities.rst index a805b564763c40..ccbf14e1850f68 100644 --- a/Doc/c-api/utilities.rst +++ b/Doc/c-api/utilities.rst @@ -19,3 +19,4 @@ and parsing function arguments and constructing Python values from C values. conversion.rst reflection.rst codec.rst + perfmaps.rst diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 513856d8a48d70..000a2d3d8790bb 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -167,6 +167,10 @@ the same library that the Python runtime is using. event loops, as done in the :file:`Modules/_tkinter.c` in the Python source code. + .. versionchanged:: 3.12 + This function is only called from the + :ref:`main interpreter `. + .. c:var:: char* (*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *) @@ -187,6 +191,10 @@ the same library that the Python runtime is using. :c:func:`PyMem_RawRealloc`, instead of being allocated by :c:func:`PyMem_Malloc` or :c:func:`PyMem_Realloc`. + .. versionchanged:: 3.12 + This function is only called from the + :ref:`main interpreter `. + .. c:function:: PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals) This is a simplified interface to :c:func:`PyRun_StringFlags` below, leaving diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 53e8cdcae1cd66..8c493f823a6fae 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -22,15 +22,6 @@ Glossary * The :const:`Ellipsis` built-in constant. - 2to3 - A tool that tries to convert Python 2.x code to Python 3.x code by - handling most of the incompatibilities which can be detected by parsing the - source and traversing the parse tree. - - 2to3 is available in the standard library as :mod:`lib2to3`; a standalone - entry point is provided as :file:`Tools/scripts/2to3`. See - :ref:`2to3-reference`. - abstract base class Abstract base classes complement :term:`duck-typing` by providing a way to define interfaces when other techniques like diff --git a/Doc/howto/perf_profiling.rst b/Doc/howto/perf_profiling.rst index 6af5536166f58a..61812c19ae6ca9 100644 --- a/Doc/howto/perf_profiling.rst +++ b/Doc/howto/perf_profiling.rst @@ -24,7 +24,7 @@ functions to appear in the output of the ``perf`` profiler. When this mode is enabled, the interpreter will interpose a small piece of code compiled on the fly before the execution of every Python function and it will teach ``perf`` the relationship between this piece of code and the associated Python function using -`perf map files`_. +:doc:`perf map files <../c-api/perfmaps>`. .. note:: @@ -206,5 +206,3 @@ You can check if your system has been compiled with this flag by running:: If you don't see any output it means that your interpreter has not been compiled with frame pointers and therefore it may not be able to show Python functions in the output of ``perf``. - -.. _perf map files: https://github.com/torvalds/linux/blob/0513e464f9007b70b96740271a948ca5ab6e7dd7/tools/perf/Documentation/jit-interface.txt diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index 61ba6bd7224fcc..86137fb38c9b93 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -6,13 +6,6 @@ :Author: `Michael Foord `_ -.. note:: - - There is a French translation of an earlier revision of this - HOWTO, available at `urllib2 - Le Manuel manquant - `_. - - Introduction ============ diff --git a/Doc/library/2to3.rst b/Doc/library/2to3.rst deleted file mode 100644 index d85ad94e9b7fe4..00000000000000 --- a/Doc/library/2to3.rst +++ /dev/null @@ -1,489 +0,0 @@ -.. _2to3-reference: - -2to3 --- Automated Python 2 to 3 code translation -================================================= - -.. sectionauthor:: Benjamin Peterson - -2to3 is a Python program that reads Python 2.x source code and applies a series -of *fixers* to transform it into valid Python 3.x code. The standard library -contains a rich set of fixers that will handle almost all code. 2to3 supporting -library :mod:`lib2to3` is, however, a flexible and generic library, so it is -possible to write your own fixers for 2to3. - -.. deprecated-removed:: 3.11 3.13 - The ``lib2to3`` module was marked pending for deprecation in Python 3.9 - (raising :exc:`PendingDeprecationWarning` on import) and fully deprecated - in Python 3.11 (raising :exc:`DeprecationWarning`). The ``2to3`` tool is - part of that. It will be removed in Python 3.13. - -.. _2to3-using: - -Using 2to3 ----------- - -2to3 will usually be installed with the Python interpreter as a script. It is -also located in the :file:`Tools/scripts` directory of the Python root. - -2to3's basic arguments are a list of files or directories to transform. The -directories are recursively traversed for Python sources. - -Here is a sample Python 2.x source file, :file:`example.py`:: - - def greet(name): - print "Hello, {0}!".format(name) - print "What's your name?" - name = raw_input() - greet(name) - -It can be converted to Python 3.x code via 2to3 on the command line: - -.. code-block:: shell-session - - $ 2to3 example.py - -A diff against the original source file is printed. 2to3 can also write the -needed modifications right back to the source file. (A backup of the original -file is made unless :option:`!-n` is also given.) Writing the changes back is -enabled with the :option:`!-w` flag: - -.. code-block:: shell-session - - $ 2to3 -w example.py - -After transformation, :file:`example.py` looks like this:: - - def greet(name): - print("Hello, {0}!".format(name)) - print("What's your name?") - name = input() - greet(name) - -Comments and exact indentation are preserved throughout the translation process. - -By default, 2to3 runs a set of :ref:`predefined fixers <2to3-fixers>`. The -:option:`!-l` flag lists all available fixers. An explicit set of fixers to run -can be given with :option:`!-f`. Likewise the :option:`!-x` explicitly disables a -fixer. The following example runs only the ``imports`` and ``has_key`` fixers: - -.. code-block:: shell-session - - $ 2to3 -f imports -f has_key example.py - -This command runs every fixer except the ``apply`` fixer: - -.. code-block:: shell-session - - $ 2to3 -x apply example.py - -Some fixers are *explicit*, meaning they aren't run by default and must be -listed on the command line to be run. Here, in addition to the default fixers, -the ``idioms`` fixer is run: - -.. code-block:: shell-session - - $ 2to3 -f all -f idioms example.py - -Notice how passing ``all`` enables all default fixers. - -Sometimes 2to3 will find a place in your source code that needs to be changed, -but 2to3 cannot fix automatically. In this case, 2to3 will print a warning -beneath the diff for a file. You should address the warning in order to have -compliant 3.x code. - -2to3 can also refactor doctests. To enable this mode, use the :option:`!-d` -flag. Note that *only* doctests will be refactored. This also doesn't require -the module to be valid Python. For example, doctest like examples in a reST -document could also be refactored with this option. - -The :option:`!-v` option enables output of more information on the translation -process. - -Since some print statements can be parsed as function calls or statements, 2to3 -cannot always read files containing the print function. When 2to3 detects the -presence of the ``from __future__ import print_function`` compiler directive, it -modifies its internal grammar to interpret :func:`print` as a function. This -change can also be enabled manually with the :option:`!-p` flag. Use -:option:`!-p` to run fixers on code that already has had its print statements -converted. Also :option:`!-e` can be used to make :func:`exec` a function. - -The :option:`!-o` or :option:`!--output-dir` option allows specification of an -alternate directory for processed output files to be written to. The -:option:`!-n` flag is required when using this as backup files do not make sense -when not overwriting the input files. - -.. versionadded:: 3.2.3 - The :option:`!-o` option was added. - -The :option:`!-W` or :option:`!--write-unchanged-files` flag tells 2to3 to always -write output files even if no changes were required to the file. This is most -useful with :option:`!-o` so that an entire Python source tree is copied with -translation from one directory to another. -This option implies the :option:`!-w` flag as it would not make sense otherwise. - -.. versionadded:: 3.2.3 - The :option:`!-W` flag was added. - -The :option:`!--add-suffix` option specifies a string to append to all output -filenames. The :option:`!-n` flag is required when specifying this as backups -are not necessary when writing to different filenames. Example: - -.. code-block:: shell-session - - $ 2to3 -n -W --add-suffix=3 example.py - -Will cause a converted file named ``example.py3`` to be written. - -.. versionadded:: 3.2.3 - The :option:`!--add-suffix` option was added. - -To translate an entire project from one directory tree to another use: - -.. code-block:: shell-session - - $ 2to3 --output-dir=python3-version/mycode -W -n python2-version/mycode - - -.. _2to3-fixers: - -Fixers ------- - -Each step of transforming code is encapsulated in a fixer. The command ``2to3 --l`` lists them. As :ref:`documented above <2to3-using>`, each can be turned on -and off individually. They are described here in more detail. - - -.. 2to3fixer:: apply - - Removes usage of :func:`apply`. For example ``apply(function, *args, - **kwargs)`` is converted to ``function(*args, **kwargs)``. - -.. 2to3fixer:: asserts - - Replaces deprecated :mod:`unittest` method names with the correct ones. - - ================================ ========================================== - From To - ================================ ========================================== - ``failUnlessEqual(a, b)`` :meth:`assertEqual(a, b) - ` - ``assertEquals(a, b)`` :meth:`assertEqual(a, b) - ` - ``failIfEqual(a, b)`` :meth:`assertNotEqual(a, b) - ` - ``assertNotEquals(a, b)`` :meth:`assertNotEqual(a, b) - ` - ``failUnless(a)`` :meth:`assertTrue(a) - ` - ``assert_(a)`` :meth:`assertTrue(a) - ` - ``failIf(a)`` :meth:`assertFalse(a) - ` - ``failUnlessRaises(exc, cal)`` :meth:`assertRaises(exc, cal) - ` - ``failUnlessAlmostEqual(a, b)`` :meth:`assertAlmostEqual(a, b) - ` - ``assertAlmostEquals(a, b)`` :meth:`assertAlmostEqual(a, b) - ` - ``failIfAlmostEqual(a, b)`` :meth:`assertNotAlmostEqual(a, b) - ` - ``assertNotAlmostEquals(a, b)`` :meth:`assertNotAlmostEqual(a, b) - ` - ================================ ========================================== - -.. 2to3fixer:: basestring - - Converts :class:`basestring` to :class:`str`. - -.. 2to3fixer:: buffer - - Converts :class:`buffer` to :class:`memoryview`. This fixer is optional - because the :class:`memoryview` API is similar but not exactly the same as - that of :class:`buffer`. - -.. 2to3fixer:: dict - - Fixes dictionary iteration methods. :meth:`dict.iteritems` is converted to - :meth:`dict.items`, :meth:`dict.iterkeys` to :meth:`dict.keys`, and - :meth:`dict.itervalues` to :meth:`dict.values`. Similarly, - :meth:`dict.viewitems`, :meth:`dict.viewkeys` and :meth:`dict.viewvalues` are - converted respectively to :meth:`dict.items`, :meth:`dict.keys` and - :meth:`dict.values`. It also wraps existing usages of :meth:`dict.items`, - :meth:`dict.keys`, and :meth:`dict.values` in a call to :class:`list`. - -.. 2to3fixer:: except - - Converts ``except X, T`` to ``except X as T``. - -.. 2to3fixer:: exec - - Converts the ``exec`` statement to the :func:`exec` function. - -.. 2to3fixer:: execfile - - Removes usage of :func:`execfile`. The argument to :func:`execfile` is - wrapped in calls to :func:`open`, :func:`compile`, and :func:`exec`. - -.. 2to3fixer:: exitfunc - - Changes assignment of :attr:`sys.exitfunc` to use of the :mod:`atexit` - module. - -.. 2to3fixer:: filter - - Wraps :func:`filter` usage in a :class:`list` call. - -.. 2to3fixer:: funcattrs - - Fixes function attributes that have been renamed. For example, - ``my_function.func_closure`` is converted to ``my_function.__closure__``. - -.. 2to3fixer:: future - - Removes ``from __future__ import new_feature`` statements. - -.. 2to3fixer:: getcwdu - - Renames :func:`os.getcwdu` to :func:`os.getcwd`. - -.. 2to3fixer:: has_key - - Changes ``dict.has_key(key)`` to ``key in dict``. - -.. 2to3fixer:: idioms - - This optional fixer performs several transformations that make Python code - more idiomatic. Type comparisons like ``type(x) is SomeClass`` and - ``type(x) == SomeClass`` are converted to ``isinstance(x, SomeClass)``. - ``while 1`` becomes ``while True``. This fixer also tries to make use of - :func:`sorted` in appropriate places. For example, this block :: - - L = list(some_iterable) - L.sort() - - is changed to :: - - L = sorted(some_iterable) - -.. 2to3fixer:: import - - Detects sibling imports and converts them to relative imports. - -.. 2to3fixer:: imports - - Handles module renames in the standard library. - -.. 2to3fixer:: imports2 - - Handles other modules renames in the standard library. It is separate from - the :2to3fixer:`imports` fixer only because of technical limitations. - -.. 2to3fixer:: input - - Converts ``input(prompt)`` to ``eval(input(prompt))``. - -.. 2to3fixer:: intern - - Converts :func:`intern` to :func:`sys.intern`. - -.. 2to3fixer:: isinstance - - Fixes duplicate types in the second argument of :func:`isinstance`. For - example, ``isinstance(x, (int, int))`` is converted to ``isinstance(x, - int)`` and ``isinstance(x, (int, float, int))`` is converted to - ``isinstance(x, (int, float))``. - -.. 2to3fixer:: itertools_imports - - Removes imports of :func:`itertools.ifilter`, :func:`itertools.izip`, and - :func:`itertools.imap`. Imports of :func:`itertools.ifilterfalse` are also - changed to :func:`itertools.filterfalse`. - -.. 2to3fixer:: itertools - - Changes usage of :func:`itertools.ifilter`, :func:`itertools.izip`, and - :func:`itertools.imap` to their built-in equivalents. - :func:`itertools.ifilterfalse` is changed to :func:`itertools.filterfalse`. - -.. 2to3fixer:: long - - Renames :class:`long` to :class:`int`. - -.. 2to3fixer:: map - - Wraps :func:`map` in a :class:`list` call. It also changes ``map(None, x)`` - to ``list(x)``. Using ``from future_builtins import map`` disables this - fixer. - -.. 2to3fixer:: metaclass - - Converts the old metaclass syntax (``__metaclass__ = Meta`` in the class - body) to the new (``class X(metaclass=Meta)``). - -.. 2to3fixer:: methodattrs - - Fixes old method attribute names. For example, ``meth.im_func`` is converted - to ``meth.__func__``. - -.. 2to3fixer:: ne - - Converts the old not-equal syntax, ``<>``, to ``!=``. - -.. 2to3fixer:: next - - Converts the use of iterator's :meth:`~iterator.next` methods to the - :func:`next` function. It also renames :meth:`next` methods to - :meth:`~iterator.__next__`. - -.. 2to3fixer:: nonzero - - Renames definitions of methods called :meth:`__nonzero__` - to :meth:`~object.__bool__`. - -.. 2to3fixer:: numliterals - - Converts octal literals into the new syntax. - -.. 2to3fixer:: operator - - Converts calls to various functions in the :mod:`operator` module to other, - but equivalent, function calls. When needed, the appropriate ``import`` - statements are added, e.g. ``import collections.abc``. The following mapping - are made: - - ================================== ============================================= - From To - ================================== ============================================= - ``operator.isCallable(obj)`` ``callable(obj)`` - ``operator.sequenceIncludes(obj)`` ``operator.contains(obj)`` - ``operator.isSequenceType(obj)`` ``isinstance(obj, collections.abc.Sequence)`` - ``operator.isMappingType(obj)`` ``isinstance(obj, collections.abc.Mapping)`` - ``operator.isNumberType(obj)`` ``isinstance(obj, numbers.Number)`` - ``operator.repeat(obj, n)`` ``operator.mul(obj, n)`` - ``operator.irepeat(obj, n)`` ``operator.imul(obj, n)`` - ================================== ============================================= - -.. 2to3fixer:: paren - - Add extra parenthesis where they are required in list comprehensions. For - example, ``[x for x in 1, 2]`` becomes ``[x for x in (1, 2)]``. - -.. 2to3fixer:: print - - Converts the ``print`` statement to the :func:`print` function. - -.. 2to3fixer:: raise - - Converts ``raise E, V`` to ``raise E(V)``, and ``raise E, V, T`` to ``raise - E(V).with_traceback(T)``. If ``E`` is a tuple, the translation will be - incorrect because substituting tuples for exceptions has been removed in 3.0. - -.. 2to3fixer:: raw_input - - Converts :func:`raw_input` to :func:`input`. - -.. 2to3fixer:: reduce - - Handles the move of :func:`reduce` to :func:`functools.reduce`. - -.. 2to3fixer:: reload - - Converts :func:`reload` to :func:`importlib.reload`. - -.. 2to3fixer:: renames - - Changes :data:`sys.maxint` to :data:`sys.maxsize`. - -.. 2to3fixer:: repr - - Replaces backtick repr with the :func:`repr` function. - -.. 2to3fixer:: set_literal - - Replaces use of the :class:`set` constructor with set literals. This fixer - is optional. - -.. 2to3fixer:: standarderror - - Renames :exc:`StandardError` to :exc:`Exception`. - -.. 2to3fixer:: sys_exc - - Changes the deprecated :data:`sys.exc_value`, :data:`sys.exc_type`, - :data:`sys.exc_traceback` to use :func:`sys.exc_info`. - -.. 2to3fixer:: throw - - Fixes the API change in generator's :meth:`throw` method. - -.. 2to3fixer:: tuple_params - - Removes implicit tuple parameter unpacking. This fixer inserts temporary - variables. - -.. 2to3fixer:: types - - Fixes code broken from the removal of some members in the :mod:`types` - module. - -.. 2to3fixer:: unicode - - Renames :class:`unicode` to :class:`str`. - -.. 2to3fixer:: urllib - - Handles the rename of :mod:`urllib` and :mod:`urllib2` to the :mod:`urllib` - package. - -.. 2to3fixer:: ws_comma - - Removes excess whitespace from comma separated items. This fixer is - optional. - -.. 2to3fixer:: xrange - - Renames :func:`xrange` to :func:`range` and wraps existing :func:`range` - calls with :class:`list`. - -.. 2to3fixer:: xreadlines - - Changes ``for x in file.xreadlines()`` to ``for x in file``. - -.. 2to3fixer:: zip - - Wraps :func:`zip` usage in a :class:`list` call. This is disabled when - ``from future_builtins import zip`` appears. - - -:mod:`lib2to3` --- 2to3's library ---------------------------------- - -.. module:: lib2to3 - :synopsis: The 2to3 library - -.. moduleauthor:: Guido van Rossum -.. moduleauthor:: Collin Winter -.. moduleauthor:: Benjamin Peterson - -**Source code:** :source:`Lib/lib2to3/` - --------------- - -.. deprecated-removed:: 3.11 3.13 - Python 3.9 switched to a PEG parser (see :pep:`617`) while lib2to3 is - using a less flexible LL(1) parser. Python 3.10 includes new language - syntax that is not parsable by lib2to3's LL(1) parser (see :pep:`634`). - The ``lib2to3`` module was marked pending for deprecation in Python 3.9 - (raising :exc:`PendingDeprecationWarning` on import) and fully deprecated - in Python 3.11 (raising :exc:`DeprecationWarning`). - It will be removed from the standard library in Python 3.13. - Consider third-party alternatives such as `LibCST`_ or `parso`_. - -.. note:: - - The :mod:`lib2to3` API should be considered unstable and may change - drastically in the future. - -.. _LibCST: https://libcst.readthedocs.io/ -.. _parso: https://parso.readthedocs.io/ diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 33e367f3ccda89..fbffa71d200735 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -57,20 +57,20 @@ the extracted data in a :class:`argparse.Namespace` object:: Quick Links for add_argument() ------------------------------ -====================== =========================================================== ========================================================================================================================== -Name Description Values -====================== =========================================================== ========================================================================================================================== -action_ Specify how an argument should be handled ``'store'``, ``'store_const'``, ``'store_true'``, ``'append'``, ``'append_const'``, ``'count'``, ``'help'``, ``'version'`` -choices_ Limit values to a specific set of choices ``['foo', 'bar']``, ``range(1, 10)``, or :class:`~collections.abc.Container` instance -const_ Store a constant value -default_ Default value used when an argument is not provided Defaults to ``None`` -dest_ Specify the attribute name used in the result namespace -help_ Help message for an argument -metavar_ Alternate display name for the argument as shown in help -nargs_ Number of times the argument can be used :class:`int`, ``'?'``, ``'*'``, or ``'+'`` -required_ Indicate whether an argument is required or optional ``True`` or ``False`` -type_ Automatically convert an argument to the given type :class:`int`, :class:`float`, ``argparse.FileType('w')``, or callable function -====================== =========================================================== ========================================================================================================================== +============================ =========================================================== ========================================================================================================================== +Name Description Values +============================ =========================================================== ========================================================================================================================== +action_ Specify how an argument should be handled ``'store'``, ``'store_const'``, ``'store_true'``, ``'append'``, ``'append_const'``, ``'count'``, ``'help'``, ``'version'`` +choices_ Limit values to a specific set of choices ``['foo', 'bar']``, ``range(1, 10)``, or :class:`~collections.abc.Container` instance +const_ Store a constant value +default_ Default value used when an argument is not provided Defaults to ``None`` +dest_ Specify the attribute name used in the result namespace +help_ Help message for an argument +metavar_ Alternate display name for the argument as shown in help +nargs_ Number of times the argument can be used :class:`int`, ``'?'``, ``'*'``, or ``'+'`` +required_ Indicate whether an argument is required or optional ``True`` or ``False`` +:ref:`type ` Automatically convert an argument to the given type :class:`int`, :class:`float`, ``argparse.FileType('w')``, or callable function +============================ =========================================================== ========================================================================================================================== Example @@ -1132,7 +1132,7 @@ command-line argument was not present:: Namespace(foo='1') -.. _type: +.. _argparse-type: type ^^^^ diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 0811b3fa0e7842..b6b1e076c9f08c 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -1724,6 +1724,7 @@ Function and class definitions body=[ FunctionDef( name='f', + type_params=[], args=arguments( posonlyargs=[], args=[ @@ -1847,6 +1848,7 @@ Function and class definitions body=[ ClassDef( name='Foo', + type_params=[], bases=[ Name(id='base1', ctx=Load()), Name(id='base2', ctx=Load())], @@ -1885,6 +1887,7 @@ Async and await body=[ AsyncFunctionDef( name='f', + type_params=[], args=arguments( posonlyargs=[], args=[], diff --git a/Doc/library/development.rst b/Doc/library/development.rst index 9edce758688e2d..b1979b921e7d5f 100644 --- a/Doc/library/development.rst +++ b/Doc/library/development.rst @@ -8,8 +8,7 @@ The modules described in this chapter help you write software. For example, the :mod:`pydoc` module takes a module and generates documentation based on the module's contents. The :mod:`doctest` and :mod:`unittest` modules contains frameworks for writing unit tests that automatically exercise code and verify -that the expected output is produced. :program:`2to3` can translate Python 2.x -source code into valid Python 3.x code. +that the expected output is produced. The list of modules described in this chapter is: @@ -23,5 +22,4 @@ The list of modules described in this chapter is: unittest.rst unittest.mock.rst unittest.mock-examples.rst - 2to3.rst test.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 248743b8fa0a87..4762fb50437460 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -622,8 +622,8 @@ not have to be) the original ``STACK[-2]``. .. versionadded:: 3.8 - .. versionchanged:: 3.11 - Exception representation on the stack now consist of one, not three, items. + .. versionchanged:: 3.11 + Exception representation on the stack now consist of one, not three, items. .. opcode:: CLEANUP_THROW diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 582e06261afd72..e9c4f0e2c5f59b 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -406,18 +406,18 @@ Data Types with an *IntEnum* member, the resulting value loses its enumeration status. >>> from enum import IntEnum - >>> class Numbers(IntEnum): + >>> class Number(IntEnum): ... ONE = 1 ... TWO = 2 ... THREE = 3 ... - >>> Numbers.THREE - - >>> Numbers.ONE + Numbers.TWO + >>> Number.THREE + + >>> Number.ONE + Number.TWO 3 - >>> Numbers.THREE + 5 + >>> Number.THREE + 5 8 - >>> Numbers.THREE == 3 + >>> Number.THREE == 3 True .. note:: diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst index 6d5c64df1a1f3f..0961ca4aaa9422 100644 --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -50,6 +50,9 @@ The :mod:`gc` module provides the following functions: is run. Not all items in some free lists may be freed due to the particular implementation, in particular :class:`float`. + The effect of calling ``gc.collect()`` while the interpreter is already + performing a collection is undefined. + .. function:: set_debug(flags) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst index bf1f2e3920783d..46d616aae95c96 100644 --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -394,6 +394,17 @@ HTTPConnection Objects one will be automatically generated and transmitted if not provided in the headers argument. + +.. method:: HTTPConnection.get_proxy_response_headers() + + Returns a dictionary with the headers of the response received from + the proxy server to the CONNECT request. + + If the CONNECT request was not sent, the method returns an empty dictionary. + + .. versionadded:: 3.12 + + .. method:: HTTPConnection.connect() Connect to the server specified when the object was created. By default, diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 250246b5cd9adc..448978f43b6d13 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -87,6 +87,10 @@ in :mod:`logging` itself) and defining handlers which are declared either in provides a mechanism to present the choices and load the chosen configuration). + It will raise :exc:`FileNotFoundError` if the file + doesn't exist and :exc:`RuntimeError` if the file is invalid or + empty. + :param fname: A filename, or a file-like object, or an instance derived from :class:`~configparser.RawConfigParser`. If a ``RawConfigParser``-derived instance is passed, it is used as @@ -111,7 +115,7 @@ in :mod:`logging` itself) and defining handlers which are declared either in they or their ancestors are explicitly named in the logging configuration. - :param encoding: The encoding used to open file when *fname* is filename. + :param encoding: The encoding used to open file when *fname* is filename. .. versionchanged:: 3.4 An instance of a subclass of :class:`~configparser.RawConfigParser` is @@ -126,6 +130,10 @@ in :mod:`logging` itself) and defining handlers which are declared either in .. versionadded:: 3.10 The *encoding* parameter is added. + .. versionchanged:: 3.12 + An exception will be thrown if the provided file + doesn't exist or is invalid or empty. + .. function:: listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None) Starts up a socket server on the specified port, and listens for new diff --git a/Doc/library/math.rst b/Doc/library/math.rst index 797f32408eac3d..9e58b552576ce6 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -224,11 +224,11 @@ Number-theoretic and representation functions of *x* and are floats. -.. function:: nextafter(x, y) +.. function:: nextafter(x, y, steps=1) - Return the next floating-point value after *x* towards *y*. + Return the floating-point value *steps* steps after *x* towards *y*. - If *x* is equal to *y*, return *y*. + If *x* is equal to *y*, return *y*, unless *steps* is zero. Examples: @@ -239,6 +239,9 @@ Number-theoretic and representation functions See also :func:`math.ulp`. + .. versionchanged:: 3.12 + Added the *steps* argument. + .. versionadded:: 3.9 .. function:: perm(n, k=None) diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst index 6d90473f2367b5..dab4de9eb6abb7 100644 --- a/Doc/library/operator.rst +++ b/Doc/library/operator.rst @@ -244,7 +244,7 @@ Operations which work with sequences (some of them with mappings too) include: .. function:: length_hint(obj, default=0) - Return an estimated length for the object *o*. First try to return its + Return an estimated length for the object *obj*. First try to return its actual length, then an estimate using :meth:`object.__length_hint__`, and finally return the default value. diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 641e289e77c518..83abb5d5ca1e42 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -493,6 +493,17 @@ process and user. .. versionadded:: 3.3 +.. data:: PRIO_DARWIN_THREAD + PRIO_DARWIN_PROCESS + PRIO_DARWIN_BG + PRIO_DARWIN_NONUI + + Parameters for the :func:`getpriority` and :func:`setpriority` functions. + + .. availability:: macOS + + .. versionadded:: 3.12 + .. function:: getresuid() Return a tuple (ruid, euid, suid) denoting the current process's diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index bfbca6bd3d771a..0083dc5e62f1c3 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -546,7 +546,7 @@ Pure paths provide the following methods and properties: PureWindowsPath('c:/Program Files') -.. method:: PurePath.match(pattern) +.. method:: PurePath.match(pattern, *, case_sensitive=None) Match this path against the provided glob-style pattern. Return ``True`` if matching is successful, ``False`` otherwise. @@ -576,6 +576,11 @@ Pure paths provide the following methods and properties: >>> PureWindowsPath('b.py').match('*.PY') True + Set *case_sensitive* to ``True`` or ``False`` to override this behaviour. + + .. versionadded:: 3.12 + The *case_sensitive* argument. + .. method:: PurePath.relative_to(other, walk_up=False) diff --git a/Doc/library/superseded.rst b/Doc/library/superseded.rst index aaf66ea121d39c..e4a473f712846d 100644 --- a/Doc/library/superseded.rst +++ b/Doc/library/superseded.rst @@ -27,6 +27,5 @@ backwards compatibility. They have been superseded by other modules. sndhdr.rst spwd.rst sunau.rst - telnetlib.rst uu.rst xdrlib.rst diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst deleted file mode 100644 index 5a993dc42a5ab2..00000000000000 --- a/Doc/library/telnetlib.rst +++ /dev/null @@ -1,262 +0,0 @@ -:mod:`telnetlib` --- Telnet client -================================== - -.. module:: telnetlib - :synopsis: Telnet client class. - :deprecated: - -.. sectionauthor:: Skip Montanaro - -**Source code:** :source:`Lib/telnetlib.py` - -.. index:: single: protocol; Telnet - -.. deprecated-removed:: 3.11 3.13 - The :mod:`telnetlib` module is deprecated - (see :pep:`PEP 594 <594#telnetlib>` for details and alternatives). - --------------- - -The :mod:`telnetlib` module provides a :class:`Telnet` class that implements the -Telnet protocol. See :rfc:`854` for details about the protocol. In addition, it -provides symbolic constants for the protocol characters (see below), and for the -telnet options. The symbolic names of the telnet options follow the definitions -in ``arpa/telnet.h``, with the leading ``TELOPT_`` removed. For symbolic names -of options which are traditionally not included in ``arpa/telnet.h``, see the -module source itself. - -The symbolic constants for the telnet commands are: IAC, DONT, DO, WONT, WILL, -SE (Subnegotiation End), NOP (No Operation), DM (Data Mark), BRK (Break), IP -(Interrupt process), AO (Abort output), AYT (Are You There), EC (Erase -Character), EL (Erase Line), GA (Go Ahead), SB (Subnegotiation Begin). - -.. include:: ../includes/wasm-notavail.rst - -.. class:: Telnet(host=None, port=0[, timeout]) - - :class:`Telnet` represents a connection to a Telnet server. The instance is - initially not connected by default; the :meth:`~Telnet.open` method must be used to - establish a connection. Alternatively, the host name and optional port - number can be passed to the constructor too, in which case the connection to - the server will be established before the constructor returns. The optional - *timeout* parameter specifies a timeout in seconds for blocking operations - like the connection attempt (if not specified, the global default timeout - setting will be used). - - Do not reopen an already connected instance. - - This class has many :meth:`read_\*` methods. Note that some of them raise - :exc:`EOFError` when the end of the connection is read, because they can return - an empty string for other reasons. See the individual descriptions below. - - A :class:`Telnet` object is a context manager and can be used in a - :keyword:`with` statement. When the :keyword:`!with` block ends, the - :meth:`close` method is called:: - - >>> from telnetlib import Telnet - >>> with Telnet('localhost', 23) as tn: - ... tn.interact() - ... - - .. versionchanged:: 3.6 Context manager support added - - -.. seealso:: - - :rfc:`854` - Telnet Protocol Specification - Definition of the Telnet protocol. - - -.. _telnet-objects: - -Telnet Objects --------------- - -:class:`Telnet` instances have the following methods: - - -.. method:: Telnet.read_until(expected, timeout=None) - - Read until a given byte string, *expected*, is encountered or until *timeout* - seconds have passed. - - When no match is found, return whatever is available instead, possibly empty - bytes. Raise :exc:`EOFError` if the connection is closed and no cooked data - is available. - - -.. method:: Telnet.read_all() - - Read all data until EOF as bytes; block until connection closed. - - -.. method:: Telnet.read_some() - - Read at least one byte of cooked data unless EOF is hit. Return ``b''`` if - EOF is hit. Block if no data is immediately available. - - -.. method:: Telnet.read_very_eager() - - Read everything that can be without blocking in I/O (eager). - - Raise :exc:`EOFError` if connection closed and no cooked data available. - Return ``b''`` if no cooked data available otherwise. Do not block unless in - the midst of an IAC sequence. - - -.. method:: Telnet.read_eager() - - Read readily available data. - - Raise :exc:`EOFError` if connection closed and no cooked data available. - Return ``b''`` if no cooked data available otherwise. Do not block unless in - the midst of an IAC sequence. - - -.. method:: Telnet.read_lazy() - - Process and return data already in the queues (lazy). - - Raise :exc:`EOFError` if connection closed and no data available. Return - ``b''`` if no cooked data available otherwise. Do not block unless in the - midst of an IAC sequence. - - -.. method:: Telnet.read_very_lazy() - - Return any data available in the cooked queue (very lazy). - - Raise :exc:`EOFError` if connection closed and no data available. Return - ``b''`` if no cooked data available otherwise. This method never blocks. - - -.. method:: Telnet.read_sb_data() - - Return the data collected between a SB/SE pair (suboption begin/end). The - callback should access these data when it was invoked with a ``SE`` command. - This method never blocks. - - -.. method:: Telnet.open(host, port=0[, timeout]) - - Connect to a host. The optional second argument is the port number, which - defaults to the standard Telnet port (23). The optional *timeout* parameter - specifies a timeout in seconds for blocking operations like the connection - attempt (if not specified, the global default timeout setting will be used). - - Do not try to reopen an already connected instance. - - .. audit-event:: telnetlib.Telnet.open self,host,port telnetlib.Telnet.open - - -.. method:: Telnet.msg(msg, *args) - - Print a debug message when the debug level is ``>`` 0. If extra arguments are - present, they are substituted in the message using the standard string - formatting operator. - - -.. method:: Telnet.set_debuglevel(debuglevel) - - Set the debug level. The higher the value of *debuglevel*, the more debug - output you get (on ``sys.stdout``). - - -.. method:: Telnet.close() - - Close the connection. - - -.. method:: Telnet.get_socket() - - Return the socket object used internally. - - -.. method:: Telnet.fileno() - - Return the file descriptor of the socket object used internally. - - -.. method:: Telnet.write(buffer) - - Write a byte string to the socket, doubling any IAC characters. This can - block if the connection is blocked. May raise :exc:`OSError` if the - connection is closed. - - .. audit-event:: telnetlib.Telnet.write self,buffer telnetlib.Telnet.write - - .. versionchanged:: 3.3 - This method used to raise :exc:`socket.error`, which is now an alias - of :exc:`OSError`. - - -.. method:: Telnet.interact() - - Interaction function, emulates a very dumb Telnet client. - - -.. method:: Telnet.mt_interact() - - Multithreaded version of :meth:`interact`. - - -.. method:: Telnet.expect(list, timeout=None) - - Read until one from a list of a regular expressions matches. - - The first argument is a list of regular expressions, either compiled - (:ref:`regex objects `) or uncompiled (byte strings). The - optional second argument is a timeout, in seconds; the default is to block - indefinitely. - - Return a tuple of three items: the index in the list of the first regular - expression that matches; the match object returned; and the bytes read up - till and including the match. - - If end of file is found and no bytes were read, raise :exc:`EOFError`. - Otherwise, when nothing matches, return ``(-1, None, data)`` where *data* is - the bytes received so far (may be empty bytes if a timeout happened). - - If a regular expression ends with a greedy match (such as ``.*``) or if more - than one expression can match the same input, the results are - non-deterministic, and may depend on the I/O timing. - - -.. method:: Telnet.set_option_negotiation_callback(callback) - - Each time a telnet option is read on the input flow, this *callback* (if set) is - called with the following parameters: callback(telnet socket, command - (DO/DONT/WILL/WONT), option). No other action is done afterwards by telnetlib. - - -.. _telnet-example: - -Telnet Example --------------- - -.. sectionauthor:: Peter Funk - - -A simple example illustrating typical use:: - - import getpass - import telnetlib - - HOST = "localhost" - user = input("Enter your remote account: ") - password = getpass.getpass() - - tn = telnetlib.Telnet(HOST) - - tn.read_until(b"login: ") - tn.write(user.encode('ascii') + b"\n") - if password: - tn.read_until(b"Password: ") - tn.write(password.encode('ascii') + b"\n") - - tn.write(b"ls\n") - tn.write(b"exit\n") - - print(tn.read_all().decode('ascii')) - diff --git a/Doc/library/token-list.inc b/Doc/library/token-list.inc index 3b345099bf54b5..e885de88cad9ae 100644 --- a/Doc/library/token-list.inc +++ b/Doc/library/token-list.inc @@ -223,6 +223,10 @@ .. data:: FSTRING_END +.. data:: COMMENT + +.. data:: NL + .. data:: ERRORTOKEN .. data:: N_TOKENS diff --git a/Doc/library/token.rst b/Doc/library/token.rst index a1aceba96ce030..903847bb206d62 100644 --- a/Doc/library/token.rst +++ b/Doc/library/token.rst @@ -50,11 +50,13 @@ The following token type values aren't used by the C tokenizer but are needed fo the :mod:`tokenize` module. .. data:: COMMENT + :noindex: Token value used to indicate a comment. .. data:: NL + :noindex: Token value used to indicate a non-terminating newline. The :data:`NEWLINE` token indicates the end of a logical line of Python code; diff --git a/Doc/library/tty.rst b/Doc/library/tty.rst index b30bc3c7ac42e9..fc7f98c7931fa5 100644 --- a/Doc/library/tty.rst +++ b/Doc/library/tty.rst @@ -20,18 +20,36 @@ Because it requires the :mod:`termios` module, it will work only on Unix. The :mod:`tty` module defines the following functions: +.. function:: cfmakeraw(mode) + + Convert the tty attribute list *mode*, which is a list like the one returned + by :func:`termios.tcgetattr`, to that of a tty in raw mode. + + .. versionadded:: 3.12 + + +.. function:: cfmakecbreak(mode) + + Convert the tty attribute list *mode*, which is a list like the one returned + by :func:`termios.tcgetattr`, to that of a tty in cbreak mode. + + .. versionadded:: 3.12 + + .. function:: setraw(fd, when=termios.TCSAFLUSH) Change the mode of the file descriptor *fd* to raw. If *when* is omitted, it defaults to :const:`termios.TCSAFLUSH`, and is passed to - :func:`termios.tcsetattr`. + :func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr` + is saved before setting *fd* to raw mode; this value is returned. .. function:: setcbreak(fd, when=termios.TCSAFLUSH) Change the mode of file descriptor *fd* to cbreak. If *when* is omitted, it defaults to :const:`termios.TCSAFLUSH`, and is passed to - :func:`termios.tcsetattr`. + :func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr` + is saved before setting *fd* to cbreak mode; this value is returned. .. seealso:: diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst index 10138f4f406f85..c656f6d9cfdaad 100644 --- a/Doc/library/turtle.rst +++ b/Doc/library/turtle.rst @@ -359,18 +359,18 @@ Turtle motion .. doctest:: :skipif: _tkinter is None - >>> tp = turtle.pos() - >>> tp - (0.00,0.00) - >>> turtle.setpos(60,30) - >>> turtle.pos() - (60.00,30.00) - >>> turtle.setpos((20,80)) - >>> turtle.pos() - (20.00,80.00) - >>> turtle.setpos(tp) - >>> turtle.pos() - (0.00,0.00) + >>> tp = turtle.pos() + >>> tp + (0.00,0.00) + >>> turtle.setpos(60,30) + >>> turtle.pos() + (60.00,30.00) + >>> turtle.setpos((20,80)) + >>> turtle.pos() + (20.00,80.00) + >>> turtle.setpos(tp) + >>> turtle.pos() + (0.00,0.00) .. function:: teleport(x, y=None, *, fill_gap=False) @@ -395,18 +395,18 @@ Turtle motion .. doctest:: :skipif: _tkinter is None - >>> tp = turtle.pos() - >>> tp - (0.00,0.00) - >>> turtle.teleport(60) - >>> turtle.pos() - (60.00,0.00) - >>> turtle.teleport(y=10) - >>> turtle.pos() - (60.00,10.00) - >>> turtle.teleport(20, 30) - >>> turtle.pos() - (20.00,30.00) + >>> tp = turtle.pos() + >>> tp + (0.00,0.00) + >>> turtle.teleport(60) + >>> turtle.pos() + (60.00,0.00) + >>> turtle.teleport(y=10) + >>> turtle.pos() + (60.00,10.00) + >>> turtle.teleport(20, 30) + >>> turtle.pos() + (20.00,30.00) .. versionadded: 3.12 @@ -950,23 +950,23 @@ Color control .. doctest:: :skipif: _tkinter is None - >>> colormode() - 1.0 - >>> turtle.pencolor() - 'red' - >>> turtle.pencolor("brown") - >>> turtle.pencolor() - 'brown' - >>> tup = (0.2, 0.8, 0.55) - >>> turtle.pencolor(tup) - >>> turtle.pencolor() - (0.2, 0.8, 0.5490196078431373) - >>> colormode(255) - >>> turtle.pencolor() - (51.0, 204.0, 140.0) - >>> turtle.pencolor('#32c18f') - >>> turtle.pencolor() - (50.0, 193.0, 143.0) + >>> colormode() + 1.0 + >>> turtle.pencolor() + 'red' + >>> turtle.pencolor("brown") + >>> turtle.pencolor() + 'brown' + >>> tup = (0.2, 0.8, 0.55) + >>> turtle.pencolor(tup) + >>> turtle.pencolor() + (0.2, 0.8, 0.5490196078431373) + >>> colormode(255) + >>> turtle.pencolor() + (51.0, 204.0, 140.0) + >>> turtle.pencolor('#32c18f') + >>> turtle.pencolor() + (50.0, 193.0, 143.0) .. function:: fillcolor(*args) @@ -999,17 +999,17 @@ Color control .. doctest:: :skipif: _tkinter is None - >>> turtle.fillcolor("violet") - >>> turtle.fillcolor() - 'violet' - >>> turtle.pencolor() - (50.0, 193.0, 143.0) - >>> turtle.fillcolor((50, 193, 143)) # Integers, not floats - >>> turtle.fillcolor() - (50.0, 193.0, 143.0) - >>> turtle.fillcolor('#ffffff') - >>> turtle.fillcolor() - (255.0, 255.0, 255.0) + >>> turtle.fillcolor("violet") + >>> turtle.fillcolor() + 'violet' + >>> turtle.pencolor() + (50.0, 193.0, 143.0) + >>> turtle.fillcolor((50, 193, 143)) # Integers, not floats + >>> turtle.fillcolor() + (50.0, 193.0, 143.0) + >>> turtle.fillcolor('#ffffff') + >>> turtle.fillcolor() + (255.0, 255.0, 255.0) .. function:: color(*args) @@ -1038,12 +1038,12 @@ Color control .. doctest:: :skipif: _tkinter is None - >>> turtle.color("red", "green") - >>> turtle.color() - ('red', 'green') - >>> color("#285078", "#a0c8f0") - >>> color() - ((40.0, 80.0, 120.0), (160.0, 200.0, 240.0)) + >>> turtle.color("red", "green") + >>> turtle.color() + ('red', 'green') + >>> color("#285078", "#a0c8f0") + >>> color() + ((40.0, 80.0, 120.0), (160.0, 200.0, 240.0)) See also: Screen method :func:`colormode`. @@ -1065,11 +1065,11 @@ Filling .. doctest:: :skipif: _tkinter is None - >>> turtle.begin_fill() - >>> if turtle.filling(): - ... turtle.pensize(5) - ... else: - ... turtle.pensize(3) + >>> turtle.begin_fill() + >>> if turtle.filling(): + ... turtle.pensize(5) + ... else: + ... turtle.pensize(3) @@ -1275,11 +1275,11 @@ Appearance .. doctest:: :skipif: _tkinter is None - >>> turtle.shape("circle") - >>> turtle.shapesize(5,2) - >>> turtle.shearfactor(0.5) - >>> turtle.shearfactor() - 0.5 + >>> turtle.shape("circle") + >>> turtle.shapesize(5,2) + >>> turtle.shearfactor(0.5) + >>> turtle.shearfactor() + 0.5 .. function:: tilt(angle) @@ -1648,11 +1648,11 @@ Window control ``"nopic"``, delete background image, if present. If *picname* is ``None``, return the filename of the current backgroundimage. :: - >>> screen.bgpic() - 'nopic' - >>> screen.bgpic("landscape.gif") - >>> screen.bgpic() - "landscape.gif" + >>> screen.bgpic() + 'nopic' + >>> screen.bgpic("landscape.gif") + >>> screen.bgpic() + "landscape.gif" .. function:: clear() @@ -2059,16 +2059,16 @@ Settings and special methods Return the height of the turtle window. :: - >>> screen.window_height() - 480 + >>> screen.window_height() + 480 .. function:: window_width() Return the width of the turtle window. :: - >>> screen.window_width() - 640 + >>> screen.window_width() + 640 .. _screenspecific: @@ -2249,12 +2249,12 @@ facilities: in the range 0..colormode or a 3-tuple of such numbers. - >>> screen.bgcolor("orange") - >>> screen.bgcolor() - "orange" - >>> screen.bgcolor(0.5,0,0.5) - >>> screen.bgcolor() - "#800080" + >>> screen.bgcolor("orange") + >>> screen.bgcolor() + "orange" + >>> screen.bgcolor(0.5,0,0.5) + >>> screen.bgcolor() + "#800080" >>> help(Turtle.penup) Help on method penup in module turtle: diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index c300c4257f0e81..92943c46ef5132 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -616,6 +616,21 @@ These can be used as types in annotations and do not support ``[]``. avoiding type checker errors with classes that can duck type anywhere or are highly dynamic. +.. data:: AnyStr + + ``AnyStr`` is a :ref:`constrained type variable ` defined as + ``AnyStr = TypeVar('AnyStr', str, bytes)``. + + It is meant to be used for functions that may accept any kind of string + without allowing different kinds of strings to mix. For example:: + + def concat(a: AnyStr, b: AnyStr) -> AnyStr: + return a + b + + concat(u"foo", u"bar") # Ok, output has type 'unicode' + concat(b"foo", b"bar") # Ok, output has type 'bytes' + concat(u"foo", b"bar") # Error, cannot mix unicode and bytes + .. data:: LiteralString Special type that includes only literal strings. A string @@ -917,13 +932,13 @@ These can be used as types in annotations using ``[]``, each having a unique syn # We don't need to pass in the lock ourselves thanks to the decorator. sum_threadsafe([1.1, 2.2, 3.3]) -.. versionadded:: 3.10 + .. versionadded:: 3.10 -.. seealso:: + .. seealso:: - * :pep:`612` -- Parameter Specification Variables (the PEP which introduced - ``ParamSpec`` and ``Concatenate``). - * :class:`ParamSpec` and :class:`Callable`. + * :pep:`612` -- Parameter Specification Variables (the PEP which introduced + ``ParamSpec`` and ``Concatenate``). + * :class:`ParamSpec` and :class:`Callable`. .. class:: Type(Generic[CT_co]) @@ -1208,6 +1223,49 @@ These can be used as types in annotations using ``[]``, each having a unique syn .. versionadded:: 3.10 +.. data:: Unpack + + A typing operator that conceptually marks an object as having been + unpacked. For example, using the unpack operator ``*`` on a + :class:`type variable tuple ` is equivalent to using ``Unpack`` + to mark the type variable tuple as having been unpacked:: + + Ts = TypeVarTuple('Ts') + tup: tuple[*Ts] + # Effectively does: + tup: tuple[Unpack[Ts]] + + In fact, ``Unpack`` can be used interchangeably with ``*`` in the context + of :class:`typing.TypeVarTuple ` and + :class:`builtins.tuple ` types. You might see ``Unpack`` being used + explicitly in older versions of Python, where ``*`` couldn't be used in + certain places:: + + # In older versions of Python, TypeVarTuple and Unpack + # are located in the `typing_extensions` backports package. + from typing_extensions import TypeVarTuple, Unpack + + Ts = TypeVarTuple('Ts') + tup: tuple[*Ts] # Syntax error on Python <= 3.10! + tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible + + ``Unpack`` can also be used along with :class:`typing.TypedDict` for typing + ``**kwargs`` in a function signature:: + + from typing import TypedDict, Unpack + + class Movie(TypedDict): + name: str + year: int + + # This function expects two keyword arguments - `name` of type `str` + # and `year` of type `int`. + def foo(**kwargs: Unpack[Movie]): ... + + See :pep:`692` for more details on using ``Unpack`` for ``**kwargs`` typing. + + .. versionadded:: 3.11 + Building generic types """""""""""""""""""""" @@ -1409,49 +1467,6 @@ These are not used in annotations. They are building blocks for creating generic .. versionadded:: 3.11 -.. data:: Unpack - - A typing operator that conceptually marks an object as having been - unpacked. For example, using the unpack operator ``*`` on a - :class:`type variable tuple ` is equivalent to using ``Unpack`` - to mark the type variable tuple as having been unpacked:: - - Ts = TypeVarTuple('Ts') - tup: tuple[*Ts] - # Effectively does: - tup: tuple[Unpack[Ts]] - - In fact, ``Unpack`` can be used interchangeably with ``*`` in the context - of :class:`typing.TypeVarTuple ` and - :class:`builtins.tuple ` types. You might see ``Unpack`` being used - explicitly in older versions of Python, where ``*`` couldn't be used in - certain places:: - - # In older versions of Python, TypeVarTuple and Unpack - # are located in the `typing_extensions` backports package. - from typing_extensions import TypeVarTuple, Unpack - - Ts = TypeVarTuple('Ts') - tup: tuple[*Ts] # Syntax error on Python <= 3.10! - tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible - - ``Unpack`` can also be used along with :class:`typing.TypedDict` for typing - ``**kwargs`` in a function signature:: - - from typing import TypedDict, Unpack - - class Movie(TypedDict): - name: str - year: int - - # This function expects two keyword arguments - `name` of type `str` - # and `year` of type `int`. - def foo(**kwargs: Unpack[Movie]): ... - - See :pep:`692` for more details on using ``Unpack`` for ``**kwargs`` typing. - - .. versionadded:: 3.11 - .. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False) Parameter specification variable. A specialized version of @@ -1550,20 +1565,93 @@ These are not used in annotations. They are building blocks for creating generic .. versionadded:: 3.10 -.. data:: AnyStr +Other special directives +"""""""""""""""""""""""" - ``AnyStr`` is a :ref:`constrained type variable ` defined as - ``AnyStr = TypeVar('AnyStr', str, bytes)``. +These are not used in annotations. They are building blocks for declaring types. - It is meant to be used for functions that may accept any kind of string - without allowing different kinds of strings to mix. For example:: +.. class:: NamedTuple - def concat(a: AnyStr, b: AnyStr) -> AnyStr: - return a + b + Typed version of :func:`collections.namedtuple`. - concat(u"foo", u"bar") # Ok, output has type 'unicode' - concat(b"foo", b"bar") # Ok, output has type 'bytes' - concat(u"foo", b"bar") # Error, cannot mix unicode and bytes + Usage:: + + class Employee(NamedTuple): + name: str + id: int + + This is equivalent to:: + + Employee = collections.namedtuple('Employee', ['name', 'id']) + + To give a field a default value, you can assign to it in the class body:: + + class Employee(NamedTuple): + name: str + id: int = 3 + + employee = Employee('Guido') + assert employee.id == 3 + + Fields with a default value must come after any fields without a default. + + The resulting class has an extra attribute ``__annotations__`` giving a + dict that maps the field names to the field types. (The field names are in + the ``_fields`` attribute and the default values are in the + ``_field_defaults`` attribute, both of which are part of the :func:`~collections.namedtuple` + API.) + + ``NamedTuple`` subclasses can also have docstrings and methods:: + + class Employee(NamedTuple): + """Represents an employee.""" + name: str + id: int = 3 + + def __repr__(self) -> str: + return f'' + + ``NamedTuple`` subclasses can be generic:: + + class Group(NamedTuple, Generic[T]): + key: T + group: list[T] + + Backward-compatible usage:: + + Employee = NamedTuple('Employee', [('name', str), ('id', int)]) + + .. versionchanged:: 3.6 + Added support for :pep:`526` variable annotation syntax. + + .. versionchanged:: 3.6.1 + Added support for default values, methods, and docstrings. + + .. versionchanged:: 3.8 + The ``_field_types`` and ``__annotations__`` attributes are + now regular dictionaries instead of instances of ``OrderedDict``. + + .. versionchanged:: 3.9 + Removed the ``_field_types`` attribute in favor of the more + standard ``__annotations__`` attribute which has the same information. + + .. versionchanged:: 3.11 + Added support for generic namedtuples. + +.. class:: NewType(name, tp) + + A helper class to indicate a distinct type to a typechecker, + see :ref:`distinct`. At runtime it returns an object that returns + its argument when called. + Usage:: + + UserId = NewType('UserId', int) + first_user = UserId(1) + + .. versionadded:: 3.5.2 + + .. versionchanged:: 3.10 + ``NewType`` is now a class rather than a function. .. class:: Protocol(Generic) @@ -1659,94 +1747,6 @@ These are not used in annotations. They are building blocks for creating generic for more details. -Other special directives -"""""""""""""""""""""""" - -These are not used in annotations. They are building blocks for declaring types. - -.. class:: NamedTuple - - Typed version of :func:`collections.namedtuple`. - - Usage:: - - class Employee(NamedTuple): - name: str - id: int - - This is equivalent to:: - - Employee = collections.namedtuple('Employee', ['name', 'id']) - - To give a field a default value, you can assign to it in the class body:: - - class Employee(NamedTuple): - name: str - id: int = 3 - - employee = Employee('Guido') - assert employee.id == 3 - - Fields with a default value must come after any fields without a default. - - The resulting class has an extra attribute ``__annotations__`` giving a - dict that maps the field names to the field types. (The field names are in - the ``_fields`` attribute and the default values are in the - ``_field_defaults`` attribute, both of which are part of the :func:`~collections.namedtuple` - API.) - - ``NamedTuple`` subclasses can also have docstrings and methods:: - - class Employee(NamedTuple): - """Represents an employee.""" - name: str - id: int = 3 - - def __repr__(self) -> str: - return f'' - - ``NamedTuple`` subclasses can be generic:: - - class Group(NamedTuple, Generic[T]): - key: T - group: list[T] - - Backward-compatible usage:: - - Employee = NamedTuple('Employee', [('name', str), ('id', int)]) - - .. versionchanged:: 3.6 - Added support for :pep:`526` variable annotation syntax. - - .. versionchanged:: 3.6.1 - Added support for default values, methods, and docstrings. - - .. versionchanged:: 3.8 - The ``_field_types`` and ``__annotations__`` attributes are - now regular dictionaries instead of instances of ``OrderedDict``. - - .. versionchanged:: 3.9 - Removed the ``_field_types`` attribute in favor of the more - standard ``__annotations__`` attribute which has the same information. - - .. versionchanged:: 3.11 - Added support for generic namedtuples. - -.. class:: NewType(name, tp) - - A helper class to indicate a distinct type to a typechecker, - see :ref:`distinct`. At runtime it returns an object that returns - its argument when called. - Usage:: - - UserId = NewType('UserId', int) - first_user = UserId(1) - - .. versionadded:: 3.5.2 - - .. versionchanged:: 3.10 - ``NewType`` is now a class rather than a function. - .. class:: TypedDict(dict) Special construct to add type hints to a dictionary. @@ -2074,10 +2074,6 @@ Other concrete types represent the types of I/O streams such as returned by :func:`open`. - .. deprecated-removed:: 3.8 3.13 - The ``typing.io`` namespace is deprecated and will be removed. - These types should be directly imported from ``typing`` instead. - .. class:: Pattern Match @@ -2088,10 +2084,6 @@ Other concrete types ``Pattern[str]``, ``Pattern[bytes]``, ``Match[str]``, or ``Match[bytes]``. - .. deprecated-removed:: 3.8 3.13 - The ``typing.re`` namespace is deprecated and will be removed. - These types should be directly imported from ``typing`` instead. - .. deprecated:: 3.9 Classes ``Pattern`` and ``Match`` from :mod:`re` now support ``[]``. See :pep:`585` and :ref:`types-genericalias`. @@ -2981,9 +2973,6 @@ convenience. This is subject to change, and not all deprecations are listed. +----------------------------------+---------------+-------------------+----------------+ | Feature | Deprecated in | Projected removal | PEP/issue | +==================================+===============+===================+================+ -| ``typing.io`` and ``typing.re`` | 3.8 | 3.13 | :issue:`38291` | -| submodules | | | | -+----------------------------------+---------------+-------------------+----------------+ | ``typing`` versions of standard | 3.9 | Undecided | :pep:`585` | | collections | | | | +----------------------------------+---------------+-------------------+----------------+ diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index 96b396510794b4..5a9a53f83dace0 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -159,6 +159,10 @@ or on combining URL components into a URL string. ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', params='', query='', fragment='') + .. warning:: + + :func:`urlparse` does not perform validation. See :ref:`URL parsing + security ` for details. .. versionchanged:: 3.2 Added IPv6 URL parsing capabilities. @@ -324,8 +328,14 @@ or on combining URL components into a URL string. ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is decomposed before parsing, no error will be raised. - Following the `WHATWG spec`_ that updates RFC 3986, ASCII newline - ``\n``, ``\r`` and tab ``\t`` characters are stripped from the URL. + Following some of the `WHATWG spec`_ that updates RFC 3986, leading C0 + control and space characters are stripped from the URL. ``\n``, + ``\r`` and tab ``\t`` characters are removed from the URL at any position. + + .. warning:: + + :func:`urlsplit` does not perform validation. See :ref:`URL parsing + security ` for details. .. versionchanged:: 3.6 Out-of-range port numbers now raise :exc:`ValueError`, instead of @@ -338,6 +348,9 @@ or on combining URL components into a URL string. .. versionchanged:: 3.10 ASCII newline and tab characters are stripped from the URL. + .. versionchanged:: 3.12 + Leading WHATWG C0 control and space characters are stripped from the URL. + .. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser .. function:: urlunsplit(parts) @@ -414,6 +427,35 @@ or on combining URL components into a URL string. or ``scheme://host/path``). If *url* is not a wrapped URL, it is returned without changes. +.. _url-parsing-security: + +URL parsing security +-------------------- + +The :func:`urlsplit` and :func:`urlparse` APIs do not perform **validation** of +inputs. They may not raise errors on inputs that other applications consider +invalid. They may also succeed on some inputs that might not be considered +URLs elsewhere. Their purpose is for practical functionality rather than +purity. + +Instead of raising an exception on unusual input, they may instead return some +component parts as empty strings. Or components may contain more than perhaps +they should. + +We recommend that users of these APIs where the values may be used anywhere +with security implications code defensively. Do some verification within your +code before trusting a returned component part. Does that ``scheme`` make +sense? Is that a sensible ``path``? Is there anything strange about that +``hostname``? etc. + +What constitutes a URL is not universally well defined. Different applications +have different needs and desired constraints. For instance the living `WHATWG +spec`_ describes what user facing web clients such as a web browser require. +While :rfc:`3986` is more general. These functions incorporate some aspects of +both, but cannot be claimed compliant with either. The APIs and existing user +code with expectations on specific behaviors predate both standards leading us +to be very cautious about making API behavior changes. + .. _parsing-ascii-encoded-bytes: Parsing ASCII Encoded Bytes diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index 1d3503bf06f085..7a711031d74e9a 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -72,7 +72,6 @@ Doc/howto/sorting.rst Doc/howto/unicode.rst Doc/howto/urllib2.rst Doc/install/index.rst -Doc/library/2to3.rst Doc/library/__future__.rst Doc/library/_thread.rst Doc/library/abc.rst @@ -215,7 +214,6 @@ Doc/library/sys_path_init.rst Doc/library/sysconfig.rst Doc/library/syslog.rst Doc/library/tarfile.rst -Doc/library/telnetlib.rst Doc/library/tempfile.rst Doc/library/termios.rst Doc/library/test.rst diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index cd8d9febb0d13b..8a2eb07a69a69a 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -41,7 +41,7 @@ ISSUE_URI = 'https://bugs.python.org/issue?@action=redirect&bpo=%s' GH_ISSUE_URI = 'https://github.com/python/cpython/issues/%s' -SOURCE_URI = 'https://github.com/python/cpython/tree/main/%s' +SOURCE_URI = 'https://github.com/python/cpython/tree/3.12/%s' # monkey-patch reST parser to disable alphabetic and roman enumerated lists from docutils.parsers.rst.states import Body @@ -710,7 +710,6 @@ def setup(app): app.add_builder(PydocTopicsBuilder) app.add_object_type('opcode', 'opcode', '%s (opcode)', parse_opcode_signature) app.add_object_type('pdbcommand', 'pdbcmd', '%s (pdb command)', parse_pdb_command) - app.add_object_type('2to3fixer', '2to3fixer', '%s (2to3 fixer)') app.add_directive_to_domain('py', 'decorator', PyDecoratorFunction) app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod) app.add_directive_to_domain('py', 'coroutinefunction', PyCoroutineFunction) diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst index b71c61089e6dc1..42ebf2b3d294a8 100644 --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -10,13 +10,13 @@ Using the Python Interpreter Invoking the Interpreter ======================== -The Python interpreter is usually installed as :file:`/usr/local/bin/python3.12` +The Python interpreter is usually installed as :file:`/usr/local/bin/python3.13` on those machines where it is available; putting :file:`/usr/local/bin` in your Unix shell's search path makes it possible to start it by typing the command: .. code-block:: text - python3.12 + python3.13 to the shell. [#]_ Since the choice of the directory where the interpreter lives is an installation option, other places are possible; check with your local @@ -24,7 +24,7 @@ Python guru or system administrator. (E.g., :file:`/usr/local/python` is a popular alternative location.) On Windows machines where you have installed Python from the :ref:`Microsoft Store -`, the :file:`python3.12` command will be available. If you have +`, the :file:`python3.13` command will be available. If you have the :ref:`py.exe launcher ` installed, you can use the :file:`py` command. See :ref:`setting-envvars` for other ways to launch Python. @@ -97,8 +97,8 @@ before printing the first prompt: .. code-block:: shell-session - $ python3.12 - Python 3.12 (default, April 4 2022, 09:25:04) + $ python3.13 + Python 3.13 (default, April 4 2023, 09:25:04) [GCC 10.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst index ce858ab2c8d79e..fbe280d6413170 100644 --- a/Doc/using/configure.rst +++ b/Doc/using/configure.rst @@ -314,6 +314,13 @@ also be used to improve performance. is dependent on a combination of the build environment + the other optimization configure args + the CPU architecture, and not all combinations are supported. + BOLT versions before LLVM 16 are known to crash BOLT under some scenarios. + Use of LLVM 16 or newer for BOLT optimization is strongly encouraged. + + The :envvar:`!BOLT_INSTRUMENT_FLAGS` and :envvar:`!BOLT_APPLY_FLAGS` + :program:`configure` variables can be defined to override the default set of + arguments for :program:`llvm-bolt` to instrument and apply BOLT data to + binaries, respectively. .. versionadded:: 3.12 diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 69cd5c92d884d0..65178272862168 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -144,8 +144,8 @@ the foundation of most modern Mac development. Information on PyObjC is available from https://pypi.org/project/pyobjc/. The standard Python GUI toolkit is :mod:`tkinter`, based on the cross-platform -Tk toolkit (https://www.tcl.tk). An Aqua-native version of Tk is bundled with OS -X by Apple, and the latest version can be downloaded and installed from +Tk toolkit (https://www.tcl.tk). An Aqua-native version of Tk is bundled with +macOS by Apple, and the latest version can be downloaded and installed from https://www.activestate.com; it can also be built from source. *wxPython* is another popular cross-platform GUI toolkit that runs natively on diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index 84bb651e68eed5..7236e1cad7c8c6 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -2465,7 +2465,7 @@ changes, or look through the Subversion logs for all the details. (All changes contributed by Lars Gustäbel). * An optional ``timeout`` parameter was added to the - :class:`telnetlib.Telnet` class constructor, specifying a timeout + :class:`!telnetlib.Telnet` class constructor, specifying a timeout measured in seconds. (Added by Facundo Batista.) * The :class:`tempfile.NamedTemporaryFile` class usually deletes diff --git a/Doc/whatsnew/3.0.rst b/Doc/whatsnew/3.0.rst index f9ac13036cbc8d..b8cd7c48b359b2 100644 --- a/Doc/whatsnew/3.0.rst +++ b/Doc/whatsnew/3.0.rst @@ -911,7 +911,7 @@ best strategy is the following: tests still pass. 3. Run the ``2to3`` source-to-source translator over your source code - tree. (See :ref:`2to3-reference` for more on this tool.) Run the + tree. Run the result of the translation under Python 3.0. Manually fix up any remaining issues, fixing problems until all tests pass again. diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 7a479c6e56a9f0..8aadc2a0a581f2 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -1731,7 +1731,7 @@ Modules slated for removal in Python 3.13: +---------------------+---------------------+---------------------+---------------------+---------------------+ - | :mod:`aifc` | :mod:`chunk` | :mod:`msilib` | :mod:`pipes` | :mod:`telnetlib` | + | :mod:`aifc` | :mod:`chunk` | :mod:`msilib` | :mod:`pipes` | :mod:`!telnetlib` | +---------------------+---------------------+---------------------+---------------------+---------------------+ | :mod:`audioop` | :mod:`crypt` | :mod:`nis` | :mod:`sndhdr` | :mod:`uu` | +---------------------+---------------------+---------------------+---------------------+---------------------+ @@ -1748,7 +1748,7 @@ Modules warnings have now been updated to note they will be removed in Python 3.12. (Contributed by Hugo van Kemenade in :issue:`47022`.) -* The :mod:`lib2to3` package and :ref:`2to3 <2to3-reference>` tool +* The :mod:`!lib2to3` package and ``2to3`` tool are now deprecated and may not be able to parse Python 3.10 or newer. See :pep:`617`, introducing the new PEG parser, for details. (Contributed by Victor Stinner in :issue:`40360`.) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 3e55b3fa0f4734..5e07a4caeb9ebe 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -395,6 +395,9 @@ pathlib * Add :meth:`pathlib.Path.is_junction` as a proxy to :func:`os.path.isjunction`. (Contributed by Charles Machalow in :gh:`99547`.) +* Add *case_sensitive* optional parameter to :meth:`pathlib.Path.glob`, + :meth:`pathlib.Path.rglob` and :meth:`pathlib.PurePath.match` for matching + the path's case sensitivity, allowing for more precise control over the matching process. dis --- @@ -529,6 +532,17 @@ threading profiling functions in all running threads in addition to the calling one. (Contributed by Pablo Galindo in :gh:`93503`.) +tkinter +------- + +* ``tkinter.Canvas.coords()`` now flattens its arguments. + It now accepts not only coordinates as separate arguments + (``x1, y1, x2, y2, ...``) and a sequence of coordinates + (``[x1, y1, x2, y2, ...]``), but also coordinates grouped in pairs + (``(x1, y1), (x2, y2), ...`` and ``[(x1, y1), (x2, y2), ...]``), + like ``create_*()`` methods. + (Contributed by Serhiy Storchaka in :gh:`94473`.) + types ----- @@ -771,6 +785,16 @@ Deprecated ``int``, convert to int explicitly with ``~int(x)``. (Contributed by Tim Hoffmann in :gh:`103487`.) +* :class:`datetime.datetime`'s + :meth:`~datetime.datetime.utcnow` and + :meth:`~datetime.datetime.utcfromtimestamp` are deprecated and will be + removed in a future version. Instead, use timezone-aware objects to represent + datetimes in UTC: respectively, call + :meth:`~datetime.datetime.now` and + :meth:`~datetime.datetime.fromtimestamp` with the *tz* parameter set to + :attr:`datetime.UTC`. + (Contributed by Paul Ganssle in :gh:`103857`.) + Pending Removal in Python 3.13 ------------------------------ @@ -795,7 +819,7 @@ Modules (see :pep:`594`): * :mod:`sndhdr` * :mod:`spwd` * :mod:`sunau` -* :mod:`telnetlib` +* :mod:`!telnetlib` * :mod:`uu` * :mod:`xdrlib` @@ -867,6 +891,11 @@ Pending Removal in Python 3.14 * The *onerror* argument of :func:`shutil.rmtree` is deprecated in 3.12, and will be removed in 3.14. +* The *type*, *choices*, and *metavar* parameters + of :class:`!argparse.BooleanOptionalAction` are deprecated + and will be removed in 3.14. + (Contributed by Nikita Sobolev in :gh:`92248`.) + * :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader` now raise :exc:`DeprecationWarning`; use :func:`importlib.util.find_spec` instead. @@ -1384,6 +1413,12 @@ Porting to Python 3.12 :py:meth:`~class.__subclasses__` (using :c:func:`PyObject_CallMethod`, for example). +* Add support of more formatting options (left aligning, octals, uppercase + hexadecimals, ``intmax_t``, ``ptrdiff_t``, ``wchar_t`` C + strings, variable width and precision) in :c:func:`PyUnicode_FromFormat` and + :c:func:`PyUnicode_FromFormatV`. + (Contributed by Serhiy Storchaka in :gh:`98836`.) + * An unrecognized format character in :c:func:`PyUnicode_FromFormat` and :c:func:`PyUnicode_FromFormatV` now sets a :exc:`SystemError`. In previous versions it caused all the rest of the format string to be @@ -1441,6 +1476,15 @@ Porting to Python 3.12 Note that :c:func:`PyType_FromMetaclass` (added in Python 3.12) already disallows creating classes whose metaclass overrides ``tp_new``. +* :c:var:`PyOS_InputHook` and :c:var:`PyOS_ReadlineFunctionPointer` are no + longer called in :ref:`subinterpreters `. This is + because clients generally rely on process-wide global state (since these + callbacks have no way of recovering extension module state). + + This also avoids situations where extensions may find themselves running in a + subinterpreter that they don't support (or haven't yet been loaded in). See + :gh:`104668` for more info. + Deprecated ---------- diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst new file mode 100644 index 00000000000000..e0c3c2a3592ec7 --- /dev/null +++ b/Doc/whatsnew/3.13.rst @@ -0,0 +1,143 @@ + +**************************** + What's New In Python 3.13 +**************************** + +:Release: |release| +:Date: |today| + +.. Rules for maintenance: + + * Anyone can add text to this document. Do not spend very much time + on the wording of your changes, because your text will probably + get rewritten to some degree. + + * The maintainer will go through Misc/NEWS periodically and add + changes; it's therefore more important to add your changes to + Misc/NEWS than to this file. + + * This is not a complete list of every single change; completeness + is the purpose of Misc/NEWS. Some changes I consider too small + or esoteric to include. If such a change is added to the text, + I'll just remove it. (This is another reason you shouldn't spend + too much time on writing your addition.) + + * If you want to draw your new text to the attention of the + maintainer, add 'XXX' to the beginning of the paragraph or + section. + + * It's OK to just add a fragmentary note about a change. For + example: "XXX Describe the transmogrify() function added to the + socket module." The maintainer will research the change and + write the necessary text. + + * You can comment out your additions if you like, but it's not + necessary (especially when a final release is some months away). + + * Credit the author of a patch or bugfix. Just the name is + sufficient; the e-mail address isn't necessary. + + * It's helpful to add the issue number as a comment: + + XXX Describe the transmogrify() function added to the socket + module. + (Contributed by P.Y. Developer in :gh:`12345`.) + + This saves the maintainer the effort of going through the VCS log + when researching a change. + +This article explains the new features in Python 3.13, compared to 3.12. + +For full details, see the :ref:`changelog `. + +.. note:: + + Prerelease users should be aware that this document is currently in draft + form. It will be updated substantially as Python 3.13 moves towards release, + so it's worth checking back even after reading earlier versions. + + +Summary -- Release highlights +============================= + +.. This section singles out the most important changes in Python 3.13. + Brevity is key. + + +.. PEP-sized items next. + + + +New Features +============ + + + +Other Language Changes +====================== + + + +New Modules +=========== + +* None yet. + + +Improved Modules +================ + + +Optimizations +============= + + + + +Deprecated +========== + + + +Removed +======= + +* :pep:`594`: Remove the :mod:`!telnetlib` module, deprecated in Python 3.11: + use the projects `telnetlib3 `_ or + `Exscript `_ instead. + (Contributed by Victor Stinner in :gh:`104773`.) + +* Remove the ``2to3`` program and the :mod:`!lib2to3` module, + deprecated in Python 3.11. + (Contributed by Victor Stinner in :gh:`104780`.) + +* Namespaces ``typing.io`` and ``typing.re``, deprecated in Python 3.8, + are now removed. The items in those namespaces can be imported directly + from :mod:`typing`. (Contributed by Sebastian Rittau in :gh:`92871`.) + +Porting to Python 3.13 +====================== + +This section lists previously described changes and other bugfixes +that may require changes to your code. + + +Build Changes +============= + + +C API Changes +============= + +New Features +------------ + +Porting to Python 3.13 +---------------------- + +Deprecated +---------- + +Removed +------- + diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 3a681754e25dd7..1cd33dfb60421a 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -1520,7 +1520,7 @@ rather than the version that is being emulated for the process telnetlib --------- -:class:`~telnetlib.Telnet` is now a context manager (contributed by +:class:`!telnetlib.Telnet` is now a context manager (contributed by Stéphane Wirtel in :issue:`25485`). diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index fd86db96302356..532cabdd7a75be 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -935,10 +935,10 @@ Deprecated * :func:`smtpd.MailmanProxy` is now deprecated as it is unusable without an external module, ``mailman``. (Contributed by Samuel Colvin in :issue:`35800`.) -* The :mod:`lib2to3` module now emits a :exc:`PendingDeprecationWarning`. +* The :mod:`!lib2to3` module now emits a :exc:`PendingDeprecationWarning`. Python 3.9 switched to a PEG parser (see :pep:`617`), and Python 3.10 may include new language syntax that is not parsable by lib2to3's LL(1) parser. - The ``lib2to3`` module may be removed from the standard library in a future + The :mod:`!lib2to3` module may be removed from the standard library in a future Python version. Consider third-party alternatives such as `LibCST`_ or `parso`_. (Contributed by Carl Meyer in :issue:`40360`.) diff --git a/Doc/whatsnew/index.rst b/Doc/whatsnew/index.rst index bfee225791eee9..b9c19602653219 100644 --- a/Doc/whatsnew/index.rst +++ b/Doc/whatsnew/index.rst @@ -11,6 +11,7 @@ anyone wishing to stay up-to-date after a new release. .. toctree:: :maxdepth: 2 + 3.13.rst 3.12.rst 3.11.rst 3.10.rst diff --git a/Grammar/Tokens b/Grammar/Tokens index 096876fdd130f8..618ae811d824b0 100644 --- a/Grammar/Tokens +++ b/Grammar/Tokens @@ -64,9 +64,9 @@ SOFT_KEYWORD FSTRING_START FSTRING_MIDDLE FSTRING_END +COMMENT +NL ERRORTOKEN # These aren't used by the C tokenizer but are needed for tokenize.py -COMMENT -NL ENCODING diff --git a/Grammar/python.gram b/Grammar/python.gram index 6361dcd0985b99..e6a983429e39d8 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -112,6 +112,7 @@ simple_stmts[asdl_stmt_seq*]: # will throw a SyntaxError. simple_stmt[stmt_ty] (memo): | assignment + | &"type" type_alias | e=star_expressions { _PyAST_Expr(e, EXTRA) } | &'return' return_stmt | &('import' | 'from') import_stmt @@ -252,8 +253,8 @@ class_def[stmt_ty]: class_def_raw[stmt_ty]: | invalid_class_def_raw - | 'class' a=NAME b=['(' z=[arguments] ')' { z }] ':' c=block { - _PyAST_ClassDef(a->v.Name.id, + | 'class' a=NAME t=[type_params] b=['(' z=[arguments] ')' { z }] ':' c=block { + _PyAST_ClassDef(a->v.Name.id, t, (b) ? ((expr_ty) b)->v.Call.args : NULL, (b) ? ((expr_ty) b)->v.Call.keywords : NULL, c, NULL, EXTRA) } @@ -267,16 +268,16 @@ function_def[stmt_ty]: function_def_raw[stmt_ty]: | invalid_def_raw - | 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { - _PyAST_FunctionDef(n->v.Name.id, + | 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { + _PyAST_FunctionDef(n->v.Name.id, t, (params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)), b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) } - | ASYNC 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { + | ASYNC 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block { CHECK_VERSION( stmt_ty, 5, "Async functions are", - _PyAST_AsyncFunctionDef(n->v.Name.id, + _PyAST_AsyncFunctionDef(n->v.Name.id, t, (params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)), b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) ) } @@ -628,6 +629,39 @@ keyword_patterns[asdl_seq*]: keyword_pattern[KeyPatternPair*]: | arg=NAME '=' value=pattern { _PyPegen_key_pattern_pair(p, arg, value) } +# Type statement +# --------------- + +type_alias[stmt_ty]: + | "type" n=NAME t=[type_params] '=' b=expression { + CHECK_VERSION(stmt_ty, 12, "Type statement is", + _PyAST_TypeAlias(CHECK(expr_ty, _PyPegen_set_expr_context(p, n, Store)), t, b, EXTRA)) } + +# Type parameter declaration +# -------------------------- + +type_params[asdl_type_param_seq*]: '[' t=type_param_seq ']' { + CHECK_VERSION(asdl_type_param_seq *, 12, "Type parameter lists are", t) } + +type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ [','] { a } + +type_param[type_param_ty] (memo): + | a=NAME b=[type_param_bound] { _PyAST_TypeVar(a->v.Name.id, b, EXTRA) } + | '*' a=NAME colon=":" e=expression { + RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind + ? "cannot use constraints with TypeVarTuple" + : "cannot use bound with TypeVarTuple") + } + | '*' a=NAME { _PyAST_TypeVarTuple(a->v.Name.id, EXTRA) } + | '**' a=NAME colon=":" e=expression { + RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind + ? "cannot use constraints with ParamSpec" + : "cannot use bound with ParamSpec") + } + | '**' a=NAME { _PyAST_ParamSpec(a->v.Name.id, EXTRA) } + +type_param_bound[expr_ty]: ":" e=expression { e } + # EXPRESSIONS # ----------- diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h index 6f3efe36ede5d8..a3dc6661786451 100644 --- a/Include/cpython/frameobject.h +++ b/Include/cpython/frameobject.h @@ -35,7 +35,7 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *); /* Returns the code object of the frame (strong reference). * Does not raise an exception. */ -PyAPI_FUNC(PyCodeObject *) PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame); +PyAPI_FUNC(PyObject *) PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame); /* Returns a byte ofsset into the last executed instruction. * Does not raise an exception. */ diff --git a/Include/cpython/funcobject.h b/Include/cpython/funcobject.h index c716330cc3fbab..6f78f5868d0166 100644 --- a/Include/cpython/funcobject.h +++ b/Include/cpython/funcobject.h @@ -41,6 +41,7 @@ typedef struct { PyObject *func_weakreflist; /* List of weak references */ PyObject *func_module; /* The __module__ attribute, can be anything */ PyObject *func_annotations; /* Annotations, a dict or NULL */ + PyObject *func_typeparams; /* Tuple of active type variables or NULL */ vectorcallfunc vectorcall; /* Version number for use by specializer. * Can set to non-zero when we want to specialize. diff --git a/Include/cpython/longintrepr.h b/Include/cpython/longintrepr.h index c4cf820da5e4f2..692c69ba76db2f 100644 --- a/Include/cpython/longintrepr.h +++ b/Include/cpython/longintrepr.h @@ -98,6 +98,33 @@ PyAPI_FUNC(PyLongObject *) _PyLong_FromDigits(int negative, Py_ssize_t digit_count, digit *digits); +/* Inline some internals for speed. These should be in pycore_long.h + * if user code didn't need them inlined. */ + +#define _PyLong_SIGN_MASK 3 +#define _PyLong_NON_SIZE_BITS 3 + + +static inline int +_PyLong_IsCompact(const PyLongObject* op) { + assert(PyType_HasFeature((op)->ob_base.ob_type, Py_TPFLAGS_LONG_SUBCLASS)); + return op->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS); +} + +#define PyUnstable_Long_IsCompact _PyLong_IsCompact + +static inline Py_ssize_t +_PyLong_CompactValue(const PyLongObject *op) +{ + assert(PyType_HasFeature((op)->ob_base.ob_type, Py_TPFLAGS_LONG_SUBCLASS)); + assert(PyUnstable_Long_IsCompact(op)); + Py_ssize_t sign = 1 - (op->long_value.lv_tag & _PyLong_SIGN_MASK); + return sign * (Py_ssize_t)op->long_value.ob_digit[0]; +} + +#define PyUnstable_Long_CompactValue _PyLong_CompactValue + + #ifdef __cplusplus } #endif diff --git a/Include/cpython/longobject.h b/Include/cpython/longobject.h index 1a73799d658fe0..90cc0f267ae833 100644 --- a/Include/cpython/longobject.h +++ b/Include/cpython/longobject.h @@ -93,3 +93,8 @@ PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *); PyAPI_FUNC(PyObject *) _PyLong_Rshift(PyObject *, size_t); PyAPI_FUNC(PyObject *) _PyLong_Lshift(PyObject *, size_t); + + +PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op); +PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op); + diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index 08569ee683ce0d..314a5cc5b942ac 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -52,6 +52,7 @@ PyAPI_FUNC(const char *) _Py_gitidentifier(void); PyAPI_FUNC(const char *) _Py_gitversion(void); PyAPI_FUNC(int) _Py_IsFinalizing(void); +PyAPI_FUNC(int) _Py_IsInterpreterFinalizing(PyInterpreterState *interp); /* Random */ PyAPI_FUNC(int) _PyOS_URandom(void *buffer, Py_ssize_t size); diff --git a/Include/internal/pycore_ast.h b/Include/internal/pycore_ast.h index 36277efe9c5ca5..06a40239a2473a 100644 --- a/Include/internal/pycore_ast.h +++ b/Include/internal/pycore_ast.h @@ -51,6 +51,8 @@ typedef struct _pattern *pattern_ty; typedef struct _type_ignore *type_ignore_ty; +typedef struct _type_param *type_param_ty; + typedef struct { _ASDL_SEQ_HEAD @@ -147,6 +149,14 @@ typedef struct { asdl_type_ignore_seq *_Py_asdl_type_ignore_seq_new(Py_ssize_t size, PyArena *arena); +typedef struct { + _ASDL_SEQ_HEAD + type_param_ty typed_elements[1]; +} asdl_type_param_seq; + +asdl_type_param_seq *_Py_asdl_type_param_seq_new(Py_ssize_t size, PyArena + *arena); + enum _mod_kind {Module_kind=1, Interactive_kind=2, Expression_kind=3, FunctionType_kind=4}; @@ -176,17 +186,19 @@ struct _mod { enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3, Return_kind=4, Delete_kind=5, Assign_kind=6, - AugAssign_kind=7, AnnAssign_kind=8, For_kind=9, - AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13, - AsyncWith_kind=14, Match_kind=15, Raise_kind=16, Try_kind=17, - TryStar_kind=18, Assert_kind=19, Import_kind=20, - ImportFrom_kind=21, Global_kind=22, Nonlocal_kind=23, - Expr_kind=24, Pass_kind=25, Break_kind=26, Continue_kind=27}; + TypeAlias_kind=7, AugAssign_kind=8, AnnAssign_kind=9, + For_kind=10, AsyncFor_kind=11, While_kind=12, If_kind=13, + With_kind=14, AsyncWith_kind=15, Match_kind=16, + Raise_kind=17, Try_kind=18, TryStar_kind=19, Assert_kind=20, + Import_kind=21, ImportFrom_kind=22, Global_kind=23, + Nonlocal_kind=24, Expr_kind=25, Pass_kind=26, Break_kind=27, + Continue_kind=28}; struct _stmt { enum _stmt_kind kind; union { struct { identifier name; + asdl_type_param_seq *type_params; arguments_ty args; asdl_stmt_seq *body; asdl_expr_seq *decorator_list; @@ -196,6 +208,7 @@ struct _stmt { struct { identifier name; + asdl_type_param_seq *type_params; arguments_ty args; asdl_stmt_seq *body; asdl_expr_seq *decorator_list; @@ -205,6 +218,7 @@ struct _stmt { struct { identifier name; + asdl_type_param_seq *type_params; asdl_expr_seq *bases; asdl_keyword_seq *keywords; asdl_stmt_seq *body; @@ -225,6 +239,12 @@ struct _stmt { string type_comment; } Assign; + struct { + expr_ty name; + asdl_type_param_seq *type_params; + expr_ty value; + } TypeAlias; + struct { expr_ty target; operator_ty op; @@ -630,6 +650,30 @@ struct _type_ignore { } v; }; +enum _type_param_kind {TypeVar_kind=1, ParamSpec_kind=2, TypeVarTuple_kind=3}; +struct _type_param { + enum _type_param_kind kind; + union { + struct { + identifier name; + expr_ty bound; + } TypeVar; + + struct { + identifier name; + } ParamSpec; + + struct { + identifier name; + } TypeVarTuple; + + } v; + int lineno; + int col_offset; + int end_lineno; + int end_col_offset; +}; + // Note: these macros affect function definitions, not only call sites. mod_ty _PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores, @@ -638,21 +682,22 @@ mod_ty _PyAST_Interactive(asdl_stmt_seq * body, PyArena *arena); mod_ty _PyAST_Expression(expr_ty body, PyArena *arena); mod_ty _PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena *arena); -stmt_ty _PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * - body, asdl_expr_seq * decorator_list, expr_ty - returns, string type_comment, int lineno, int - col_offset, int end_lineno, int end_col_offset, - PyArena *arena); -stmt_ty _PyAST_AsyncFunctionDef(identifier name, arguments_ty args, - asdl_stmt_seq * body, asdl_expr_seq * - decorator_list, expr_ty returns, string - type_comment, int lineno, int col_offset, int - end_lineno, int end_col_offset, PyArena *arena); -stmt_ty _PyAST_ClassDef(identifier name, asdl_expr_seq * bases, - asdl_keyword_seq * keywords, asdl_stmt_seq * body, - asdl_expr_seq * decorator_list, int lineno, int - col_offset, int end_lineno, int end_col_offset, PyArena - *arena); +stmt_ty _PyAST_FunctionDef(identifier name, asdl_type_param_seq * type_params, + arguments_ty args, asdl_stmt_seq * body, + asdl_expr_seq * decorator_list, expr_ty returns, + string type_comment, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena); +stmt_ty _PyAST_AsyncFunctionDef(identifier name, asdl_type_param_seq * + type_params, arguments_ty args, asdl_stmt_seq * + body, asdl_expr_seq * decorator_list, expr_ty + returns, string type_comment, int lineno, int + col_offset, int end_lineno, int end_col_offset, + PyArena *arena); +stmt_ty _PyAST_ClassDef(identifier name, asdl_type_param_seq * type_params, + asdl_expr_seq * bases, asdl_keyword_seq * keywords, + asdl_stmt_seq * body, asdl_expr_seq * decorator_list, + int lineno, int col_offset, int end_lineno, int + end_col_offset, PyArena *arena); stmt_ty _PyAST_Return(expr_ty value, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); stmt_ty _PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int @@ -660,6 +705,9 @@ stmt_ty _PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int stmt_ty _PyAST_Assign(asdl_expr_seq * targets, expr_ty value, string type_comment, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); +stmt_ty _PyAST_TypeAlias(expr_ty name, asdl_type_param_seq * type_params, + expr_ty value, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena); stmt_ty _PyAST_AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); @@ -844,6 +892,14 @@ pattern_ty _PyAST_MatchOr(asdl_pattern_seq * patterns, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena); type_ignore_ty _PyAST_TypeIgnore(int lineno, string tag, PyArena *arena); +type_param_ty _PyAST_TypeVar(identifier name, expr_ty bound, int lineno, int + col_offset, int end_lineno, int end_col_offset, + PyArena *arena); +type_param_ty _PyAST_ParamSpec(identifier name, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena); +type_param_ty _PyAST_TypeVarTuple(identifier name, int lineno, int col_offset, + int end_lineno, int end_col_offset, PyArena + *arena); PyObject* PyAST_mod2obj(mod_ty t); diff --git a/Include/internal/pycore_ast_state.h b/Include/internal/pycore_ast_state.h index f15b4905eed14b..0c0d53f3e5d7e9 100644 --- a/Include/internal/pycore_ast_state.h +++ b/Include/internal/pycore_ast_state.h @@ -118,6 +118,7 @@ struct ast_state { PyObject *Not_type; PyObject *Or_singleton; PyObject *Or_type; + PyObject *ParamSpec_type; PyObject *Pass_type; PyObject *Pow_singleton; PyObject *Pow_type; @@ -137,7 +138,10 @@ struct ast_state { PyObject *TryStar_type; PyObject *Try_type; PyObject *Tuple_type; + PyObject *TypeAlias_type; PyObject *TypeIgnore_type; + PyObject *TypeVarTuple_type; + PyObject *TypeVar_type; PyObject *UAdd_singleton; PyObject *UAdd_type; PyObject *USub_singleton; @@ -166,6 +170,7 @@ struct ast_state { PyObject *bases; PyObject *body; PyObject *boolop_type; + PyObject *bound; PyObject *cases; PyObject *cause; PyObject *cls; @@ -243,6 +248,8 @@ struct ast_state { PyObject *type_comment; PyObject *type_ignore_type; PyObject *type_ignores; + PyObject *type_param_type; + PyObject *type_params; PyObject *unaryop_type; PyObject *upper; PyObject *value; diff --git a/Include/internal/pycore_ceval_state.h b/Include/internal/pycore_ceval_state.h index b352801673c40a..95d1fa16ba40dc 100644 --- a/Include/internal/pycore_ceval_state.h +++ b/Include/internal/pycore_ceval_state.h @@ -81,14 +81,14 @@ struct _pending_calls { }; struct _ceval_state { - int recursion_limit; - struct _gil_runtime_state *gil; - int own_gil; /* This single variable consolidates all requests to break out of the fast path in the eval loop. */ _Py_atomic_int eval_breaker; /* Request for dropping the GIL */ _Py_atomic_int gil_drop_request; + int recursion_limit; + struct _gil_runtime_state *gil; + int own_gil; /* The GC is ready to be executed */ _Py_atomic_int gc_scheduled; struct _pending_calls pending; diff --git a/Include/internal/pycore_compile.h b/Include/internal/pycore_compile.h index 499f55f3e276be..80a637e5bf9aed 100644 --- a/Include/internal/pycore_compile.h +++ b/Include/internal/pycore_compile.h @@ -105,7 +105,8 @@ PyAPI_FUNC(PyObject*) _PyCompile_CodeGen( PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg( PyObject *instructions, - PyObject *consts); + PyObject *consts, + int nlocals); PyAPI_FUNC(PyCodeObject*) _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h index 11988149843fef..ecbb7001e7d840 100644 --- a/Include/internal/pycore_function.h +++ b/Include/internal/pycore_function.h @@ -17,6 +17,8 @@ struct _py_func_state { extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr); extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); +extern PyObject *_Py_set_function_type_params( + PyThreadState* unused, PyObject *func, PyObject *type_params); #ifdef __cplusplus } diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h index 64d9384df9c5c5..5a3fb132c745ab 100644 --- a/Include/internal/pycore_global_objects.h +++ b/Include/internal/pycore_global_objects.h @@ -68,6 +68,13 @@ struct _Py_interp_cached_objects { PyObject *type_slots_pname; pytype_slotdef *type_slots_ptrs[MAX_EQUIV]; + /* TypeVar and related types */ + PyTypeObject *generic_type; + PyTypeObject *typevar_type; + PyTypeObject *typevartuple_type; + PyTypeObject *paramspec_type; + PyTypeObject *paramspecargs_type; + PyTypeObject *paramspeckwargs_type; }; #define _Py_INTERP_STATIC_OBJECT(interp, NAME) \ diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 7e495817981f06..5a1993eac23a8a 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -555,15 +555,19 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_close_br)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_open_br)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_percent)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(defaults)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot_locals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(empty)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(generic_base)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(json_decoder)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(kwdefaults)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(list_err)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(newline)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(open_br)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(percent)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(shim_name)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(type_params)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(utf_8)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(CANCELLED)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(FINISHED)); @@ -602,6 +606,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__class__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__class_getitem__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classcell__)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classdict__)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classdictcell__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__complex__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__contains__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__copy__)); @@ -724,6 +730,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__subclasshook__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__truediv__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__trunc__)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__type_params__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_is_unpacked_typevartuple__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_prepare_subst__)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_subst__)); @@ -779,8 +786,11 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_child)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_parent)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(aggregate_class)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(alias)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(append)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argdefs)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(args)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arguments)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argv)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(as_integer_ratio)); @@ -795,6 +805,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(big)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(binary_form)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(block)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(bound)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer_callback)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer_size)); @@ -850,11 +861,13 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(compile_mode)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(consts)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(context)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(contravariant)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cookie)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(copy)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(copyreg)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(coro)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(count)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(covariant)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cwd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(d)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data)); @@ -905,6 +918,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exception)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extend)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extra_tokens)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(facility)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(factory)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(false)); @@ -964,6 +978,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(incoming)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(indexgroup)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(inf)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(infer_variance)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(inheritable)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(initial)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(initial_bytes)); @@ -1057,6 +1072,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(newline)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(newlines)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(next)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nlocals)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(node_depth)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(node_offset)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ns)); @@ -1080,6 +1096,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(optimize)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(options)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(order)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(origin)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(out_fd)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(outgoing)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(overlapped)); @@ -1177,6 +1194,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(stdin)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(stdout)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(step)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(steps)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(store_name)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(strategy)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(strftime)); @@ -1213,6 +1231,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(twice)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(txt)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type_params)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tz)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tzname)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uid)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 8ebfee85c87c23..61967877ab4ac8 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -40,15 +40,19 @@ struct _Py_global_strings { STRUCT_FOR_STR(dbl_close_br, "}}") STRUCT_FOR_STR(dbl_open_br, "{{") STRUCT_FOR_STR(dbl_percent, "%%") + STRUCT_FOR_STR(defaults, ".defaults") STRUCT_FOR_STR(dot, ".") STRUCT_FOR_STR(dot_locals, ".") STRUCT_FOR_STR(empty, "") + STRUCT_FOR_STR(generic_base, ".generic_base") STRUCT_FOR_STR(json_decoder, "json.decoder") + STRUCT_FOR_STR(kwdefaults, ".kwdefaults") STRUCT_FOR_STR(list_err, "list index out of range") STRUCT_FOR_STR(newline, "\n") STRUCT_FOR_STR(open_br, "{") STRUCT_FOR_STR(percent, "%") STRUCT_FOR_STR(shim_name, "") + STRUCT_FOR_STR(type_params, ".type_params") STRUCT_FOR_STR(utf_8, "utf-8") } literals; @@ -90,6 +94,8 @@ struct _Py_global_strings { STRUCT_FOR_ID(__class__) STRUCT_FOR_ID(__class_getitem__) STRUCT_FOR_ID(__classcell__) + STRUCT_FOR_ID(__classdict__) + STRUCT_FOR_ID(__classdictcell__) STRUCT_FOR_ID(__complex__) STRUCT_FOR_ID(__contains__) STRUCT_FOR_ID(__copy__) @@ -212,6 +218,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(__subclasshook__) STRUCT_FOR_ID(__truediv__) STRUCT_FOR_ID(__trunc__) + STRUCT_FOR_ID(__type_params__) STRUCT_FOR_ID(__typing_is_unpacked_typevartuple__) STRUCT_FOR_ID(__typing_prepare_subst__) STRUCT_FOR_ID(__typing_subst__) @@ -267,8 +274,11 @@ struct _Py_global_strings { STRUCT_FOR_ID(after_in_child) STRUCT_FOR_ID(after_in_parent) STRUCT_FOR_ID(aggregate_class) + STRUCT_FOR_ID(alias) STRUCT_FOR_ID(append) + STRUCT_FOR_ID(arg) STRUCT_FOR_ID(argdefs) + STRUCT_FOR_ID(args) STRUCT_FOR_ID(arguments) STRUCT_FOR_ID(argv) STRUCT_FOR_ID(as_integer_ratio) @@ -283,6 +293,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(big) STRUCT_FOR_ID(binary_form) STRUCT_FOR_ID(block) + STRUCT_FOR_ID(bound) STRUCT_FOR_ID(buffer) STRUCT_FOR_ID(buffer_callback) STRUCT_FOR_ID(buffer_size) @@ -338,11 +349,13 @@ struct _Py_global_strings { STRUCT_FOR_ID(compile_mode) STRUCT_FOR_ID(consts) STRUCT_FOR_ID(context) + STRUCT_FOR_ID(contravariant) STRUCT_FOR_ID(cookie) STRUCT_FOR_ID(copy) STRUCT_FOR_ID(copyreg) STRUCT_FOR_ID(coro) STRUCT_FOR_ID(count) + STRUCT_FOR_ID(covariant) STRUCT_FOR_ID(cwd) STRUCT_FOR_ID(d) STRUCT_FOR_ID(data) @@ -393,6 +406,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(exception) STRUCT_FOR_ID(exp) STRUCT_FOR_ID(extend) + STRUCT_FOR_ID(extra_tokens) STRUCT_FOR_ID(facility) STRUCT_FOR_ID(factory) STRUCT_FOR_ID(false) @@ -452,6 +466,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(incoming) STRUCT_FOR_ID(indexgroup) STRUCT_FOR_ID(inf) + STRUCT_FOR_ID(infer_variance) STRUCT_FOR_ID(inheritable) STRUCT_FOR_ID(initial) STRUCT_FOR_ID(initial_bytes) @@ -545,6 +560,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(newline) STRUCT_FOR_ID(newlines) STRUCT_FOR_ID(next) + STRUCT_FOR_ID(nlocals) STRUCT_FOR_ID(node_depth) STRUCT_FOR_ID(node_offset) STRUCT_FOR_ID(ns) @@ -568,6 +584,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(optimize) STRUCT_FOR_ID(options) STRUCT_FOR_ID(order) + STRUCT_FOR_ID(origin) STRUCT_FOR_ID(out_fd) STRUCT_FOR_ID(outgoing) STRUCT_FOR_ID(overlapped) @@ -665,6 +682,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(stdin) STRUCT_FOR_ID(stdout) STRUCT_FOR_ID(step) + STRUCT_FOR_ID(steps) STRUCT_FOR_ID(store_name) STRUCT_FOR_ID(strategy) STRUCT_FOR_ID(strftime) @@ -701,6 +719,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(twice) STRUCT_FOR_ID(txt) STRUCT_FOR_ID(type) + STRUCT_FOR_ID(type_params) STRUCT_FOR_ID(tz) STRUCT_FOR_ID(tzname) STRUCT_FOR_ID(uid) diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 527b2121148f4c..04474c1da8855a 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -48,6 +48,7 @@ struct _Py_long_state { */ struct _is { + struct _ceval_state ceval; PyInterpreterState *next; uint64_t monitoring_version; @@ -83,9 +84,15 @@ struct _is { int _initialized; int finalizing; + /* Set by Py_EndInterpreter(). + + Use _PyInterpreterState_GetFinalizing() + and _PyInterpreterState_SetFinalizing() + to access it, don't access it directly. */ + _Py_atomic_address _finalizing; + struct _obmalloc_state obmalloc; - struct _ceval_state ceval; struct _gc_runtime_state gc; struct _import_state imports; @@ -191,6 +198,17 @@ struct _is { extern void _PyInterpreterState_Clear(PyThreadState *tstate); +static inline PyThreadState* +_PyInterpreterState_GetFinalizing(PyInterpreterState *interp) { + return (PyThreadState*)_Py_atomic_load_relaxed(&interp->_finalizing); +} + +static inline void +_PyInterpreterState_SetFinalizing(PyInterpreterState *interp, PyThreadState *tstate) { + _Py_atomic_store_relaxed(&interp->_finalizing, (uintptr_t)tstate); +} + + /* cross-interpreter data registry */ /* For now we use a global registry of shareable classes. An diff --git a/Include/internal/pycore_intrinsics.h b/Include/internal/pycore_intrinsics.h index 3902059a04b9da..39f15681b7b24b 100644 --- a/Include/internal/pycore_intrinsics.h +++ b/Include/internal/pycore_intrinsics.h @@ -8,15 +8,23 @@ #define INTRINSIC_ASYNC_GEN_WRAP 4 #define INTRINSIC_UNARY_POSITIVE 5 #define INTRINSIC_LIST_TO_TUPLE 6 +#define INTRINSIC_TYPEVAR 7 +#define INTRINSIC_PARAMSPEC 8 +#define INTRINSIC_TYPEVARTUPLE 9 +#define INTRINSIC_SUBSCRIPT_GENERIC 10 +#define INTRINSIC_TYPEALIAS 11 -#define MAX_INTRINSIC_1 6 +#define MAX_INTRINSIC_1 11 /* Binary Functions: */ #define INTRINSIC_2_INVALID 0 #define INTRINSIC_PREP_RERAISE_STAR 1 +#define INTRINSIC_TYPEVAR_WITH_BOUND 2 +#define INTRINSIC_TYPEVAR_WITH_CONSTRAINTS 3 +#define INTRINSIC_SET_FUNCTION_TYPE_PARAMS 4 -#define MAX_INTRINSIC_2 1 +#define MAX_INTRINSIC_2 4 typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value); typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index fe86581e81f6b5..64c00cb1475480 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -118,6 +118,21 @@ PyAPI_FUNC(char*) _PyLong_FormatBytesWriter( #define SIGN_NEGATIVE 2 #define NON_SIZE_BITS 3 +/* The functions _PyLong_IsCompact and _PyLong_CompactValue are defined + * in Include/cpython/longobject.h, since they need to be inline. + * + * "Compact" values have at least one bit to spare, + * so that addition and subtraction can be performed on the values + * without risk of overflow. + * + * The inline functions need tag bits. + * For readability, rather than do `#define SIGN_MASK _PyLong_SIGN_MASK` + * we define them to the numbers in both places and then assert that + * they're the same. + */ +static_assert(SIGN_MASK == _PyLong_SIGN_MASK, "SIGN_MASK does not match _PyLong_SIGN_MASK"); +static_assert(NON_SIZE_BITS == _PyLong_NON_SIZE_BITS, "NON_SIZE_BITS does not match _PyLong_NON_SIZE_BITS"); + /* All *compact" values are guaranteed to fit into * a Py_ssize_t with at least one bit to spare. * In other words, for 64 bit machines, compact @@ -131,11 +146,6 @@ _PyLong_IsNonNegativeCompact(const PyLongObject* op) { return op->long_value.lv_tag <= (1 << NON_SIZE_BITS); } -static inline int -_PyLong_IsCompact(const PyLongObject* op) { - assert(PyLong_Check(op)); - return op->long_value.lv_tag < (2 << NON_SIZE_BITS); -} static inline int _PyLong_BothAreCompact(const PyLongObject* a, const PyLongObject* b) { @@ -144,21 +154,6 @@ _PyLong_BothAreCompact(const PyLongObject* a, const PyLongObject* b) { return (a->long_value.lv_tag | b->long_value.lv_tag) < (2 << NON_SIZE_BITS); } -/* Returns a *compact* value, iff `_PyLong_IsCompact` is true for `op`. - * - * "Compact" values have at least one bit to spare, - * so that addition and subtraction can be performed on the values - * without risk of overflow. - */ -static inline Py_ssize_t -_PyLong_CompactValue(const PyLongObject *op) -{ - assert(PyLong_Check(op)); - assert(_PyLong_IsCompact(op)); - Py_ssize_t sign = 1 - (op->long_value.lv_tag & SIGN_MASK); - return sign * (Py_ssize_t)op->long_value.ob_digit[0]; -} - static inline bool _PyLong_IsZero(const PyLongObject *op) { diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index e823e1bfb5d452..15d96503830f93 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -138,6 +138,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [INSTRUMENTED_JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD, [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD, [INSTRUMENTED_LINE] = INSTRUMENTED_LINE, + [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE, [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE, [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE, @@ -167,7 +168,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [LOAD_ATTR_SLOT] = LOAD_ATTR, [LOAD_ATTR_WITH_HINT] = LOAD_ATTR, [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS, - [LOAD_CLASSDEREF] = LOAD_CLASSDEREF, [LOAD_CLOSURE] = LOAD_CLOSURE, [LOAD_CONST] = LOAD_CONST, [LOAD_CONST__LOAD_FAST] = LOAD_CONST, @@ -177,9 +177,12 @@ const uint8_t _PyOpcode_Deopt[256] = { [LOAD_FAST_CHECK] = LOAD_FAST_CHECK, [LOAD_FAST__LOAD_CONST] = LOAD_FAST, [LOAD_FAST__LOAD_FAST] = LOAD_FAST, + [LOAD_FROM_DICT_OR_DEREF] = LOAD_FROM_DICT_OR_DEREF, + [LOAD_FROM_DICT_OR_GLOBALS] = LOAD_FROM_DICT_OR_GLOBALS, [LOAD_GLOBAL] = LOAD_GLOBAL, [LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL, [LOAD_GLOBAL_MODULE] = LOAD_GLOBAL, + [LOAD_LOCALS] = LOAD_LOCALS, [LOAD_NAME] = LOAD_NAME, [LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR, [LOAD_SUPER_ATTR_ATTR] = LOAD_SUPER_ATTR, @@ -329,8 +332,8 @@ static const char *const _PyOpcode_OpName[267] = { [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS", [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", + [LOAD_LOCALS] = "LOAD_LOCALS", [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", - [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", [POP_EXCEPT] = "POP_EXCEPT", [STORE_NAME] = "STORE_NAME", [DELETE_NAME] = "DELETE_NAME", @@ -353,9 +356,9 @@ static const char *const _PyOpcode_OpName[267] = { [IMPORT_NAME] = "IMPORT_NAME", [IMPORT_FROM] = "IMPORT_FROM", [JUMP_FORWARD] = "JUMP_FORWARD", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", - [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE", [POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE", [LOAD_GLOBAL] = "LOAD_GLOBAL", @@ -390,7 +393,7 @@ static const char *const _PyOpcode_OpName[267] = { [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", [MAP_ADD] = "MAP_ADD", - [LOAD_CLASSDEREF] = "LOAD_CLASSDEREF", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [COPY_FREE_VARS] = "COPY_FREE_VARS", [YIELD_VALUE] = "YIELD_VALUE", [RESUME] = "RESUME", @@ -417,8 +420,8 @@ static const char *const _PyOpcode_OpName[267] = { [KW_NAMES] = "KW_NAMES", [CALL_INTRINSIC_1] = "CALL_INTRINSIC_1", [CALL_INTRINSIC_2] = "CALL_INTRINSIC_2", - [175] = "<175>", - [176] = "<176>", + [LOAD_FROM_DICT_OR_GLOBALS] = "LOAD_FROM_DICT_OR_GLOBALS", + [LOAD_FROM_DICT_OR_DEREF] = "LOAD_FROM_DICT_OR_DEREF", [177] = "<177>", [178] = "<178>", [179] = "<179>", @@ -479,7 +482,7 @@ static const char *const _PyOpcode_OpName[267] = { [234] = "<234>", [235] = "<235>", [236] = "<236>", - [237] = "<237>", + [INSTRUMENTED_LOAD_SUPER_ATTR] = "INSTRUMENTED_LOAD_SUPER_ATTR", [INSTRUMENTED_POP_JUMP_IF_NONE] = "INSTRUMENTED_POP_JUMP_IF_NONE", [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", [INSTRUMENTED_RESUME] = "INSTRUMENTED_RESUME", @@ -515,8 +518,6 @@ static const char *const _PyOpcode_OpName[267] = { #define EXTRA_CASES \ case 169: \ case 170: \ - case 175: \ - case 176: \ case 177: \ case 178: \ case 179: \ @@ -577,7 +578,6 @@ static const char *const _PyOpcode_OpName[267] = { case 234: \ case 235: \ case 236: \ - case 237: \ case 255: \ ; diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 7f8cc643ec0c96..7cd998a704c88d 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -31,7 +31,6 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc); extern void _Py_InitVersion(void); extern PyStatus _PyFaulthandler_Init(int enable); -extern int _PyTraceMalloc_Init(int enable); extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp); extern PyStatus _PySys_Create( PyThreadState *tstate, diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 7b9c73dd1edf3b..59ec49af358f2e 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -546,15 +546,19 @@ extern "C" { INIT_STR(dbl_close_br, "}}"), \ INIT_STR(dbl_open_br, "{{"), \ INIT_STR(dbl_percent, "%%"), \ + INIT_STR(defaults, ".defaults"), \ INIT_STR(dot, "."), \ INIT_STR(dot_locals, "."), \ INIT_STR(empty, ""), \ + INIT_STR(generic_base, ".generic_base"), \ INIT_STR(json_decoder, "json.decoder"), \ + INIT_STR(kwdefaults, ".kwdefaults"), \ INIT_STR(list_err, "list index out of range"), \ INIT_STR(newline, "\n"), \ INIT_STR(open_br, "{"), \ INIT_STR(percent, "%"), \ INIT_STR(shim_name, ""), \ + INIT_STR(type_params, ".type_params"), \ INIT_STR(utf_8, "utf-8"), \ } @@ -596,6 +600,8 @@ extern "C" { INIT_ID(__class__), \ INIT_ID(__class_getitem__), \ INIT_ID(__classcell__), \ + INIT_ID(__classdict__), \ + INIT_ID(__classdictcell__), \ INIT_ID(__complex__), \ INIT_ID(__contains__), \ INIT_ID(__copy__), \ @@ -718,6 +724,7 @@ extern "C" { INIT_ID(__subclasshook__), \ INIT_ID(__truediv__), \ INIT_ID(__trunc__), \ + INIT_ID(__type_params__), \ INIT_ID(__typing_is_unpacked_typevartuple__), \ INIT_ID(__typing_prepare_subst__), \ INIT_ID(__typing_subst__), \ @@ -773,8 +780,11 @@ extern "C" { INIT_ID(after_in_child), \ INIT_ID(after_in_parent), \ INIT_ID(aggregate_class), \ + INIT_ID(alias), \ INIT_ID(append), \ + INIT_ID(arg), \ INIT_ID(argdefs), \ + INIT_ID(args), \ INIT_ID(arguments), \ INIT_ID(argv), \ INIT_ID(as_integer_ratio), \ @@ -789,6 +799,7 @@ extern "C" { INIT_ID(big), \ INIT_ID(binary_form), \ INIT_ID(block), \ + INIT_ID(bound), \ INIT_ID(buffer), \ INIT_ID(buffer_callback), \ INIT_ID(buffer_size), \ @@ -844,11 +855,13 @@ extern "C" { INIT_ID(compile_mode), \ INIT_ID(consts), \ INIT_ID(context), \ + INIT_ID(contravariant), \ INIT_ID(cookie), \ INIT_ID(copy), \ INIT_ID(copyreg), \ INIT_ID(coro), \ INIT_ID(count), \ + INIT_ID(covariant), \ INIT_ID(cwd), \ INIT_ID(d), \ INIT_ID(data), \ @@ -899,6 +912,7 @@ extern "C" { INIT_ID(exception), \ INIT_ID(exp), \ INIT_ID(extend), \ + INIT_ID(extra_tokens), \ INIT_ID(facility), \ INIT_ID(factory), \ INIT_ID(false), \ @@ -958,6 +972,7 @@ extern "C" { INIT_ID(incoming), \ INIT_ID(indexgroup), \ INIT_ID(inf), \ + INIT_ID(infer_variance), \ INIT_ID(inheritable), \ INIT_ID(initial), \ INIT_ID(initial_bytes), \ @@ -1051,6 +1066,7 @@ extern "C" { INIT_ID(newline), \ INIT_ID(newlines), \ INIT_ID(next), \ + INIT_ID(nlocals), \ INIT_ID(node_depth), \ INIT_ID(node_offset), \ INIT_ID(ns), \ @@ -1074,6 +1090,7 @@ extern "C" { INIT_ID(optimize), \ INIT_ID(options), \ INIT_ID(order), \ + INIT_ID(origin), \ INIT_ID(out_fd), \ INIT_ID(outgoing), \ INIT_ID(overlapped), \ @@ -1171,6 +1188,7 @@ extern "C" { INIT_ID(stdin), \ INIT_ID(stdout), \ INIT_ID(step), \ + INIT_ID(steps), \ INIT_ID(store_name), \ INIT_ID(strategy), \ INIT_ID(strftime), \ @@ -1207,6 +1225,7 @@ extern "C" { INIT_ID(twice), \ INIT_ID(txt), \ INIT_ID(type), \ + INIT_ID(type_params), \ INIT_ID(tz), \ INIT_ID(tzname), \ INIT_ID(uid), \ diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index 9a005be5402c4e..c8e0578a231756 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -10,8 +10,17 @@ extern "C" { struct _mod; // Type defined in pycore_ast.h -typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock, AnnotationBlock } - _Py_block_ty; +typedef enum _block_type { + FunctionBlock, ClassBlock, ModuleBlock, + // Used for annotations if 'from __future__ import annotations' is active. + // Annotation blocks cannot bind names and are not evaluated. + AnnotationBlock, + // Used for generics and type aliases. These work mostly like functions + // (see PEP 695 for details). The three different blocks function identically; + // they are different enum entries only so that error messages can be more + // precise. + TypeVarBoundBlock, TypeAliasBlock, TypeParamBlock +} _Py_block_ty; typedef enum _comprehension_type { NoComprehension = 0, @@ -49,7 +58,7 @@ typedef struct _symtable_entry { PyObject *ste_varnames; /* list of function parameters */ PyObject *ste_children; /* list of child blocks */ PyObject *ste_directives;/* locations of global and nonlocal statements */ - _Py_block_ty ste_type; /* module, class, function or annotation */ + _Py_block_ty ste_type; int ste_nested; /* true if block is nested */ unsigned ste_free : 1; /* true if block has free variables */ unsigned ste_child_free : 1; /* true if a child block has free vars, @@ -64,8 +73,12 @@ typedef struct _symtable_entry { unsigned ste_needs_class_closure : 1; /* for class scopes, true if a closure over __class__ should be created */ + unsigned ste_needs_classdict : 1; /* for class scopes, true if a closure + over the class dict should be created */ unsigned ste_comp_inlined : 1; /* true if this comprehension is inlined */ unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */ + unsigned ste_can_see_class_scope : 1; /* true if this block can see names bound in an + enclosing class scope */ int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */ int ste_lineno; /* first line of block */ int ste_col_offset; /* offset of first line of block */ @@ -82,6 +95,7 @@ extern PyTypeObject PySTEntry_Type; extern long _PyST_GetSymbol(PySTEntryObject *, PyObject *); extern int _PyST_GetScope(PySTEntryObject *, PyObject *); +extern int _PyST_IsFunctionLike(PySTEntryObject *); extern struct symtable* _PySymtable_Build( struct _mod *mod, @@ -105,14 +119,16 @@ extern PyObject* _Py_Mangle(PyObject *p, PyObject *name); #define DEF_IMPORT 2<<6 /* assignment occurred via import */ #define DEF_ANNOT 2<<7 /* this name is annotated */ #define DEF_COMP_ITER 2<<8 /* this name is a comprehension iteration variable */ +#define DEF_TYPE_PARAM 2<<9 /* this name is a type parameter */ +#define DEF_COMP_CELL 2<<10 /* this name is a cell in an inlined comprehension */ #define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT) /* GLOBAL_EXPLICIT and GLOBAL_IMPLICIT are used internally by the symbol table. GLOBAL is returned from PyST_GetScope() for either of them. - It is stored in ste_symbols at bits 12-15. + It is stored in ste_symbols at bits 13-16. */ -#define SCOPE_OFFSET 11 +#define SCOPE_OFFSET 12 #define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL) #define LOCAL 1 diff --git a/Include/internal/pycore_token.h b/Include/internal/pycore_token.h index b9df8766736adf..c02e637fee1ee2 100644 --- a/Include/internal/pycore_token.h +++ b/Include/internal/pycore_token.h @@ -77,7 +77,9 @@ extern "C" { #define FSTRING_START 61 #define FSTRING_MIDDLE 62 #define FSTRING_END 63 -#define ERRORTOKEN 64 +#define COMMENT 64 +#define NL 65 +#define ERRORTOKEN 66 #define N_TOKENS 68 #define NT_OFFSET 256 diff --git a/Include/internal/pycore_typevarobject.h b/Include/internal/pycore_typevarobject.h new file mode 100644 index 00000000000000..c9fa97d6820757 --- /dev/null +++ b/Include/internal/pycore_typevarobject.h @@ -0,0 +1,24 @@ +#ifndef Py_INTERNAL_TYPEVAROBJECT_H +#define Py_INTERNAL_TYPEVAROBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +extern PyObject *_Py_make_typevar(PyObject *, PyObject *, PyObject *); +extern PyObject *_Py_make_paramspec(PyThreadState *, PyObject *); +extern PyObject *_Py_make_typevartuple(PyThreadState *, PyObject *); +extern PyObject *_Py_make_typealias(PyThreadState *, PyObject *); +extern PyObject *_Py_subscript_generic(PyThreadState *, PyObject *); +extern int _Py_initialize_generic(PyInterpreterState *); +extern void _Py_clear_generic_types(PyInterpreterState *); + +extern PyTypeObject _PyTypeAlias_Type; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_TYPEVAROBJECT_H */ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 8e086edbdf8193..8f8a067e4c1808 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -123,6 +123,12 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(__classcell__); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(__classdict__); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(__classdictcell__); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(__complex__); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -489,6 +495,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(__trunc__); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(__type_params__); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(__typing_is_unpacked_typevartuple__); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -654,12 +663,21 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(aggregate_class); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(alias); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(append); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(arg); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(argdefs); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(args); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(arguments); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -702,6 +720,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(block); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(bound); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(buffer); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -867,6 +888,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(context); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(contravariant); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(cookie); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -882,6 +906,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(count); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(covariant); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(cwd); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1032,6 +1059,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(extend); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(extra_tokens); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(facility); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1209,6 +1239,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(inf); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(infer_variance); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(inheritable); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1488,6 +1521,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(next); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(nlocals); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(node_depth); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1557,6 +1593,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(order); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(origin); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(out_fd); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1848,6 +1887,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(step); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(steps); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(store_name); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); @@ -1956,6 +1998,9 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { string = &_Py_ID(type); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); + string = &_Py_ID(type_params); + assert(_PyUnicode_CheckConsistency(string, 1)); + _PyUnicode_InternInPlace(interp, &string); string = &_Py_ID(tz); assert(_PyUnicode_CheckConsistency(string, 1)); _PyUnicode_InternInPlace(interp, &string); diff --git a/Include/object.h b/Include/object.h index 81aeb2d8bd5a69..c4fe2f83ef62bc 100644 --- a/Include/object.h +++ b/Include/object.h @@ -590,7 +590,7 @@ you can count such references to the type object.) extern Py_ssize_t _Py_RefTotal; # define _Py_INC_REFTOTAL() _Py_RefTotal++ # define _Py_DEC_REFTOTAL() _Py_RefTotal-- -# elif !defined(Py_LIMITED_API) || Py_LIMITED_API+0 > 0x030C0000 +# elif !defined(Py_LIMITED_API) || Py_LIMITED_API+0 > 0x030D0000 PyAPI_FUNC(void) _Py_IncRefTotal_DO_NOT_USE_THIS(void); PyAPI_FUNC(void) _Py_DecRefTotal_DO_NOT_USE_THIS(void); # define _Py_INC_REFTOTAL() _Py_IncRefTotal_DO_NOT_USE_THIS() diff --git a/Include/opcode.h b/Include/opcode.h index c3b6e5dce49ad3..9806511ba4286a 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -45,6 +45,7 @@ extern "C" { #define RETURN_GENERATOR 75 #define RETURN_VALUE 83 #define SETUP_ANNOTATIONS 85 +#define LOAD_LOCALS 87 #define POP_EXCEPT 89 #define HAVE_ARGUMENT 90 #define STORE_NAME 90 @@ -102,7 +103,6 @@ extern "C" { #define LIST_APPEND 145 #define SET_ADD 146 #define MAP_ADD 147 -#define LOAD_CLASSDEREF 148 #define COPY_FREE_VARS 149 #define YIELD_VALUE 150 #define RESUME 151 @@ -118,7 +118,10 @@ extern "C" { #define KW_NAMES 172 #define CALL_INTRINSIC_1 173 #define CALL_INTRINSIC_2 174 -#define MIN_INSTRUMENTED_OPCODE 238 +#define LOAD_FROM_DICT_OR_GLOBALS 175 +#define LOAD_FROM_DICT_OR_DEREF 176 +#define MIN_INSTRUMENTED_OPCODE 237 +#define INSTRUMENTED_LOAD_SUPER_ATTR 237 #define INSTRUMENTED_POP_JUMP_IF_NONE 238 #define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 239 #define INSTRUMENTED_RESUME 240 @@ -199,11 +202,11 @@ extern "C" { #define LOAD_ATTR_METHOD_WITH_VALUES 82 #define LOAD_CONST__LOAD_FAST 84 #define LOAD_FAST__LOAD_CONST 86 -#define LOAD_FAST__LOAD_FAST 87 -#define LOAD_GLOBAL_BUILTIN 88 -#define LOAD_GLOBAL_MODULE 111 -#define STORE_ATTR_INSTANCE_VALUE 112 -#define STORE_ATTR_SLOT 113 +#define LOAD_FAST__LOAD_FAST 88 +#define LOAD_GLOBAL_BUILTIN 111 +#define LOAD_GLOBAL_MODULE 112 +#define STORE_ATTR_INSTANCE_VALUE 113 +#define STORE_ATTR_SLOT 148 #define STORE_ATTR_WITH_HINT 153 #define STORE_FAST__LOAD_FAST 154 #define STORE_FAST__STORE_FAST 158 diff --git a/Include/patchlevel.h b/Include/patchlevel.h index aaedd563a905e9..ae9d36c12d6eaf 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -17,13 +17,13 @@ /* Version parsed out into numeric values */ /*--start constants--*/ #define PY_MAJOR_VERSION 3 -#define PY_MINOR_VERSION 12 +#define PY_MINOR_VERSION 13 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 7 +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.12.0a7+" +#define PY_VERSION "3.13.0a0" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Include/sysmodule.h b/Include/sysmodule.h index b5087119b1cae7..96f883870b34dc 100644 --- a/Include/sysmodule.h +++ b/Include/sysmodule.h @@ -29,6 +29,19 @@ Py_DEPRECATED(3.11) PyAPI_FUNC(int) PySys_HasWarnOptions(void); Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *); PyAPI_FUNC(PyObject *) PySys_GetXOptions(void); +#if !defined(Py_LIMITED_API) +typedef struct { + FILE* perf_map; + PyThread_type_lock map_lock; +} PerfMapState; + +PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void); + +PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry(const void *code_addr, unsigned int code_size, const char *entry_name); + +PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void); +#endif + #ifndef Py_LIMITED_API # define Py_CPYTHON_SYSMODULE_H # include "cpython/sysmodule.h" diff --git a/Include/tracemalloc.h b/Include/tracemalloc.h index bd14217c199c3c..580027a8e365e5 100644 --- a/Include/tracemalloc.h +++ b/Include/tracemalloc.h @@ -33,6 +33,40 @@ PyAPI_FUNC(int) PyTraceMalloc_Untrack( PyAPI_FUNC(PyObject*) _PyTraceMalloc_GetTraceback( unsigned int domain, uintptr_t ptr); + +/* Return non-zero if tracemalloc is tracing */ +PyAPI_FUNC(int) _PyTraceMalloc_IsTracing(void); + +/* Clear the tracemalloc traces */ +PyAPI_FUNC(void) _PyTraceMalloc_ClearTraces(void); + +/* Clear the tracemalloc traces */ +PyAPI_FUNC(PyObject *) _PyTraceMalloc_GetTraces(void); + +/* Clear tracemalloc traceback for an object */ +PyAPI_FUNC(PyObject *) _PyTraceMalloc_GetObjectTraceback(PyObject *obj); + +/* Initialize tracemalloc */ +PyAPI_FUNC(int) _PyTraceMalloc_Init(void); + +/* Start tracemalloc */ +PyAPI_FUNC(int) _PyTraceMalloc_Start(int max_nframe); + +/* Stop tracemalloc */ +PyAPI_FUNC(void) _PyTraceMalloc_Stop(void); + +/* Get the tracemalloc traceback limit */ +PyAPI_FUNC(int) _PyTraceMalloc_GetTracebackLimit(void); + +/* Get the memory usage of tracemalloc in bytes */ +PyAPI_FUNC(size_t) _PyTraceMalloc_GetMemory(void); + +/* Get the current size and peak size of traced memory blocks as a 2-tuple */ +PyAPI_FUNC(PyObject *) _PyTraceMalloc_GetTracedMemory(void); + +/* Set the peak size of traced memory blocks to the current size */ +PyAPI_FUNC(void) _PyTraceMalloc_ResetPeak(void); + #endif #endif /* !Py_TRACEMALLOC_H */ diff --git a/Lib/argparse.py b/Lib/argparse.py index f5f44ff02c0d38..543d9944f9ede3 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -883,16 +883,19 @@ def __call__(self, parser, namespace, values, option_string=None): raise NotImplementedError(_('.__call__() not defined')) +# FIXME: remove together with `BooleanOptionalAction` deprecated arguments. +_deprecated_default = object() + class BooleanOptionalAction(Action): def __init__(self, option_strings, dest, default=None, - type=None, - choices=None, + type=_deprecated_default, + choices=_deprecated_default, required=False, help=None, - metavar=None): + metavar=_deprecated_default): _option_strings = [] for option_string in option_strings: @@ -902,6 +905,24 @@ def __init__(self, option_string = '--no-' + option_string[2:] _option_strings.append(option_string) + # We need `_deprecated` special value to ban explicit arguments that + # match default value. Like: + # parser.add_argument('-f', action=BooleanOptionalAction, type=int) + for field_name in ('type', 'choices', 'metavar'): + if locals()[field_name] is not _deprecated_default: + warnings._deprecated( + field_name, + "{name!r} is deprecated as of Python 3.12 and will be " + "removed in Python {remove}.", + remove=(3, 14)) + + if type is _deprecated_default: + type = None + if choices is _deprecated_default: + choices = None + if metavar is _deprecated_default: + metavar = None + super().__init__( option_strings=_option_strings, dest=dest, diff --git a/Lib/ast.py b/Lib/ast.py index 65152047a22370..226910ecac0b4a 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -1051,6 +1051,7 @@ def visit_ClassDef(self, node): self.fill("@") self.traverse(deco) self.fill("class " + node.name) + self._type_params_helper(node.type_params) with self.delimit_if("(", ")", condition = node.bases or node.keywords): comma = False for e in node.bases: @@ -1082,6 +1083,7 @@ def _function_helper(self, node, fill_suffix): self.traverse(deco) def_str = fill_suffix + " " + node.name self.fill(def_str) + self._type_params_helper(node.type_params) with self.delimit("(", ")"): self.traverse(node.args) if node.returns: @@ -1090,6 +1092,30 @@ def _function_helper(self, node, fill_suffix): with self.block(extra=self.get_type_comment(node)): self._write_docstring_and_traverse_body(node) + def _type_params_helper(self, type_params): + if type_params is not None and len(type_params) > 0: + with self.delimit("[", "]"): + self.interleave(lambda: self.write(", "), self.traverse, type_params) + + def visit_TypeVar(self, node): + self.write(node.name) + if node.bound: + self.write(": ") + self.traverse(node.bound) + + def visit_TypeVarTuple(self, node): + self.write("*" + node.name) + + def visit_ParamSpec(self, node): + self.write("**" + node.name) + + def visit_TypeAlias(self, node): + self.fill("type ") + self.traverse(node.name) + self._type_params_helper(node.type_params) + self.write(" = ") + self.traverse(node.value) + def visit_For(self, node): self._for_helper("for ", node) diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py index 50727ca300e63e..c4e5ba2061cffc 100644 --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -81,6 +81,9 @@ def pipe_connection_lost(self, fd, exc): self._stdin_closed.set_result(None) else: self._stdin_closed.set_exception(exc) + # Since calling `wait_closed()` is not mandatory, + # we shouldn't log the traceback if this is not awaited. + self._stdin_closed._log_traceback = False return if fd == 1: reader = self.stdout diff --git a/Lib/enum.py b/Lib/enum.py index 6e497f7ef6a7de..b50fe50d8258d3 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -388,16 +388,8 @@ def __setitem__(self, key, value): Single underscore (sunder) names are reserved. """ - if _is_internal_class(self._cls_name, value): - import warnings - warnings.warn( - "In 3.13 classes created inside an enum will not become a member. " - "Use the `member` decorator to keep the current behavior.", - DeprecationWarning, - stacklevel=2, - ) if _is_private(self._cls_name, key): - # also do nothing, name will be a normal attribute + # do nothing, name will be a normal attribute pass elif _is_sunder(key): if key not in ( @@ -440,10 +432,9 @@ def __setitem__(self, key, value): value = value.value elif _is_descriptor(value): pass - # TODO: uncomment next three lines in 3.13 - # elif _is_internal_class(self._cls_name, value): - # # do nothing, name will be a normal attribute - # pass + elif _is_internal_class(self._cls_name, value): + # do nothing, name will be a normal attribute + pass else: if key in self: # enum overwriting a descriptor? @@ -1169,28 +1160,13 @@ def _generate_next_value_(name, start, count, last_values): if not last_values: return start try: - last = last_values[-1] - last_values.sort() - if last == last_values[-1]: - # no difference between old and new methods - return last + 1 - else: - # trigger old method (with warning) - raise TypeError + last_value = sorted(last_values).pop() except TypeError: - import warnings - warnings.warn( - "In 3.13 the default `auto()`/`_generate_next_value_` will require all values to be sortable and support adding +1\n" - "and the value returned will be the largest value in the enum incremented by 1", - DeprecationWarning, - stacklevel=3, - ) - for v in last_values: - try: - return v + 1 - except TypeError: - pass - return start + raise TypeError('unable to sort non-numeric values') from None + try: + return last_value + 1 + except TypeError: + raise TypeError('unable to increment %r' % (last_value, )) from None @classmethod def _missing_(cls, value): diff --git a/Lib/functools.py b/Lib/functools.py index aaf4291150fbbf..72b2103e7a5544 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -30,7 +30,7 @@ # wrapper functions that can handle naive introspection WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__', - '__annotations__') + '__annotations__', '__type_params__') WRAPPER_UPDATES = ('__dict__',) def update_wrapper(wrapper, wrapped, diff --git a/Lib/http/client.py b/Lib/http/client.py index 50f2b4680769c8..59a9fd72b4722f 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -221,8 +221,9 @@ def _read_headers(fp): break return headers -def parse_headers(fp, _class=HTTPMessage): - """Parses only RFC2822 headers from a file pointer. +def _parse_header_lines(header_lines, _class=HTTPMessage): + """ + Parses only RFC2822 headers from header lines. email Parser wants to see strings rather than bytes. But a TextIOWrapper around self.rfile would buffer too many bytes @@ -231,10 +232,15 @@ def parse_headers(fp, _class=HTTPMessage): to parse. """ - headers = _read_headers(fp) - hstring = b''.join(headers).decode('iso-8859-1') + hstring = b''.join(header_lines).decode('iso-8859-1') return email.parser.Parser(_class=_class).parsestr(hstring) +def parse_headers(fp, _class=HTTPMessage): + """Parses only RFC2822 headers from a file pointer.""" + + headers = _read_headers(fp) + return _parse_header_lines(headers, _class) + class HTTPResponse(io.BufferedIOBase): @@ -858,7 +864,7 @@ def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, self._tunnel_host = None self._tunnel_port = None self._tunnel_headers = {} - self._proxy_response_headers = None + self._raw_proxy_headers = None (self.host, self.port) = self._get_hostport(host, port) @@ -945,11 +951,11 @@ def _tunnel(self): try: (version, code, message) = response._read_status() - self._proxy_response_headers = parse_headers(response.fp) + self._raw_proxy_headers = _read_headers(response.fp) if self.debuglevel > 0: - for hdr, val in self._proxy_response_headers.items(): - print("header:", hdr + ":", val) + for header in self._raw_proxy_headers: + print('header:', header.decode()) if code != http.HTTPStatus.OK: self.close() @@ -958,6 +964,21 @@ def _tunnel(self): finally: response.close() + def get_proxy_response_headers(self): + """ + Returns a dictionary with the headers of the response + received from the proxy server to the CONNECT request + sent to set the tunnel. + + If the CONNECT request was not sent, the method returns + an empty dictionary. + """ + return ( + _parse_header_lines(self._raw_proxy_headers) + if self._raw_proxy_headers is not None + else {} + ) + def connect(self): """Connect to the host and port specified in __init__.""" sys.audit("http.client.connect", self, self.host, self.port) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index e97e3ca01ef30c..553b932aa6b6bc 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -4,6 +4,11 @@ Released on 2023-10-02 ========================= +gh-104499: Fix completions for Tk Aqua 8.7 (currently blank). + +gh-104486: Make About print both tcl and tk versions if different, +as is expected someday. + gh-88496 Fix IDLE test hang on macOS. gh-103314 Support sys.last_exc after exceptions in Shell. diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index 0f835a9cc1d010..24320b5a3bffab 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -182,16 +182,11 @@ def show_window(self, comp_lists, index, complete, mode, userWantsWin): self.userwantswindow = userWantsWin self.lasttypedstart = self.start - # Put widgets in place self.autocompletewindow = acw = Toplevel(self.widget) - # Put it in a position so that it is not seen. - acw.wm_geometry("+10000+10000") - # Make it float + acw.withdraw() acw.wm_overrideredirect(1) try: - # This command is only needed and available on Tk >= 8.4.0 for OSX - # Without it, call tips intrude on the typing process by grabbing - # the focus. + # Prevent grabbing focus on macOS. acw.tk.call("::tk::unsupported::MacWindowStyle", "style", acw._w, "help", "noActivates") except TclError: @@ -271,6 +266,7 @@ def winconfig_event(self, event): # place acw above current line new_y -= acw_height acw.wm_geometry("+%d+%d" % (new_x, new_y)) + acw.deiconify() acw.update_idletasks() except TclError: pass diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 21402ad7139173..df36be8766016f 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1643,19 +1643,13 @@ def tokeneater(self, type, token, start, end, line, self.finished = 1 def run(self): - save_tabsize = tokenize.tabsize - tokenize.tabsize = self.tabwidth try: - try: - tokens = tokenize.generate_tokens(self.readline) - for token in tokens: - self.tokeneater(*token) - except (tokenize.TokenError, SyntaxError): - # since we cut off the tokenizer early, we can trigger - # spurious errors - pass - finally: - tokenize.tabsize = save_tabsize + tokens = tokenize.generate_tokens(self.readline) + for token in tokens: + self.tokeneater(*token) + except (tokenize.TokenError, SyntaxError): + # Stopping the tokenizer early can trigger spurious errors. + pass return self.blkopenline, self.indentedline ### end autoindent code ### diff --git a/Lib/idlelib/help_about.py b/Lib/idlelib/help_about.py index a0085a40b980ef..cfa4ca781f087d 100644 --- a/Lib/idlelib/help_about.py +++ b/Lib/idlelib/help_about.py @@ -11,15 +11,12 @@ from idlelib import textview -version = python_version() +pyver = python_version() - -def build_bits(): - "Return bits for platform." - if sys.platform == 'darwin': - return '64' if sys.maxsize > 2**32 else '32' - else: - return architecture()[0][:2] +if sys.platform == 'darwin': + bits = '64' if sys.maxsize > 2**32 else '32' +else: + bits = architecture()[0][:2] class AboutDialog(Toplevel): @@ -45,7 +42,7 @@ def __init__(self, parent, title=None, *, _htest=False, _utest=False): self.create_widgets() self.resizable(height=False, width=False) self.title(title or - f'About IDLE {version} ({build_bits()} bit)') + f'About IDLE {pyver} ({bits} bit)') self.transient(parent) self.grab_set() self.protocol("WM_DELETE_WINDOW", self.ok) @@ -76,8 +73,8 @@ def create_widgets(self): bg=self.bg, font=('courier', 24, 'bold')) header.grid(row=0, column=0, sticky=E, padx=10, pady=10) - tk_patchlevel = self.info_patchlevel() - ext = '.png' if tk_patchlevel >= (8, 6) else '.gif' + tkpatch = self._root().getvar('tk_patchLevel') + ext = '.png' if tkpatch >= '8.6' else '.gif' icon = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Icons', f'idle_48{ext}') self.icon_image = PhotoImage(master=self._root(), file=icon) @@ -102,13 +99,11 @@ def create_widgets(self): height=2, bg=self.bg).grid(row=8, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - pyver = Label(frame_background, - text='Python version: ' + version, - fg=self.fg, bg=self.bg) - pyver.grid(row=9, column=0, sticky=W, padx=10, pady=0) - tkver = Label(frame_background, text=f'Tk version: {tk_patchlevel}', - fg=self.fg, bg=self.bg) - tkver.grid(row=9, column=1, sticky=W, padx=2, pady=0) + tclver = str(self.info_patchlevel()) + tkver = ' and ' + tkpatch if tkpatch != tclver else '' + versions = f"Python {pyver} with tcl/tk {tclver}{tkver}" + vers = Label(frame_background, text=versions, fg=self.fg, bg=self.bg) + vers.grid(row=9, column=0, sticky=W, padx=10, pady=0) py_buttons = Frame(frame_background, bg=self.bg) py_buttons.grid(row=10, column=0, columnspan=2, sticky=NSEW) self.py_license = Button(py_buttons, text='License', width=8, @@ -128,10 +123,10 @@ def create_widgets(self): height=2, bg=self.bg).grid(row=11, column=0, sticky=EW, columnspan=3, padx=5, pady=5) - idlever = Label(frame_background, - text='IDLE version: ' + version, + idle = Label(frame_background, + text='IDLE', fg=self.fg, bg=self.bg) - idlever.grid(row=12, column=0, sticky=W, padx=10, pady=0) + idle.grid(row=12, column=0, sticky=W, padx=10, pady=0) idle_buttons = Frame(frame_background, bg=self.bg) idle_buttons.grid(row=13, column=0, columnspan=3, sticky=NSEW) self.readme = Button(idle_buttons, text='README', width=8, diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py index b915535acac0cc..8b79487b15d4cd 100644 --- a/Lib/idlelib/idle_test/test_help_about.py +++ b/Lib/idlelib/idle_test/test_help_about.py @@ -36,7 +36,7 @@ def tearDownClass(cls): del cls.root def test_build_bits(self): - self.assertIn(help_about.build_bits(), ('32', '64')) + self.assertIn(help_about.bits, ('32', '64')) def test_dialog_title(self): """Test about dialog title""" @@ -107,7 +107,7 @@ def test_dialog_title(self): """Test about dialog title""" self.assertEqual(self.dialog.title(), f'About IDLE {python_version()}' - f' ({help_about.build_bits()} bit)') + f' ({help_about.bits} bit)') class CloseTest(unittest.TestCase): diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 3ca5a1aea28af7..73ac4405cb54cf 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -444,6 +444,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.12b1 3528 (Add LOAD_SUPER_ATTR_METHOD specialization) # Python 3.12b1 3529 (Inline list/dict/set comprehensions) # Python 3.12b1 3530 (Shrink the LOAD_SUPER_ATTR caches) +# Python 3.12b1 3531 (Add PEP 695 changes) # Python 3.13 will start with 3550 @@ -460,7 +461,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3530).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3531).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c diff --git a/Lib/inspect.py b/Lib/inspect.py index a64e85e4fd67a4..7709a95003efbd 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1835,8 +1835,10 @@ def getattr_static(obj, attr, default=_sentinel): klass_result = _check_class(klass, attr) if instance_result is not _sentinel and klass_result is not _sentinel: - if (_check_class(type(klass_result), '__get__') is not _sentinel and - _check_class(type(klass_result), '__set__') is not _sentinel): + if _check_class(type(klass_result), "__get__") is not _sentinel and ( + _check_class(type(klass_result), "__set__") is not _sentinel + or _check_class(type(klass_result), "__delete__") is not _sentinel + ): return klass_result if instance_result is not _sentinel: @@ -2185,7 +2187,7 @@ def _signature_strip_non_python_syntax(signature): if string == ',': current_parameter += 1 - if (type == ERRORTOKEN) and (string == '$'): + if (type == OP) and (string == '$'): assert self_parameter is None self_parameter = current_parameter continue @@ -2193,7 +2195,7 @@ def _signature_strip_non_python_syntax(signature): add(string) if (string == ','): add(' ') - clean_signature = ''.join(text) + clean_signature = ''.join(text).strip() return clean_signature, self_parameter diff --git a/Lib/keyword.py b/Lib/keyword.py index cc2b46b7229d53..e22c837835e740 100644 --- a/Lib/keyword.py +++ b/Lib/keyword.py @@ -56,7 +56,8 @@ softkwlist = [ '_', 'case', - 'match' + 'match', + 'type' ] iskeyword = frozenset(kwlist).__contains__ diff --git a/Lib/lib2to3/Grammar.txt b/Lib/lib2to3/Grammar.txt deleted file mode 100644 index fa7b15061d941c..00000000000000 --- a/Lib/lib2to3/Grammar.txt +++ /dev/null @@ -1,196 +0,0 @@ -# Grammar for 2to3. This grammar supports Python 2.x and 3.x. - -# NOTE WELL: You should also follow all the steps listed at -# https://devguide.python.org/grammar/ - -# Start symbols for the grammar: -# file_input is a module or sequence of commands read from an input file; -# single_input is a single interactive statement; -# eval_input is the input for the eval() and input() functions. -# NB: compound_stmt in single_input is followed by extra NEWLINE! -file_input: (NEWLINE | stmt)* ENDMARKER -single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE -eval_input: testlist NEWLINE* ENDMARKER - -decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE -decorators: decorator+ -decorated: decorators (classdef | funcdef | async_funcdef) -async_funcdef: ASYNC funcdef -funcdef: 'def' NAME parameters ['->' test] ':' suite -parameters: '(' [typedargslist] ')' - -# The following definition for typedarglist is equivalent to this set of rules: -# -# arguments = argument (',' argument)* -# argument = tfpdef ['=' test] -# kwargs = '**' tname [','] -# args = '*' [tname] -# kwonly_kwargs = (',' argument)* [',' [kwargs]] -# args_kwonly_kwargs = args kwonly_kwargs | kwargs -# poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]] -# typedargslist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs -# typedarglist = arguments ',' '/' [',' [typedargslist_no_posonly]])|(typedargslist_no_posonly)" -# -# It needs to be fully expanded to allow our LL(1) parser to work on it. - -typedargslist: tfpdef ['=' test] (',' tfpdef ['=' test])* ',' '/' [ - ',' [((tfpdef ['=' test] ',')* ('*' [tname] (',' tname ['=' test])* - [',' ['**' tname [',']]] | '**' tname [',']) - | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])] - ] | ((tfpdef ['=' test] ',')* ('*' [tname] (',' tname ['=' test])* - [',' ['**' tname [',']]] | '**' tname [',']) - | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) - -tname: NAME [':' test] -tfpdef: tname | '(' tfplist ')' -tfplist: tfpdef (',' tfpdef)* [','] - -# The following definition for varargslist is equivalent to this set of rules: -# -# arguments = argument (',' argument )* -# argument = vfpdef ['=' test] -# kwargs = '**' vname [','] -# args = '*' [vname] -# kwonly_kwargs = (',' argument )* [',' [kwargs]] -# args_kwonly_kwargs = args kwonly_kwargs | kwargs -# poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]] -# vararglist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs -# varargslist = arguments ',' '/' [','[(vararglist_no_posonly)]] | (vararglist_no_posonly) -# -# It needs to be fully expanded to allow our LL(1) parser to work on it. - -varargslist: vfpdef ['=' test ](',' vfpdef ['=' test])* ',' '/' [',' [ - ((vfpdef ['=' test] ',')* ('*' [vname] (',' vname ['=' test])* - [',' ['**' vname [',']]] | '**' vname [',']) - | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) - ]] | ((vfpdef ['=' test] ',')* - ('*' [vname] (',' vname ['=' test])* [',' ['**' vname [',']]]| '**' vname [',']) - | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) - -vname: NAME -vfpdef: vname | '(' vfplist ')' -vfplist: vfpdef (',' vfpdef)* [','] - -stmt: simple_stmt | compound_stmt -simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE -small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | - import_stmt | global_stmt | exec_stmt | assert_stmt) -expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) | - ('=' (yield_expr|testlist_star_expr))*) -annassign: ':' test ['=' test] -testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [','] -augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | - '<<=' | '>>=' | '**=' | '//=') -# For normal and annotated assignments, additional restrictions enforced by the interpreter -print_stmt: 'print' ( [ test (',' test)* [','] ] | - '>>' test [ (',' test)+ [','] ] ) -del_stmt: 'del' exprlist -pass_stmt: 'pass' -flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt -break_stmt: 'break' -continue_stmt: 'continue' -return_stmt: 'return' [testlist_star_expr] -yield_stmt: yield_expr -raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]] -import_stmt: import_name | import_from -import_name: 'import' dotted_as_names -import_from: ('from' ('.'* dotted_name | '.'+) - 'import' ('*' | '(' import_as_names ')' | import_as_names)) -import_as_name: NAME ['as' NAME] -dotted_as_name: dotted_name ['as' NAME] -import_as_names: import_as_name (',' import_as_name)* [','] -dotted_as_names: dotted_as_name (',' dotted_as_name)* -dotted_name: NAME ('.' NAME)* -global_stmt: ('global' | 'nonlocal') NAME (',' NAME)* -exec_stmt: 'exec' expr ['in' test [',' test]] -assert_stmt: 'assert' test [',' test] - -compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt -async_stmt: ASYNC (funcdef | with_stmt | for_stmt) -if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite] -while_stmt: 'while' namedexpr_test ':' suite ['else' ':' suite] -for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] -try_stmt: ('try' ':' suite - ((except_clause ':' suite)+ - ['else' ':' suite] - ['finally' ':' suite] | - 'finally' ':' suite)) -with_stmt: 'with' with_item (',' with_item)* ':' suite -with_item: test ['as' expr] -with_var: 'as' expr -# NB compile.c makes sure that the default except clause is last -except_clause: 'except' [test [(',' | 'as') test]] -suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT - -# Backward compatibility cruft to support: -# [ x for x in lambda: True, lambda: False if x() ] -# even while also allowing: -# lambda x: 5 if x else 2 -# (But not a mix of the two) -testlist_safe: old_test [(',' old_test)+ [',']] -old_test: or_test | old_lambdef -old_lambdef: 'lambda' [varargslist] ':' old_test - -namedexpr_test: test [':=' test] -test: or_test ['if' or_test 'else' test] | lambdef -or_test: and_test ('or' and_test)* -and_test: not_test ('and' not_test)* -not_test: 'not' not_test | comparison -comparison: expr (comp_op expr)* -comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' -star_expr: '*' expr -expr: xor_expr ('|' xor_expr)* -xor_expr: and_expr ('^' and_expr)* -and_expr: shift_expr ('&' shift_expr)* -shift_expr: arith_expr (('<<'|'>>') arith_expr)* -arith_expr: term (('+'|'-') term)* -term: factor (('*'|'@'|'/'|'%'|'//') factor)* -factor: ('+'|'-'|'~') factor | power -power: [AWAIT] atom trailer* ['**' factor] -atom: ('(' [yield_expr|testlist_gexp] ')' | - '[' [listmaker] ']' | - '{' [dictsetmaker] '}' | - '`' testlist1 '`' | - NAME | NUMBER | STRING+ | '.' '.' '.') -listmaker: (namedexpr_test|star_expr) ( comp_for | (',' (namedexpr_test|star_expr))* [','] ) -testlist_gexp: (namedexpr_test|star_expr) ( comp_for | (',' (namedexpr_test|star_expr))* [','] ) -lambdef: 'lambda' [varargslist] ':' test -trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME -subscriptlist: subscript (',' subscript)* [','] -subscript: test | [test] ':' [test] [sliceop] -sliceop: ':' [test] -exprlist: (expr|star_expr) (',' (expr|star_expr))* [','] -testlist: test (',' test)* [','] -dictsetmaker: ( ((test ':' test | '**' expr) - (comp_for | (',' (test ':' test | '**' expr))* [','])) | - ((test | star_expr) - (comp_for | (',' (test | star_expr))* [','])) ) - -classdef: 'class' NAME ['(' [arglist] ')'] ':' suite - -arglist: argument (',' argument)* [','] - -# "test '=' test" is really "keyword '=' test", but we have no such token. -# These need to be in a single rule to avoid grammar that is ambiguous -# to our LL(1) parser. Even though 'test' includes '*expr' in star_expr, -# we explicitly match '*' here, too, to give it proper precedence. -# Illegal combinations and orderings are blocked in ast.c: -# multiple (test comp_for) arguments are blocked; keyword unpackings -# that precede iterable unpackings are blocked; etc. -argument: ( test [comp_for] | - test ':=' test | - test '=' test | - '**' test | - '*' test ) - -comp_iter: comp_for | comp_if -comp_for: [ASYNC] 'for' exprlist 'in' testlist_safe [comp_iter] -comp_if: 'if' old_test [comp_iter] - -testlist1: test (',' test)* - -# not used in grammar, but may appear in "node" passed from Parser to Compiler -encoding_decl: NAME - -yield_expr: 'yield' [yield_arg] -yield_arg: 'from' test | testlist_star_expr diff --git a/Lib/lib2to3/PatternGrammar.txt b/Lib/lib2to3/PatternGrammar.txt deleted file mode 100644 index 36bf8148273bd7..00000000000000 --- a/Lib/lib2to3/PatternGrammar.txt +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -# A grammar to describe tree matching patterns. -# Not shown here: -# - 'TOKEN' stands for any token (leaf node) -# - 'any' stands for any node (leaf or interior) -# With 'any' we can still specify the sub-structure. - -# The start symbol is 'Matcher'. - -Matcher: Alternatives ENDMARKER - -Alternatives: Alternative ('|' Alternative)* - -Alternative: (Unit | NegatedUnit)+ - -Unit: [NAME '='] ( STRING [Repeater] - | NAME [Details] [Repeater] - | '(' Alternatives ')' [Repeater] - | '[' Alternatives ']' - ) - -NegatedUnit: 'not' (STRING | NAME [Details] | '(' Alternatives ')') - -Repeater: '*' | '+' | '{' NUMBER [',' NUMBER] '}' - -Details: '<' Alternatives '>' diff --git a/Lib/lib2to3/__init__.py b/Lib/lib2to3/__init__.py deleted file mode 100644 index 177405c8090d3e..00000000000000 --- a/Lib/lib2to3/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -import warnings - - -warnings.warn( - "lib2to3 package is deprecated and may not be able to parse Python 3.10+", - DeprecationWarning, - stacklevel=2, -) diff --git a/Lib/lib2to3/__main__.py b/Lib/lib2to3/__main__.py deleted file mode 100644 index 80688baf27abfc..00000000000000 --- a/Lib/lib2to3/__main__.py +++ /dev/null @@ -1,4 +0,0 @@ -import sys -from .main import main - -sys.exit(main("lib2to3.fixes")) diff --git a/Lib/lib2to3/btm_matcher.py b/Lib/lib2to3/btm_matcher.py deleted file mode 100644 index 3b78868038bda0..00000000000000 --- a/Lib/lib2to3/btm_matcher.py +++ /dev/null @@ -1,163 +0,0 @@ -"""A bottom-up tree matching algorithm implementation meant to speed -up 2to3's matching process. After the tree patterns are reduced to -their rarest linear path, a linear Aho-Corasick automaton is -created. The linear automaton traverses the linear paths from the -leaves to the root of the AST and returns a set of nodes for further -matching. This reduces significantly the number of candidate nodes.""" - -__author__ = "George Boutsioukis " - -import logging -import itertools -from collections import defaultdict - -from . import pytree -from .btm_utils import reduce_tree - -class BMNode(object): - """Class for a node of the Aho-Corasick automaton used in matching""" - count = itertools.count() - def __init__(self): - self.transition_table = {} - self.fixers = [] - self.id = next(BMNode.count) - self.content = '' - -class BottomMatcher(object): - """The main matcher class. After instantiating the patterns should - be added using the add_fixer method""" - - def __init__(self): - self.match = set() - self.root = BMNode() - self.nodes = [self.root] - self.fixers = [] - self.logger = logging.getLogger("RefactoringTool") - - def add_fixer(self, fixer): - """Reduces a fixer's pattern tree to a linear path and adds it - to the matcher(a common Aho-Corasick automaton). The fixer is - appended on the matching states and called when they are - reached""" - self.fixers.append(fixer) - tree = reduce_tree(fixer.pattern_tree) - linear = tree.get_linear_subpattern() - match_nodes = self.add(linear, start=self.root) - for match_node in match_nodes: - match_node.fixers.append(fixer) - - def add(self, pattern, start): - "Recursively adds a linear pattern to the AC automaton" - #print("adding pattern", pattern, "to", start) - if not pattern: - #print("empty pattern") - return [start] - if isinstance(pattern[0], tuple): - #alternatives - #print("alternatives") - match_nodes = [] - for alternative in pattern[0]: - #add all alternatives, and add the rest of the pattern - #to each end node - end_nodes = self.add(alternative, start=start) - for end in end_nodes: - match_nodes.extend(self.add(pattern[1:], end)) - return match_nodes - else: - #single token - #not last - if pattern[0] not in start.transition_table: - #transition did not exist, create new - next_node = BMNode() - start.transition_table[pattern[0]] = next_node - else: - #transition exists already, follow - next_node = start.transition_table[pattern[0]] - - if pattern[1:]: - end_nodes = self.add(pattern[1:], start=next_node) - else: - end_nodes = [next_node] - return end_nodes - - def run(self, leaves): - """The main interface with the bottom matcher. The tree is - traversed from the bottom using the constructed - automaton. Nodes are only checked once as the tree is - retraversed. When the automaton fails, we give it one more - shot(in case the above tree matches as a whole with the - rejected leaf), then we break for the next leaf. There is the - special case of multiple arguments(see code comments) where we - recheck the nodes - - Args: - The leaves of the AST tree to be matched - - Returns: - A dictionary of node matches with fixers as the keys - """ - current_ac_node = self.root - results = defaultdict(list) - for leaf in leaves: - current_ast_node = leaf - while current_ast_node: - current_ast_node.was_checked = True - for child in current_ast_node.children: - # multiple statements, recheck - if isinstance(child, pytree.Leaf) and child.value == ";": - current_ast_node.was_checked = False - break - if current_ast_node.type == 1: - #name - node_token = current_ast_node.value - else: - node_token = current_ast_node.type - - if node_token in current_ac_node.transition_table: - #token matches - current_ac_node = current_ac_node.transition_table[node_token] - for fixer in current_ac_node.fixers: - results[fixer].append(current_ast_node) - else: - #matching failed, reset automaton - current_ac_node = self.root - if (current_ast_node.parent is not None - and current_ast_node.parent.was_checked): - #the rest of the tree upwards has been checked, next leaf - break - - #recheck the rejected node once from the root - if node_token in current_ac_node.transition_table: - #token matches - current_ac_node = current_ac_node.transition_table[node_token] - for fixer in current_ac_node.fixers: - results[fixer].append(current_ast_node) - - current_ast_node = current_ast_node.parent - return results - - def print_ac(self): - "Prints a graphviz diagram of the BM automaton(for debugging)" - print("digraph g{") - def print_node(node): - for subnode_key in node.transition_table.keys(): - subnode = node.transition_table[subnode_key] - print("%d -> %d [label=%s] //%s" % - (node.id, subnode.id, type_repr(subnode_key), str(subnode.fixers))) - if subnode_key == 1: - print(subnode.content) - print_node(subnode) - print_node(self.root) - print("}") - -# taken from pytree.py for debugging; only used by print_ac -_type_reprs = {} -def type_repr(type_num): - global _type_reprs - if not _type_reprs: - from .pygram import python_symbols - # printing tokens is possible but not as useful - # from .pgen2 import token // token.__dict__.items(): - for name, val in python_symbols.__dict__.items(): - if type(val) == int: _type_reprs[val] = name - return _type_reprs.setdefault(type_num, type_num) diff --git a/Lib/lib2to3/btm_utils.py b/Lib/lib2to3/btm_utils.py deleted file mode 100644 index b61afdba693071..00000000000000 --- a/Lib/lib2to3/btm_utils.py +++ /dev/null @@ -1,280 +0,0 @@ -"Utility functions used by the btm_matcher module" - -from . import pytree -from .pgen2 import grammar, token -from .pygram import pattern_symbols, python_symbols - -syms = pattern_symbols -pysyms = python_symbols -tokens = grammar.opmap -token_labels = token - -TYPE_ANY = -1 -TYPE_ALTERNATIVES = -2 -TYPE_GROUP = -3 - -class MinNode(object): - """This class serves as an intermediate representation of the - pattern tree during the conversion to sets of leaf-to-root - subpatterns""" - - def __init__(self, type=None, name=None): - self.type = type - self.name = name - self.children = [] - self.leaf = False - self.parent = None - self.alternatives = [] - self.group = [] - - def __repr__(self): - return str(self.type) + ' ' + str(self.name) - - def leaf_to_root(self): - """Internal method. Returns a characteristic path of the - pattern tree. This method must be run for all leaves until the - linear subpatterns are merged into a single""" - node = self - subp = [] - while node: - if node.type == TYPE_ALTERNATIVES: - node.alternatives.append(subp) - if len(node.alternatives) == len(node.children): - #last alternative - subp = [tuple(node.alternatives)] - node.alternatives = [] - node = node.parent - continue - else: - node = node.parent - subp = None - break - - if node.type == TYPE_GROUP: - node.group.append(subp) - #probably should check the number of leaves - if len(node.group) == len(node.children): - subp = get_characteristic_subpattern(node.group) - node.group = [] - node = node.parent - continue - else: - node = node.parent - subp = None - break - - if node.type == token_labels.NAME and node.name: - #in case of type=name, use the name instead - subp.append(node.name) - else: - subp.append(node.type) - - node = node.parent - return subp - - def get_linear_subpattern(self): - """Drives the leaf_to_root method. The reason that - leaf_to_root must be run multiple times is because we need to - reject 'group' matches; for example the alternative form - (a | b c) creates a group [b c] that needs to be matched. Since - matching multiple linear patterns overcomes the automaton's - capabilities, leaf_to_root merges each group into a single - choice based on 'characteristic'ity, - - i.e. (a|b c) -> (a|b) if b more characteristic than c - - Returns: The most 'characteristic'(as defined by - get_characteristic_subpattern) path for the compiled pattern - tree. - """ - - for l in self.leaves(): - subp = l.leaf_to_root() - if subp: - return subp - - def leaves(self): - "Generator that returns the leaves of the tree" - for child in self.children: - yield from child.leaves() - if not self.children: - yield self - -def reduce_tree(node, parent=None): - """ - Internal function. Reduces a compiled pattern tree to an - intermediate representation suitable for feeding the - automaton. This also trims off any optional pattern elements(like - [a], a*). - """ - - new_node = None - #switch on the node type - if node.type == syms.Matcher: - #skip - node = node.children[0] - - if node.type == syms.Alternatives : - #2 cases - if len(node.children) <= 2: - #just a single 'Alternative', skip this node - new_node = reduce_tree(node.children[0], parent) - else: - #real alternatives - new_node = MinNode(type=TYPE_ALTERNATIVES) - #skip odd children('|' tokens) - for child in node.children: - if node.children.index(child)%2: - continue - reduced = reduce_tree(child, new_node) - if reduced is not None: - new_node.children.append(reduced) - elif node.type == syms.Alternative: - if len(node.children) > 1: - - new_node = MinNode(type=TYPE_GROUP) - for child in node.children: - reduced = reduce_tree(child, new_node) - if reduced: - new_node.children.append(reduced) - if not new_node.children: - # delete the group if all of the children were reduced to None - new_node = None - - else: - new_node = reduce_tree(node.children[0], parent) - - elif node.type == syms.Unit: - if (isinstance(node.children[0], pytree.Leaf) and - node.children[0].value == '('): - #skip parentheses - return reduce_tree(node.children[1], parent) - if ((isinstance(node.children[0], pytree.Leaf) and - node.children[0].value == '[') - or - (len(node.children)>1 and - hasattr(node.children[1], "value") and - node.children[1].value == '[')): - #skip whole unit if its optional - return None - - leaf = True - details_node = None - alternatives_node = None - has_repeater = False - repeater_node = None - has_variable_name = False - - for child in node.children: - if child.type == syms.Details: - leaf = False - details_node = child - elif child.type == syms.Repeater: - has_repeater = True - repeater_node = child - elif child.type == syms.Alternatives: - alternatives_node = child - if hasattr(child, 'value') and child.value == '=': # variable name - has_variable_name = True - - #skip variable name - if has_variable_name: - #skip variable name, '=' - name_leaf = node.children[2] - if hasattr(name_leaf, 'value') and name_leaf.value == '(': - # skip parenthesis - name_leaf = node.children[3] - else: - name_leaf = node.children[0] - - #set node type - if name_leaf.type == token_labels.NAME: - #(python) non-name or wildcard - if name_leaf.value == 'any': - new_node = MinNode(type=TYPE_ANY) - else: - if hasattr(token_labels, name_leaf.value): - new_node = MinNode(type=getattr(token_labels, name_leaf.value)) - else: - new_node = MinNode(type=getattr(pysyms, name_leaf.value)) - - elif name_leaf.type == token_labels.STRING: - #(python) name or character; remove the apostrophes from - #the string value - name = name_leaf.value.strip("'") - if name in tokens: - new_node = MinNode(type=tokens[name]) - else: - new_node = MinNode(type=token_labels.NAME, name=name) - elif name_leaf.type == syms.Alternatives: - new_node = reduce_tree(alternatives_node, parent) - - #handle repeaters - if has_repeater: - if repeater_node.children[0].value == '*': - #reduce to None - new_node = None - elif repeater_node.children[0].value == '+': - #reduce to a single occurrence i.e. do nothing - pass - else: - #TODO: handle {min, max} repeaters - raise NotImplementedError - - #add children - if details_node and new_node is not None: - for child in details_node.children[1:-1]: - #skip '<', '>' markers - reduced = reduce_tree(child, new_node) - if reduced is not None: - new_node.children.append(reduced) - if new_node: - new_node.parent = parent - return new_node - - -def get_characteristic_subpattern(subpatterns): - """Picks the most characteristic from a list of linear patterns - Current order used is: - names > common_names > common_chars - """ - if not isinstance(subpatterns, list): - return subpatterns - if len(subpatterns)==1: - return subpatterns[0] - - # first pick out the ones containing variable names - subpatterns_with_names = [] - subpatterns_with_common_names = [] - common_names = ['in', 'for', 'if' , 'not', 'None'] - subpatterns_with_common_chars = [] - common_chars = "[]().,:" - for subpattern in subpatterns: - if any(rec_test(subpattern, lambda x: type(x) is str)): - if any(rec_test(subpattern, - lambda x: isinstance(x, str) and x in common_chars)): - subpatterns_with_common_chars.append(subpattern) - elif any(rec_test(subpattern, - lambda x: isinstance(x, str) and x in common_names)): - subpatterns_with_common_names.append(subpattern) - - else: - subpatterns_with_names.append(subpattern) - - if subpatterns_with_names: - subpatterns = subpatterns_with_names - elif subpatterns_with_common_names: - subpatterns = subpatterns_with_common_names - elif subpatterns_with_common_chars: - subpatterns = subpatterns_with_common_chars - # of the remaining subpatterns pick out the longest one - return max(subpatterns, key=len) - -def rec_test(sequence, test_func): - """Tests test_func on all items of sequence and items of included - sub-iterables""" - for x in sequence: - if isinstance(x, (list, tuple)): - yield from rec_test(x, test_func) - else: - yield test_func(x) diff --git a/Lib/lib2to3/fixer_base.py b/Lib/lib2to3/fixer_base.py deleted file mode 100644 index df581a4deab9e9..00000000000000 --- a/Lib/lib2to3/fixer_base.py +++ /dev/null @@ -1,186 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Base class for fixers (optional, but recommended).""" - -# Python imports -import itertools - -# Local imports -from .patcomp import PatternCompiler -from . import pygram -from .fixer_util import does_tree_import - -class BaseFix(object): - - """Optional base class for fixers. - - The subclass name must be FixFooBar where FooBar is the result of - removing underscores and capitalizing the words of the fix name. - For example, the class name for a fixer named 'has_key' should be - FixHasKey. - """ - - PATTERN = None # Most subclasses should override with a string literal - pattern = None # Compiled pattern, set by compile_pattern() - pattern_tree = None # Tree representation of the pattern - options = None # Options object passed to initializer - filename = None # The filename (set by set_filename) - numbers = itertools.count(1) # For new_name() - used_names = set() # A set of all used NAMEs - order = "post" # Does the fixer prefer pre- or post-order traversal - explicit = False # Is this ignored by refactor.py -f all? - run_order = 5 # Fixers will be sorted by run order before execution - # Lower numbers will be run first. - _accept_type = None # [Advanced and not public] This tells RefactoringTool - # which node type to accept when there's not a pattern. - - keep_line_order = False # For the bottom matcher: match with the - # original line order - BM_compatible = False # Compatibility with the bottom matching - # module; every fixer should set this - # manually - - # Shortcut for access to Python grammar symbols - syms = pygram.python_symbols - - def __init__(self, options, log): - """Initializer. Subclass may override. - - Args: - options: a dict containing the options passed to RefactoringTool - that could be used to customize the fixer through the command line. - log: a list to append warnings and other messages to. - """ - self.options = options - self.log = log - self.compile_pattern() - - def compile_pattern(self): - """Compiles self.PATTERN into self.pattern. - - Subclass may override if it doesn't want to use - self.{pattern,PATTERN} in .match(). - """ - if self.PATTERN is not None: - PC = PatternCompiler() - self.pattern, self.pattern_tree = PC.compile_pattern(self.PATTERN, - with_tree=True) - - def set_filename(self, filename): - """Set the filename. - - The main refactoring tool should call this. - """ - self.filename = filename - - def match(self, node): - """Returns match for a given parse tree node. - - Should return a true or false object (not necessarily a bool). - It may return a non-empty dict of matching sub-nodes as - returned by a matching pattern. - - Subclass may override. - """ - results = {"node": node} - return self.pattern.match(node, results) and results - - def transform(self, node, results): - """Returns the transformation for a given parse tree node. - - Args: - node: the root of the parse tree that matched the fixer. - results: a dict mapping symbolic names to part of the match. - - Returns: - None, or a node that is a modified copy of the - argument node. The node argument may also be modified in-place to - effect the same change. - - Subclass *must* override. - """ - raise NotImplementedError() - - def new_name(self, template="xxx_todo_changeme"): - """Return a string suitable for use as an identifier - - The new name is guaranteed not to conflict with other identifiers. - """ - name = template - while name in self.used_names: - name = template + str(next(self.numbers)) - self.used_names.add(name) - return name - - def log_message(self, message): - if self.first_log: - self.first_log = False - self.log.append("### In file %s ###" % self.filename) - self.log.append(message) - - def cannot_convert(self, node, reason=None): - """Warn the user that a given chunk of code is not valid Python 3, - but that it cannot be converted automatically. - - First argument is the top-level node for the code in question. - Optional second argument is why it can't be converted. - """ - lineno = node.get_lineno() - for_output = node.clone() - for_output.prefix = "" - msg = "Line %d: could not convert: %s" - self.log_message(msg % (lineno, for_output)) - if reason: - self.log_message(reason) - - def warning(self, node, reason): - """Used for warning the user about possible uncertainty in the - translation. - - First argument is the top-level node for the code in question. - Optional second argument is why it can't be converted. - """ - lineno = node.get_lineno() - self.log_message("Line %d: %s" % (lineno, reason)) - - def start_tree(self, tree, filename): - """Some fixers need to maintain tree-wide state. - This method is called once, at the start of tree fix-up. - - tree - the root node of the tree to be processed. - filename - the name of the file the tree came from. - """ - self.used_names = tree.used_names - self.set_filename(filename) - self.numbers = itertools.count(1) - self.first_log = True - - def finish_tree(self, tree, filename): - """Some fixers need to maintain tree-wide state. - This method is called once, at the conclusion of tree fix-up. - - tree - the root node of the tree to be processed. - filename - the name of the file the tree came from. - """ - pass - - -class ConditionalFix(BaseFix): - """ Base class for fixers which not execute if an import is found. """ - - # This is the name of the import which, if found, will cause the test to be skipped - skip_on = None - - def start_tree(self, *args): - super(ConditionalFix, self).start_tree(*args) - self._should_skip = None - - def should_skip(self, node): - if self._should_skip is not None: - return self._should_skip - pkg = self.skip_on.split(".") - name = pkg[-1] - pkg = ".".join(pkg[:-1]) - self._should_skip = does_tree_import(pkg, name, node) - return self._should_skip diff --git a/Lib/lib2to3/fixer_util.py b/Lib/lib2to3/fixer_util.py deleted file mode 100644 index c2a3a47f503286..00000000000000 --- a/Lib/lib2to3/fixer_util.py +++ /dev/null @@ -1,453 +0,0 @@ -"""Utility functions, node construction macros, etc.""" -# Author: Collin Winter - -# Local imports -from .pgen2 import token -from .pytree import Leaf, Node -from .pygram import python_symbols as syms -from . import patcomp - - -########################################################### -### Common node-construction "macros" -########################################################### - -def KeywordArg(keyword, value): - return Node(syms.argument, - [keyword, Leaf(token.EQUAL, "="), value]) - -def LParen(): - return Leaf(token.LPAR, "(") - -def RParen(): - return Leaf(token.RPAR, ")") - -def Assign(target, source): - """Build an assignment statement""" - if not isinstance(target, list): - target = [target] - if not isinstance(source, list): - source.prefix = " " - source = [source] - - return Node(syms.atom, - target + [Leaf(token.EQUAL, "=", prefix=" ")] + source) - -def Name(name, prefix=None): - """Return a NAME leaf""" - return Leaf(token.NAME, name, prefix=prefix) - -def Attr(obj, attr): - """A node tuple for obj.attr""" - return [obj, Node(syms.trailer, [Dot(), attr])] - -def Comma(): - """A comma leaf""" - return Leaf(token.COMMA, ",") - -def Dot(): - """A period (.) leaf""" - return Leaf(token.DOT, ".") - -def ArgList(args, lparen=LParen(), rparen=RParen()): - """A parenthesised argument list, used by Call()""" - node = Node(syms.trailer, [lparen.clone(), rparen.clone()]) - if args: - node.insert_child(1, Node(syms.arglist, args)) - return node - -def Call(func_name, args=None, prefix=None): - """A function call""" - node = Node(syms.power, [func_name, ArgList(args)]) - if prefix is not None: - node.prefix = prefix - return node - -def Newline(): - """A newline literal""" - return Leaf(token.NEWLINE, "\n") - -def BlankLine(): - """A blank line""" - return Leaf(token.NEWLINE, "") - -def Number(n, prefix=None): - return Leaf(token.NUMBER, n, prefix=prefix) - -def Subscript(index_node): - """A numeric or string subscript""" - return Node(syms.trailer, [Leaf(token.LBRACE, "["), - index_node, - Leaf(token.RBRACE, "]")]) - -def String(string, prefix=None): - """A string leaf""" - return Leaf(token.STRING, string, prefix=prefix) - -def ListComp(xp, fp, it, test=None): - """A list comprehension of the form [xp for fp in it if test]. - - If test is None, the "if test" part is omitted. - """ - xp.prefix = "" - fp.prefix = " " - it.prefix = " " - for_leaf = Leaf(token.NAME, "for") - for_leaf.prefix = " " - in_leaf = Leaf(token.NAME, "in") - in_leaf.prefix = " " - inner_args = [for_leaf, fp, in_leaf, it] - if test: - test.prefix = " " - if_leaf = Leaf(token.NAME, "if") - if_leaf.prefix = " " - inner_args.append(Node(syms.comp_if, [if_leaf, test])) - inner = Node(syms.listmaker, [xp, Node(syms.comp_for, inner_args)]) - return Node(syms.atom, - [Leaf(token.LBRACE, "["), - inner, - Leaf(token.RBRACE, "]")]) - -def FromImport(package_name, name_leafs): - """ Return an import statement in the form: - from package import name_leafs""" - # XXX: May not handle dotted imports properly (eg, package_name='foo.bar') - #assert package_name == '.' or '.' not in package_name, "FromImport has "\ - # "not been tested with dotted package names -- use at your own "\ - # "peril!" - - for leaf in name_leafs: - # Pull the leaves out of their old tree - leaf.remove() - - children = [Leaf(token.NAME, "from"), - Leaf(token.NAME, package_name, prefix=" "), - Leaf(token.NAME, "import", prefix=" "), - Node(syms.import_as_names, name_leafs)] - imp = Node(syms.import_from, children) - return imp - -def ImportAndCall(node, results, names): - """Returns an import statement and calls a method - of the module: - - import module - module.name()""" - obj = results["obj"].clone() - if obj.type == syms.arglist: - newarglist = obj.clone() - else: - newarglist = Node(syms.arglist, [obj.clone()]) - after = results["after"] - if after: - after = [n.clone() for n in after] - new = Node(syms.power, - Attr(Name(names[0]), Name(names[1])) + - [Node(syms.trailer, - [results["lpar"].clone(), - newarglist, - results["rpar"].clone()])] + after) - new.prefix = node.prefix - return new - - -########################################################### -### Determine whether a node represents a given literal -########################################################### - -def is_tuple(node): - """Does the node represent a tuple literal?""" - if isinstance(node, Node) and node.children == [LParen(), RParen()]: - return True - return (isinstance(node, Node) - and len(node.children) == 3 - and isinstance(node.children[0], Leaf) - and isinstance(node.children[1], Node) - and isinstance(node.children[2], Leaf) - and node.children[0].value == "(" - and node.children[2].value == ")") - -def is_list(node): - """Does the node represent a list literal?""" - return (isinstance(node, Node) - and len(node.children) > 1 - and isinstance(node.children[0], Leaf) - and isinstance(node.children[-1], Leaf) - and node.children[0].value == "[" - and node.children[-1].value == "]") - - -########################################################### -### Misc -########################################################### - -def parenthesize(node): - return Node(syms.atom, [LParen(), node, RParen()]) - - -consuming_calls = {"sorted", "list", "set", "any", "all", "tuple", "sum", - "min", "max", "enumerate"} - -def attr_chain(obj, attr): - """Follow an attribute chain. - - If you have a chain of objects where a.foo -> b, b.foo-> c, etc, - use this to iterate over all objects in the chain. Iteration is - terminated by getattr(x, attr) is None. - - Args: - obj: the starting object - attr: the name of the chaining attribute - - Yields: - Each successive object in the chain. - """ - next = getattr(obj, attr) - while next: - yield next - next = getattr(next, attr) - -p0 = """for_stmt< 'for' any 'in' node=any ':' any* > - | comp_for< 'for' any 'in' node=any any* > - """ -p1 = """ -power< - ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' | - 'any' | 'all' | 'enumerate' | (any* trailer< '.' 'join' >) ) - trailer< '(' node=any ')' > - any* -> -""" -p2 = """ -power< - ( 'sorted' | 'enumerate' ) - trailer< '(' arglist ')' > - any* -> -""" -pats_built = False -def in_special_context(node): - """ Returns true if node is in an environment where all that is required - of it is being iterable (ie, it doesn't matter if it returns a list - or an iterator). - See test_map_nochange in test_fixers.py for some examples and tests. - """ - global p0, p1, p2, pats_built - if not pats_built: - p0 = patcomp.compile_pattern(p0) - p1 = patcomp.compile_pattern(p1) - p2 = patcomp.compile_pattern(p2) - pats_built = True - patterns = [p0, p1, p2] - for pattern, parent in zip(patterns, attr_chain(node, "parent")): - results = {} - if pattern.match(parent, results) and results["node"] is node: - return True - return False - -def is_probably_builtin(node): - """ - Check that something isn't an attribute or function name etc. - """ - prev = node.prev_sibling - if prev is not None and prev.type == token.DOT: - # Attribute lookup. - return False - parent = node.parent - if parent.type in (syms.funcdef, syms.classdef): - return False - if parent.type == syms.expr_stmt and parent.children[0] is node: - # Assignment. - return False - if parent.type == syms.parameters or \ - (parent.type == syms.typedargslist and ( - (prev is not None and prev.type == token.COMMA) or - parent.children[0] is node - )): - # The name of an argument. - return False - return True - -def find_indentation(node): - """Find the indentation of *node*.""" - while node is not None: - if node.type == syms.suite and len(node.children) > 2: - indent = node.children[1] - if indent.type == token.INDENT: - return indent.value - node = node.parent - return "" - -########################################################### -### The following functions are to find bindings in a suite -########################################################### - -def make_suite(node): - if node.type == syms.suite: - return node - node = node.clone() - parent, node.parent = node.parent, None - suite = Node(syms.suite, [node]) - suite.parent = parent - return suite - -def find_root(node): - """Find the top level namespace.""" - # Scamper up to the top level namespace - while node.type != syms.file_input: - node = node.parent - if not node: - raise ValueError("root found before file_input node was found.") - return node - -def does_tree_import(package, name, node): - """ Returns true if name is imported from package at the - top level of the tree which node belongs to. - To cover the case of an import like 'import foo', use - None for the package and 'foo' for the name. """ - binding = find_binding(name, find_root(node), package) - return bool(binding) - -def is_import(node): - """Returns true if the node is an import statement.""" - return node.type in (syms.import_name, syms.import_from) - -def touch_import(package, name, node): - """ Works like `does_tree_import` but adds an import statement - if it was not imported. """ - def is_import_stmt(node): - return (node.type == syms.simple_stmt and node.children and - is_import(node.children[0])) - - root = find_root(node) - - if does_tree_import(package, name, root): - return - - # figure out where to insert the new import. First try to find - # the first import and then skip to the last one. - insert_pos = offset = 0 - for idx, node in enumerate(root.children): - if not is_import_stmt(node): - continue - for offset, node2 in enumerate(root.children[idx:]): - if not is_import_stmt(node2): - break - insert_pos = idx + offset - break - - # if there are no imports where we can insert, find the docstring. - # if that also fails, we stick to the beginning of the file - if insert_pos == 0: - for idx, node in enumerate(root.children): - if (node.type == syms.simple_stmt and node.children and - node.children[0].type == token.STRING): - insert_pos = idx + 1 - break - - if package is None: - import_ = Node(syms.import_name, [ - Leaf(token.NAME, "import"), - Leaf(token.NAME, name, prefix=" ") - ]) - else: - import_ = FromImport(package, [Leaf(token.NAME, name, prefix=" ")]) - - children = [import_, Newline()] - root.insert_child(insert_pos, Node(syms.simple_stmt, children)) - - -_def_syms = {syms.classdef, syms.funcdef} -def find_binding(name, node, package=None): - """ Returns the node which binds variable name, otherwise None. - If optional argument package is supplied, only imports will - be returned. - See test cases for examples.""" - for child in node.children: - ret = None - if child.type == syms.for_stmt: - if _find(name, child.children[1]): - return child - n = find_binding(name, make_suite(child.children[-1]), package) - if n: ret = n - elif child.type in (syms.if_stmt, syms.while_stmt): - n = find_binding(name, make_suite(child.children[-1]), package) - if n: ret = n - elif child.type == syms.try_stmt: - n = find_binding(name, make_suite(child.children[2]), package) - if n: - ret = n - else: - for i, kid in enumerate(child.children[3:]): - if kid.type == token.COLON and kid.value == ":": - # i+3 is the colon, i+4 is the suite - n = find_binding(name, make_suite(child.children[i+4]), package) - if n: ret = n - elif child.type in _def_syms and child.children[1].value == name: - ret = child - elif _is_import_binding(child, name, package): - ret = child - elif child.type == syms.simple_stmt: - ret = find_binding(name, child, package) - elif child.type == syms.expr_stmt: - if _find(name, child.children[0]): - ret = child - - if ret: - if not package: - return ret - if is_import(ret): - return ret - return None - -_block_syms = {syms.funcdef, syms.classdef, syms.trailer} -def _find(name, node): - nodes = [node] - while nodes: - node = nodes.pop() - if node.type > 256 and node.type not in _block_syms: - nodes.extend(node.children) - elif node.type == token.NAME and node.value == name: - return node - return None - -def _is_import_binding(node, name, package=None): - """ Will return node if node will import name, or node - will import * from package. None is returned otherwise. - See test cases for examples. """ - - if node.type == syms.import_name and not package: - imp = node.children[1] - if imp.type == syms.dotted_as_names: - for child in imp.children: - if child.type == syms.dotted_as_name: - if child.children[2].value == name: - return node - elif child.type == token.NAME and child.value == name: - return node - elif imp.type == syms.dotted_as_name: - last = imp.children[-1] - if last.type == token.NAME and last.value == name: - return node - elif imp.type == token.NAME and imp.value == name: - return node - elif node.type == syms.import_from: - # str(...) is used to make life easier here, because - # from a.b import parses to ['import', ['a', '.', 'b'], ...] - if package and str(node.children[1]).strip() != package: - return None - n = node.children[3] - if package and _find("as", n): - # See test_from_import_as for explanation - return None - elif n.type == syms.import_as_names and _find(name, n): - return node - elif n.type == syms.import_as_name: - child = n.children[2] - if child.type == token.NAME and child.value == name: - return node - elif n.type == token.NAME and n.value == name: - return node - elif package and n.type == token.STAR: - return node - return None diff --git a/Lib/lib2to3/fixes/__init__.py b/Lib/lib2to3/fixes/__init__.py deleted file mode 100644 index b93054b3ecf3a5..00000000000000 --- a/Lib/lib2to3/fixes/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Dummy file to make this directory a package. diff --git a/Lib/lib2to3/fixes/fix_apply.py b/Lib/lib2to3/fixes/fix_apply.py deleted file mode 100644 index 6408582c426477..00000000000000 --- a/Lib/lib2to3/fixes/fix_apply.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for apply(). - -This converts apply(func, v, k) into (func)(*v, **k).""" - -# Local imports -from .. import pytree -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Call, Comma, parenthesize - -class FixApply(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - power< 'apply' - trailer< - '(' - arglist< - (not argument - ')' - > - > - """ - - def transform(self, node, results): - syms = self.syms - assert results - func = results["func"] - args = results["args"] - kwds = results.get("kwds") - # I feel like we should be able to express this logic in the - # PATTERN above but I don't know how to do it so... - if args: - if (args.type == self.syms.argument and - args.children[0].value in {'**', '*'}): - return # Make no change. - if kwds and (kwds.type == self.syms.argument and - kwds.children[0].value == '**'): - return # Make no change. - prefix = node.prefix - func = func.clone() - if (func.type not in (token.NAME, syms.atom) and - (func.type != syms.power or - func.children[-2].type == token.DOUBLESTAR)): - # Need to parenthesize - func = parenthesize(func) - func.prefix = "" - args = args.clone() - args.prefix = "" - if kwds is not None: - kwds = kwds.clone() - kwds.prefix = "" - l_newargs = [pytree.Leaf(token.STAR, "*"), args] - if kwds is not None: - l_newargs.extend([Comma(), - pytree.Leaf(token.DOUBLESTAR, "**"), - kwds]) - l_newargs[-2].prefix = " " # that's the ** token - # XXX Sometimes we could be cleverer, e.g. apply(f, (x, y) + t) - # can be translated into f(x, y, *t) instead of f(*(x, y) + t) - #new = pytree.Node(syms.power, (func, ArgList(l_newargs))) - return Call(func, l_newargs, prefix=prefix) diff --git a/Lib/lib2to3/fixes/fix_asserts.py b/Lib/lib2to3/fixes/fix_asserts.py deleted file mode 100644 index 5bcec885f52cbf..00000000000000 --- a/Lib/lib2to3/fixes/fix_asserts.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Fixer that replaces deprecated unittest method names.""" - -# Author: Ezio Melotti - -from ..fixer_base import BaseFix -from ..fixer_util import Name - -NAMES = dict( - assert_="assertTrue", - assertEquals="assertEqual", - assertNotEquals="assertNotEqual", - assertAlmostEquals="assertAlmostEqual", - assertNotAlmostEquals="assertNotAlmostEqual", - assertRegexpMatches="assertRegex", - assertRaisesRegexp="assertRaisesRegex", - failUnlessEqual="assertEqual", - failIfEqual="assertNotEqual", - failUnlessAlmostEqual="assertAlmostEqual", - failIfAlmostEqual="assertNotAlmostEqual", - failUnless="assertTrue", - failUnlessRaises="assertRaises", - failIf="assertFalse", -) - - -class FixAsserts(BaseFix): - - PATTERN = """ - power< any+ trailer< '.' meth=(%s)> any* > - """ % '|'.join(map(repr, NAMES)) - - def transform(self, node, results): - name = results["meth"][0] - name.replace(Name(NAMES[str(name)], prefix=name.prefix)) diff --git a/Lib/lib2to3/fixes/fix_basestring.py b/Lib/lib2to3/fixes/fix_basestring.py deleted file mode 100644 index 5fe69a0f03b1b8..00000000000000 --- a/Lib/lib2to3/fixes/fix_basestring.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Fixer for basestring -> str.""" -# Author: Christian Heimes - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - -class FixBasestring(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = "'basestring'" - - def transform(self, node, results): - return Name("str", prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_buffer.py b/Lib/lib2to3/fixes/fix_buffer.py deleted file mode 100644 index f9a1958ad3b93e..00000000000000 --- a/Lib/lib2to3/fixes/fix_buffer.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that changes buffer(...) into memoryview(...).""" - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - - -class FixBuffer(fixer_base.BaseFix): - BM_compatible = True - - explicit = True # The user must ask for this fixer - - PATTERN = """ - power< name='buffer' trailer< '(' [any] ')' > any* > - """ - - def transform(self, node, results): - name = results["name"] - name.replace(Name("memoryview", prefix=name.prefix)) diff --git a/Lib/lib2to3/fixes/fix_dict.py b/Lib/lib2to3/fixes/fix_dict.py deleted file mode 100644 index d3655c9f1b2d9b..00000000000000 --- a/Lib/lib2to3/fixes/fix_dict.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for dict methods. - -d.keys() -> list(d.keys()) -d.items() -> list(d.items()) -d.values() -> list(d.values()) - -d.iterkeys() -> iter(d.keys()) -d.iteritems() -> iter(d.items()) -d.itervalues() -> iter(d.values()) - -d.viewkeys() -> d.keys() -d.viewitems() -> d.items() -d.viewvalues() -> d.values() - -Except in certain very specific contexts: the iter() can be dropped -when the context is list(), sorted(), iter() or for...in; the list() -can be dropped when the context is list() or sorted() (but not iter() -or for...in!). Special contexts that apply to both: list(), sorted(), tuple() -set(), any(), all(), sum(). - -Note: iter(d.keys()) could be written as iter(d) but since the -original d.iterkeys() was also redundant we don't fix this. And there -are (rare) contexts where it makes a difference (e.g. when passing it -as an argument to a function that introspects the argument). -""" - -# Local imports -from .. import pytree -from .. import patcomp -from .. import fixer_base -from ..fixer_util import Name, Call, Dot -from .. import fixer_util - - -iter_exempt = fixer_util.consuming_calls | {"iter"} - - -class FixDict(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - power< head=any+ - trailer< '.' method=('keys'|'items'|'values'| - 'iterkeys'|'iteritems'|'itervalues'| - 'viewkeys'|'viewitems'|'viewvalues') > - parens=trailer< '(' ')' > - tail=any* - > - """ - - def transform(self, node, results): - head = results["head"] - method = results["method"][0] # Extract node for method name - tail = results["tail"] - syms = self.syms - method_name = method.value - isiter = method_name.startswith("iter") - isview = method_name.startswith("view") - if isiter or isview: - method_name = method_name[4:] - assert method_name in ("keys", "items", "values"), repr(method) - head = [n.clone() for n in head] - tail = [n.clone() for n in tail] - special = not tail and self.in_special_context(node, isiter) - args = head + [pytree.Node(syms.trailer, - [Dot(), - Name(method_name, - prefix=method.prefix)]), - results["parens"].clone()] - new = pytree.Node(syms.power, args) - if not (special or isview): - new.prefix = "" - new = Call(Name("iter" if isiter else "list"), [new]) - if tail: - new = pytree.Node(syms.power, [new] + tail) - new.prefix = node.prefix - return new - - P1 = "power< func=NAME trailer< '(' node=any ')' > any* >" - p1 = patcomp.compile_pattern(P1) - - P2 = """for_stmt< 'for' any 'in' node=any ':' any* > - | comp_for< 'for' any 'in' node=any any* > - """ - p2 = patcomp.compile_pattern(P2) - - def in_special_context(self, node, isiter): - if node.parent is None: - return False - results = {} - if (node.parent.parent is not None and - self.p1.match(node.parent.parent, results) and - results["node"] is node): - if isiter: - # iter(d.iterkeys()) -> iter(d.keys()), etc. - return results["func"].value in iter_exempt - else: - # list(d.keys()) -> list(d.keys()), etc. - return results["func"].value in fixer_util.consuming_calls - if not isiter: - return False - # for ... in d.iterkeys() -> for ... in d.keys(), etc. - return self.p2.match(node.parent, results) and results["node"] is node diff --git a/Lib/lib2to3/fixes/fix_except.py b/Lib/lib2to3/fixes/fix_except.py deleted file mode 100644 index 49bd3d5ab7d6cc..00000000000000 --- a/Lib/lib2to3/fixes/fix_except.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Fixer for except statements with named exceptions. - -The following cases will be converted: - -- "except E, T:" where T is a name: - - except E as T: - -- "except E, T:" where T is not a name, tuple or list: - - except E as t: - T = t - - This is done because the target of an "except" clause must be a - name. - -- "except E, T:" where T is a tuple or list literal: - - except E as t: - T = t.args -""" -# Author: Collin Winter - -# Local imports -from .. import pytree -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Assign, Attr, Name, is_tuple, is_list, syms - -def find_excepts(nodes): - for i, n in enumerate(nodes): - if n.type == syms.except_clause: - if n.children[0].value == 'except': - yield (n, nodes[i+2]) - -class FixExcept(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - try_stmt< 'try' ':' (simple_stmt | suite) - cleanup=(except_clause ':' (simple_stmt | suite))+ - tail=(['except' ':' (simple_stmt | suite)] - ['else' ':' (simple_stmt | suite)] - ['finally' ':' (simple_stmt | suite)]) > - """ - - def transform(self, node, results): - syms = self.syms - - tail = [n.clone() for n in results["tail"]] - - try_cleanup = [ch.clone() for ch in results["cleanup"]] - for except_clause, e_suite in find_excepts(try_cleanup): - if len(except_clause.children) == 4: - (E, comma, N) = except_clause.children[1:4] - comma.replace(Name("as", prefix=" ")) - - if N.type != token.NAME: - # Generate a new N for the except clause - new_N = Name(self.new_name(), prefix=" ") - target = N.clone() - target.prefix = "" - N.replace(new_N) - new_N = new_N.clone() - - # Insert "old_N = new_N" as the first statement in - # the except body. This loop skips leading whitespace - # and indents - #TODO(cwinter) suite-cleanup - suite_stmts = e_suite.children - for i, stmt in enumerate(suite_stmts): - if isinstance(stmt, pytree.Node): - break - - # The assignment is different if old_N is a tuple or list - # In that case, the assignment is old_N = new_N.args - if is_tuple(N) or is_list(N): - assign = Assign(target, Attr(new_N, Name('args'))) - else: - assign = Assign(target, new_N) - - #TODO(cwinter) stopgap until children becomes a smart list - for child in reversed(suite_stmts[:i]): - e_suite.insert_child(0, child) - e_suite.insert_child(i, assign) - elif N.prefix == "": - # No space after a comma is legal; no space after "as", - # not so much. - N.prefix = " " - - #TODO(cwinter) fix this when children becomes a smart list - children = [c.clone() for c in node.children[:3]] + try_cleanup + tail - return pytree.Node(node.type, children) diff --git a/Lib/lib2to3/fixes/fix_exec.py b/Lib/lib2to3/fixes/fix_exec.py deleted file mode 100644 index ab921ee80cdf36..00000000000000 --- a/Lib/lib2to3/fixes/fix_exec.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for exec. - -This converts usages of the exec statement into calls to a built-in -exec() function. - -exec code in ns1, ns2 -> exec(code, ns1, ns2) -""" - -# Local imports -from .. import fixer_base -from ..fixer_util import Comma, Name, Call - - -class FixExec(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - exec_stmt< 'exec' a=any 'in' b=any [',' c=any] > - | - exec_stmt< 'exec' (not atom<'(' [any] ')'>) a=any > - """ - - def transform(self, node, results): - assert results - syms = self.syms - a = results["a"] - b = results.get("b") - c = results.get("c") - args = [a.clone()] - args[0].prefix = "" - if b is not None: - args.extend([Comma(), b.clone()]) - if c is not None: - args.extend([Comma(), c.clone()]) - - return Call(Name("exec"), args, prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_execfile.py b/Lib/lib2to3/fixes/fix_execfile.py deleted file mode 100644 index b6c786fd4e8b6a..00000000000000 --- a/Lib/lib2to3/fixes/fix_execfile.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for execfile. - -This converts usages of the execfile function into calls to the built-in -exec() function. -""" - -from .. import fixer_base -from ..fixer_util import (Comma, Name, Call, LParen, RParen, Dot, Node, - ArgList, String, syms) - - -class FixExecfile(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - power< 'execfile' trailer< '(' arglist< filename=any [',' globals=any [',' locals=any ] ] > ')' > > - | - power< 'execfile' trailer< '(' filename=any ')' > > - """ - - def transform(self, node, results): - assert results - filename = results["filename"] - globals = results.get("globals") - locals = results.get("locals") - - # Copy over the prefix from the right parentheses end of the execfile - # call. - execfile_paren = node.children[-1].children[-1].clone() - # Construct open().read(). - open_args = ArgList([filename.clone(), Comma(), String('"rb"', ' ')], - rparen=execfile_paren) - open_call = Node(syms.power, [Name("open"), open_args]) - read = [Node(syms.trailer, [Dot(), Name('read')]), - Node(syms.trailer, [LParen(), RParen()])] - open_expr = [open_call] + read - # Wrap the open call in a compile call. This is so the filename will be - # preserved in the execed code. - filename_arg = filename.clone() - filename_arg.prefix = " " - exec_str = String("'exec'", " ") - compile_args = open_expr + [Comma(), filename_arg, Comma(), exec_str] - compile_call = Call(Name("compile"), compile_args, "") - # Finally, replace the execfile call with an exec call. - args = [compile_call] - if globals is not None: - args.extend([Comma(), globals.clone()]) - if locals is not None: - args.extend([Comma(), locals.clone()]) - return Call(Name("exec"), args, prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_exitfunc.py b/Lib/lib2to3/fixes/fix_exitfunc.py deleted file mode 100644 index 2e47887afead36..00000000000000 --- a/Lib/lib2to3/fixes/fix_exitfunc.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -Convert use of sys.exitfunc to use the atexit module. -""" - -# Author: Benjamin Peterson - -from lib2to3 import pytree, fixer_base -from lib2to3.fixer_util import Name, Attr, Call, Comma, Newline, syms - - -class FixExitfunc(fixer_base.BaseFix): - keep_line_order = True - BM_compatible = True - - PATTERN = """ - ( - sys_import=import_name<'import' - ('sys' - | - dotted_as_names< (any ',')* 'sys' (',' any)* > - ) - > - | - expr_stmt< - power< 'sys' trailer< '.' 'exitfunc' > > - '=' func=any > - ) - """ - - def __init__(self, *args): - super(FixExitfunc, self).__init__(*args) - - def start_tree(self, tree, filename): - super(FixExitfunc, self).start_tree(tree, filename) - self.sys_import = None - - def transform(self, node, results): - # First, find the sys import. We'll just hope it's global scope. - if "sys_import" in results: - if self.sys_import is None: - self.sys_import = results["sys_import"] - return - - func = results["func"].clone() - func.prefix = "" - register = pytree.Node(syms.power, - Attr(Name("atexit"), Name("register")) - ) - call = Call(register, [func], node.prefix) - node.replace(call) - - if self.sys_import is None: - # That's interesting. - self.warning(node, "Can't find sys import; Please add an atexit " - "import at the top of your file.") - return - - # Now add an atexit import after the sys import. - names = self.sys_import.children[1] - if names.type == syms.dotted_as_names: - names.append_child(Comma()) - names.append_child(Name("atexit", " ")) - else: - containing_stmt = self.sys_import.parent - position = containing_stmt.children.index(self.sys_import) - stmt_container = containing_stmt.parent - new_import = pytree.Node(syms.import_name, - [Name("import"), Name("atexit", " ")] - ) - new = pytree.Node(syms.simple_stmt, [new_import]) - containing_stmt.insert_child(position + 1, Newline()) - containing_stmt.insert_child(position + 2, new) diff --git a/Lib/lib2to3/fixes/fix_filter.py b/Lib/lib2to3/fixes/fix_filter.py deleted file mode 100644 index 38e9078f11ac88..00000000000000 --- a/Lib/lib2to3/fixes/fix_filter.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that changes filter(F, X) into list(filter(F, X)). - -We avoid the transformation if the filter() call is directly contained -in iter(<>), list(<>), tuple(<>), sorted(<>), ...join(<>), or -for V in <>:. - -NOTE: This is still not correct if the original code was depending on -filter(F, X) to return a string if X is a string and a tuple if X is a -tuple. That would require type inference, which we don't do. Let -Python 2.6 figure it out. -""" - -# Local imports -from .. import fixer_base -from ..pytree import Node -from ..pygram import python_symbols as syms -from ..fixer_util import Name, ArgList, ListComp, in_special_context, parenthesize - - -class FixFilter(fixer_base.ConditionalFix): - BM_compatible = True - - PATTERN = """ - filter_lambda=power< - 'filter' - trailer< - '(' - arglist< - lambdef< 'lambda' - (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any - > - ',' - it=any - > - ')' - > - [extra_trailers=trailer*] - > - | - power< - 'filter' - trailer< '(' arglist< none='None' ',' seq=any > ')' > - [extra_trailers=trailer*] - > - | - power< - 'filter' - args=trailer< '(' [any] ')' > - [extra_trailers=trailer*] - > - """ - - skip_on = "future_builtins.filter" - - def transform(self, node, results): - if self.should_skip(node): - return - - trailers = [] - if 'extra_trailers' in results: - for t in results['extra_trailers']: - trailers.append(t.clone()) - - if "filter_lambda" in results: - xp = results.get("xp").clone() - if xp.type == syms.test: - xp.prefix = "" - xp = parenthesize(xp) - - new = ListComp(results.get("fp").clone(), - results.get("fp").clone(), - results.get("it").clone(), xp) - new = Node(syms.power, [new] + trailers, prefix="") - - elif "none" in results: - new = ListComp(Name("_f"), - Name("_f"), - results["seq"].clone(), - Name("_f")) - new = Node(syms.power, [new] + trailers, prefix="") - - else: - if in_special_context(node): - return None - - args = results['args'].clone() - new = Node(syms.power, [Name("filter"), args], prefix="") - new = Node(syms.power, [Name("list"), ArgList([new])] + trailers) - new.prefix = "" - new.prefix = node.prefix - return new diff --git a/Lib/lib2to3/fixes/fix_funcattrs.py b/Lib/lib2to3/fixes/fix_funcattrs.py deleted file mode 100644 index 67f3e18e061bdb..00000000000000 --- a/Lib/lib2to3/fixes/fix_funcattrs.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Fix function attribute names (f.func_x -> f.__x__).""" -# Author: Collin Winter - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - - -class FixFuncattrs(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - power< any+ trailer< '.' attr=('func_closure' | 'func_doc' | 'func_globals' - | 'func_name' | 'func_defaults' | 'func_code' - | 'func_dict') > any* > - """ - - def transform(self, node, results): - attr = results["attr"][0] - attr.replace(Name(("__%s__" % attr.value[5:]), - prefix=attr.prefix)) diff --git a/Lib/lib2to3/fixes/fix_future.py b/Lib/lib2to3/fixes/fix_future.py deleted file mode 100644 index fbcb86af079133..00000000000000 --- a/Lib/lib2to3/fixes/fix_future.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Remove __future__ imports - -from __future__ import foo is replaced with an empty line. -""" -# Author: Christian Heimes - -# Local imports -from .. import fixer_base -from ..fixer_util import BlankLine - -class FixFuture(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """import_from< 'from' module_name="__future__" 'import' any >""" - - # This should be run last -- some things check for the import - run_order = 10 - - def transform(self, node, results): - new = BlankLine() - new.prefix = node.prefix - return new diff --git a/Lib/lib2to3/fixes/fix_getcwdu.py b/Lib/lib2to3/fixes/fix_getcwdu.py deleted file mode 100644 index 087eaedcb26f9c..00000000000000 --- a/Lib/lib2to3/fixes/fix_getcwdu.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -Fixer that changes os.getcwdu() to os.getcwd(). -""" -# Author: Victor Stinner - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - -class FixGetcwdu(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - power< 'os' trailer< dot='.' name='getcwdu' > any* > - """ - - def transform(self, node, results): - name = results["name"] - name.replace(Name("getcwd", prefix=name.prefix)) diff --git a/Lib/lib2to3/fixes/fix_has_key.py b/Lib/lib2to3/fixes/fix_has_key.py deleted file mode 100644 index 439708c9923404..00000000000000 --- a/Lib/lib2to3/fixes/fix_has_key.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for has_key(). - -Calls to .has_key() methods are expressed in terms of the 'in' -operator: - - d.has_key(k) -> k in d - -CAVEATS: -1) While the primary target of this fixer is dict.has_key(), the - fixer will change any has_key() method call, regardless of its - class. - -2) Cases like this will not be converted: - - m = d.has_key - if m(k): - ... - - Only *calls* to has_key() are converted. While it is possible to - convert the above to something like - - m = d.__contains__ - if m(k): - ... - - this is currently not done. -""" - -# Local imports -from .. import pytree -from .. import fixer_base -from ..fixer_util import Name, parenthesize - - -class FixHasKey(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - anchor=power< - before=any+ - trailer< '.' 'has_key' > - trailer< - '(' - ( not(arglist | argument) arg=any ','> - ) - ')' - > - after=any* - > - | - negation=not_test< - 'not' - anchor=power< - before=any+ - trailer< '.' 'has_key' > - trailer< - '(' - ( not(arglist | argument) arg=any ','> - ) - ')' - > - > - > - """ - - def transform(self, node, results): - assert results - syms = self.syms - if (node.parent.type == syms.not_test and - self.pattern.match(node.parent)): - # Don't transform a node matching the first alternative of the - # pattern when its parent matches the second alternative - return None - negation = results.get("negation") - anchor = results["anchor"] - prefix = node.prefix - before = [n.clone() for n in results["before"]] - arg = results["arg"].clone() - after = results.get("after") - if after: - after = [n.clone() for n in after] - if arg.type in (syms.comparison, syms.not_test, syms.and_test, - syms.or_test, syms.test, syms.lambdef, syms.argument): - arg = parenthesize(arg) - if len(before) == 1: - before = before[0] - else: - before = pytree.Node(syms.power, before) - before.prefix = " " - n_op = Name("in", prefix=" ") - if negation: - n_not = Name("not", prefix=" ") - n_op = pytree.Node(syms.comp_op, (n_not, n_op)) - new = pytree.Node(syms.comparison, (arg, n_op, before)) - if after: - new = parenthesize(new) - new = pytree.Node(syms.power, (new,) + tuple(after)) - if node.parent.type in (syms.comparison, syms.expr, syms.xor_expr, - syms.and_expr, syms.shift_expr, - syms.arith_expr, syms.term, - syms.factor, syms.power): - new = parenthesize(new) - new.prefix = prefix - return new diff --git a/Lib/lib2to3/fixes/fix_idioms.py b/Lib/lib2to3/fixes/fix_idioms.py deleted file mode 100644 index 6905913d7cb79d..00000000000000 --- a/Lib/lib2to3/fixes/fix_idioms.py +++ /dev/null @@ -1,152 +0,0 @@ -"""Adjust some old Python 2 idioms to their modern counterparts. - -* Change some type comparisons to isinstance() calls: - type(x) == T -> isinstance(x, T) - type(x) is T -> isinstance(x, T) - type(x) != T -> not isinstance(x, T) - type(x) is not T -> not isinstance(x, T) - -* Change "while 1:" into "while True:". - -* Change both - - v = list(EXPR) - v.sort() - foo(v) - -and the more general - - v = EXPR - v.sort() - foo(v) - -into - - v = sorted(EXPR) - foo(v) -""" -# Author: Jacques Frechet, Collin Winter - -# Local imports -from .. import fixer_base -from ..fixer_util import Call, Comma, Name, Node, BlankLine, syms - -CMP = "(n='!=' | '==' | 'is' | n=comp_op< 'is' 'not' >)" -TYPE = "power< 'type' trailer< '(' x=any ')' > >" - -class FixIdioms(fixer_base.BaseFix): - explicit = True # The user must ask for this fixer - - PATTERN = r""" - isinstance=comparison< %s %s T=any > - | - isinstance=comparison< T=any %s %s > - | - while_stmt< 'while' while='1' ':' any+ > - | - sorted=any< - any* - simple_stmt< - expr_stmt< id1=any '=' - power< list='list' trailer< '(' (not arglist) any ')' > > - > - '\n' - > - sort= - simple_stmt< - power< id2=any - trailer< '.' 'sort' > trailer< '(' ')' > - > - '\n' - > - next=any* - > - | - sorted=any< - any* - simple_stmt< expr_stmt< id1=any '=' expr=any > '\n' > - sort= - simple_stmt< - power< id2=any - trailer< '.' 'sort' > trailer< '(' ')' > - > - '\n' - > - next=any* - > - """ % (TYPE, CMP, CMP, TYPE) - - def match(self, node): - r = super(FixIdioms, self).match(node) - # If we've matched one of the sort/sorted subpatterns above, we - # want to reject matches where the initial assignment and the - # subsequent .sort() call involve different identifiers. - if r and "sorted" in r: - if r["id1"] == r["id2"]: - return r - return None - return r - - def transform(self, node, results): - if "isinstance" in results: - return self.transform_isinstance(node, results) - elif "while" in results: - return self.transform_while(node, results) - elif "sorted" in results: - return self.transform_sort(node, results) - else: - raise RuntimeError("Invalid match") - - def transform_isinstance(self, node, results): - x = results["x"].clone() # The thing inside of type() - T = results["T"].clone() # The type being compared against - x.prefix = "" - T.prefix = " " - test = Call(Name("isinstance"), [x, Comma(), T]) - if "n" in results: - test.prefix = " " - test = Node(syms.not_test, [Name("not"), test]) - test.prefix = node.prefix - return test - - def transform_while(self, node, results): - one = results["while"] - one.replace(Name("True", prefix=one.prefix)) - - def transform_sort(self, node, results): - sort_stmt = results["sort"] - next_stmt = results["next"] - list_call = results.get("list") - simple_expr = results.get("expr") - - if list_call: - list_call.replace(Name("sorted", prefix=list_call.prefix)) - elif simple_expr: - new = simple_expr.clone() - new.prefix = "" - simple_expr.replace(Call(Name("sorted"), [new], - prefix=simple_expr.prefix)) - else: - raise RuntimeError("should not have reached here") - sort_stmt.remove() - - btwn = sort_stmt.prefix - # Keep any prefix lines between the sort_stmt and the list_call and - # shove them right after the sorted() call. - if "\n" in btwn: - if next_stmt: - # The new prefix should be everything from the sort_stmt's - # prefix up to the last newline, then the old prefix after a new - # line. - prefix_lines = (btwn.rpartition("\n")[0], next_stmt[0].prefix) - next_stmt[0].prefix = "\n".join(prefix_lines) - else: - assert list_call.parent - assert list_call.next_sibling is None - # Put a blank line after list_call and set its prefix. - end_line = BlankLine() - list_call.parent.append_child(end_line) - assert list_call.next_sibling is end_line - # The new prefix should be everything up to the first new line - # of sort_stmt's prefix. - end_line.prefix = btwn.rpartition("\n")[0] diff --git a/Lib/lib2to3/fixes/fix_import.py b/Lib/lib2to3/fixes/fix_import.py deleted file mode 100644 index 734ca294699c36..00000000000000 --- a/Lib/lib2to3/fixes/fix_import.py +++ /dev/null @@ -1,99 +0,0 @@ -"""Fixer for import statements. -If spam is being imported from the local directory, this import: - from spam import eggs -Becomes: - from .spam import eggs - -And this import: - import spam -Becomes: - from . import spam -""" - -# Local imports -from .. import fixer_base -from os.path import dirname, join, exists, sep -from ..fixer_util import FromImport, syms, token - - -def traverse_imports(names): - """ - Walks over all the names imported in a dotted_as_names node. - """ - pending = [names] - while pending: - node = pending.pop() - if node.type == token.NAME: - yield node.value - elif node.type == syms.dotted_name: - yield "".join([ch.value for ch in node.children]) - elif node.type == syms.dotted_as_name: - pending.append(node.children[0]) - elif node.type == syms.dotted_as_names: - pending.extend(node.children[::-2]) - else: - raise AssertionError("unknown node type") - - -class FixImport(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - import_from< 'from' imp=any 'import' ['('] any [')'] > - | - import_name< 'import' imp=any > - """ - - def start_tree(self, tree, name): - super(FixImport, self).start_tree(tree, name) - self.skip = "absolute_import" in tree.future_features - - def transform(self, node, results): - if self.skip: - return - imp = results['imp'] - - if node.type == syms.import_from: - # Some imps are top-level (eg: 'import ham') - # some are first level (eg: 'import ham.eggs') - # some are third level (eg: 'import ham.eggs as spam') - # Hence, the loop - while not hasattr(imp, 'value'): - imp = imp.children[0] - if self.probably_a_local_import(imp.value): - imp.value = "." + imp.value - imp.changed() - else: - have_local = False - have_absolute = False - for mod_name in traverse_imports(imp): - if self.probably_a_local_import(mod_name): - have_local = True - else: - have_absolute = True - if have_absolute: - if have_local: - # We won't handle both sibling and absolute imports in the - # same statement at the moment. - self.warning(node, "absolute and local imports together") - return - - new = FromImport(".", [imp]) - new.prefix = node.prefix - return new - - def probably_a_local_import(self, imp_name): - if imp_name.startswith("."): - # Relative imports are certainly not local imports. - return False - imp_name = imp_name.split(".", 1)[0] - base_path = dirname(self.filename) - base_path = join(base_path, imp_name) - # If there is no __init__.py next to the file its not in a package - # so can't be a relative import. - if not exists(join(dirname(base_path), "__init__.py")): - return False - for ext in [".py", sep, ".pyc", ".so", ".sl", ".pyd"]: - if exists(base_path + ext): - return True - return False diff --git a/Lib/lib2to3/fixes/fix_imports.py b/Lib/lib2to3/fixes/fix_imports.py deleted file mode 100644 index aaf4f2f642efb5..00000000000000 --- a/Lib/lib2to3/fixes/fix_imports.py +++ /dev/null @@ -1,145 +0,0 @@ -"""Fix incompatible imports and module references.""" -# Authors: Collin Winter, Nick Edds - -# Local imports -from .. import fixer_base -from ..fixer_util import Name, attr_chain - -MAPPING = {'StringIO': 'io', - 'cStringIO': 'io', - 'cPickle': 'pickle', - '__builtin__' : 'builtins', - 'copy_reg': 'copyreg', - 'Queue': 'queue', - 'SocketServer': 'socketserver', - 'ConfigParser': 'configparser', - 'repr': 'reprlib', - 'FileDialog': 'tkinter.filedialog', - 'tkFileDialog': 'tkinter.filedialog', - 'SimpleDialog': 'tkinter.simpledialog', - 'tkSimpleDialog': 'tkinter.simpledialog', - 'tkColorChooser': 'tkinter.colorchooser', - 'tkCommonDialog': 'tkinter.commondialog', - 'Dialog': 'tkinter.dialog', - 'Tkdnd': 'tkinter.dnd', - 'tkFont': 'tkinter.font', - 'tkMessageBox': 'tkinter.messagebox', - 'ScrolledText': 'tkinter.scrolledtext', - 'Tkconstants': 'tkinter.constants', - 'Tix': 'tkinter.tix', - 'ttk': 'tkinter.ttk', - 'Tkinter': 'tkinter', - 'markupbase': '_markupbase', - '_winreg': 'winreg', - 'thread': '_thread', - 'dummy_thread': '_dummy_thread', - # anydbm and whichdb are handled by fix_imports2 - 'dbhash': 'dbm.bsd', - 'dumbdbm': 'dbm.dumb', - 'dbm': 'dbm.ndbm', - 'gdbm': 'dbm.gnu', - 'xmlrpclib': 'xmlrpc.client', - 'DocXMLRPCServer': 'xmlrpc.server', - 'SimpleXMLRPCServer': 'xmlrpc.server', - 'httplib': 'http.client', - 'htmlentitydefs' : 'html.entities', - 'HTMLParser' : 'html.parser', - 'Cookie': 'http.cookies', - 'cookielib': 'http.cookiejar', - 'BaseHTTPServer': 'http.server', - 'SimpleHTTPServer': 'http.server', - 'CGIHTTPServer': 'http.server', - #'test.test_support': 'test.support', - 'commands': 'subprocess', - 'UserString' : 'collections', - 'UserList' : 'collections', - 'urlparse' : 'urllib.parse', - 'robotparser' : 'urllib.robotparser', -} - - -def alternates(members): - return "(" + "|".join(map(repr, members)) + ")" - - -def build_pattern(mapping=MAPPING): - mod_list = ' | '.join(["module_name='%s'" % key for key in mapping]) - bare_names = alternates(mapping.keys()) - - yield """name_import=import_name< 'import' ((%s) | - multiple_imports=dotted_as_names< any* (%s) any* >) > - """ % (mod_list, mod_list) - yield """import_from< 'from' (%s) 'import' ['('] - ( any | import_as_name< any 'as' any > | - import_as_names< any* >) [')'] > - """ % mod_list - yield """import_name< 'import' (dotted_as_name< (%s) 'as' any > | - multiple_imports=dotted_as_names< - any* dotted_as_name< (%s) 'as' any > any* >) > - """ % (mod_list, mod_list) - - # Find usages of module members in code e.g. thread.foo(bar) - yield "power< bare_with_attr=(%s) trailer<'.' any > any* >" % bare_names - - -class FixImports(fixer_base.BaseFix): - - BM_compatible = True - keep_line_order = True - # This is overridden in fix_imports2. - mapping = MAPPING - - # We want to run this fixer late, so fix_import doesn't try to make stdlib - # renames into relative imports. - run_order = 6 - - def build_pattern(self): - return "|".join(build_pattern(self.mapping)) - - def compile_pattern(self): - # We override this, so MAPPING can be pragmatically altered and the - # changes will be reflected in PATTERN. - self.PATTERN = self.build_pattern() - super(FixImports, self).compile_pattern() - - # Don't match the node if it's within another match. - def match(self, node): - match = super(FixImports, self).match - results = match(node) - if results: - # Module usage could be in the trailer of an attribute lookup, so we - # might have nested matches when "bare_with_attr" is present. - if "bare_with_attr" not in results and \ - any(match(obj) for obj in attr_chain(node, "parent")): - return False - return results - return False - - def start_tree(self, tree, filename): - super(FixImports, self).start_tree(tree, filename) - self.replace = {} - - def transform(self, node, results): - import_mod = results.get("module_name") - if import_mod: - mod_name = import_mod.value - new_name = self.mapping[mod_name] - import_mod.replace(Name(new_name, prefix=import_mod.prefix)) - if "name_import" in results: - # If it's not a "from x import x, y" or "import x as y" import, - # marked its usage to be replaced. - self.replace[mod_name] = new_name - if "multiple_imports" in results: - # This is a nasty hack to fix multiple imports on a line (e.g., - # "import StringIO, urlparse"). The problem is that I can't - # figure out an easy way to make a pattern recognize the keys of - # MAPPING randomly sprinkled in an import statement. - results = self.match(node) - if results: - self.transform(node, results) - else: - # Replace usage of the module. - bare_name = results["bare_with_attr"][0] - new_name = self.replace.get(bare_name.value) - if new_name: - bare_name.replace(Name(new_name, prefix=bare_name.prefix)) diff --git a/Lib/lib2to3/fixes/fix_imports2.py b/Lib/lib2to3/fixes/fix_imports2.py deleted file mode 100644 index 9a33c67b1dc194..00000000000000 --- a/Lib/lib2to3/fixes/fix_imports2.py +++ /dev/null @@ -1,16 +0,0 @@ -"""Fix incompatible imports and module references that must be fixed after -fix_imports.""" -from . import fix_imports - - -MAPPING = { - 'whichdb': 'dbm', - 'anydbm': 'dbm', - } - - -class FixImports2(fix_imports.FixImports): - - run_order = 7 - - mapping = MAPPING diff --git a/Lib/lib2to3/fixes/fix_input.py b/Lib/lib2to3/fixes/fix_input.py deleted file mode 100644 index 9cf9a48c471f35..00000000000000 --- a/Lib/lib2to3/fixes/fix_input.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Fixer that changes input(...) into eval(input(...)).""" -# Author: Andre Roberge - -# Local imports -from .. import fixer_base -from ..fixer_util import Call, Name -from .. import patcomp - - -context = patcomp.compile_pattern("power< 'eval' trailer< '(' any ')' > >") - - -class FixInput(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - power< 'input' args=trailer< '(' [any] ')' > > - """ - - def transform(self, node, results): - # If we're already wrapped in an eval() call, we're done. - if context.match(node.parent.parent): - return - - new = node.clone() - new.prefix = "" - return Call(Name("eval"), [new], prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_intern.py b/Lib/lib2to3/fixes/fix_intern.py deleted file mode 100644 index d752843092aacd..00000000000000 --- a/Lib/lib2to3/fixes/fix_intern.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2006 Georg Brandl. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for intern(). - -intern(s) -> sys.intern(s)""" - -# Local imports -from .. import fixer_base -from ..fixer_util import ImportAndCall, touch_import - - -class FixIntern(fixer_base.BaseFix): - BM_compatible = True - order = "pre" - - PATTERN = """ - power< 'intern' - trailer< lpar='(' - ( not(arglist | argument) any ','> ) - rpar=')' > - after=any* - > - """ - - def transform(self, node, results): - if results: - # I feel like we should be able to express this logic in the - # PATTERN above but I don't know how to do it so... - obj = results['obj'] - if obj: - if (obj.type == self.syms.argument and - obj.children[0].value in {'**', '*'}): - return # Make no change. - names = ('sys', 'intern') - new = ImportAndCall(node, results, names) - touch_import(None, 'sys', node) - return new diff --git a/Lib/lib2to3/fixes/fix_isinstance.py b/Lib/lib2to3/fixes/fix_isinstance.py deleted file mode 100644 index bebb1de120424b..00000000000000 --- a/Lib/lib2to3/fixes/fix_isinstance.py +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright 2008 Armin Ronacher. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that cleans up a tuple argument to isinstance after the tokens -in it were fixed. This is mainly used to remove double occurrences of -tokens as a leftover of the long -> int / unicode -> str conversion. - -eg. isinstance(x, (int, long)) -> isinstance(x, (int, int)) - -> isinstance(x, int) -""" - -from .. import fixer_base -from ..fixer_util import token - - -class FixIsinstance(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - power< - 'isinstance' - trailer< '(' arglist< any ',' atom< '(' - args=testlist_gexp< any+ > - ')' > > ')' > - > - """ - - run_order = 6 - - def transform(self, node, results): - names_inserted = set() - testlist = results["args"] - args = testlist.children - new_args = [] - iterator = enumerate(args) - for idx, arg in iterator: - if arg.type == token.NAME and arg.value in names_inserted: - if idx < len(args) - 1 and args[idx + 1].type == token.COMMA: - next(iterator) - continue - else: - new_args.append(arg) - if arg.type == token.NAME: - names_inserted.add(arg.value) - if new_args and new_args[-1].type == token.COMMA: - del new_args[-1] - if len(new_args) == 1: - atom = testlist.parent - new_args[0].prefix = atom.prefix - atom.replace(new_args[0]) - else: - args[:] = new_args - node.changed() diff --git a/Lib/lib2to3/fixes/fix_itertools.py b/Lib/lib2to3/fixes/fix_itertools.py deleted file mode 100644 index 8e78d6c689f439..00000000000000 --- a/Lib/lib2to3/fixes/fix_itertools.py +++ /dev/null @@ -1,43 +0,0 @@ -""" Fixer for itertools.(imap|ifilter|izip) --> (map|filter|zip) and - itertools.ifilterfalse --> itertools.filterfalse (bugs 2360-2363) - - imports from itertools are fixed in fix_itertools_import.py - - If itertools is imported as something else (ie: import itertools as it; - it.izip(spam, eggs)) method calls will not get fixed. - """ - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - -class FixItertools(fixer_base.BaseFix): - BM_compatible = True - it_funcs = "('imap'|'ifilter'|'izip'|'izip_longest'|'ifilterfalse')" - PATTERN = """ - power< it='itertools' - trailer< - dot='.' func=%(it_funcs)s > trailer< '(' [any] ')' > > - | - power< func=%(it_funcs)s trailer< '(' [any] ')' > > - """ %(locals()) - - # Needs to be run after fix_(map|zip|filter) - run_order = 6 - - def transform(self, node, results): - prefix = None - func = results['func'][0] - if ('it' in results and - func.value not in ('ifilterfalse', 'izip_longest')): - dot, it = (results['dot'], results['it']) - # Remove the 'itertools' - prefix = it.prefix - it.remove() - # Replace the node which contains ('.', 'function') with the - # function (to be consistent with the second part of the pattern) - dot.remove() - func.parent.replace(func) - - prefix = prefix or func.prefix - func.replace(Name(func.value[1:], prefix=prefix)) diff --git a/Lib/lib2to3/fixes/fix_itertools_imports.py b/Lib/lib2to3/fixes/fix_itertools_imports.py deleted file mode 100644 index 0ddbc7b8422991..00000000000000 --- a/Lib/lib2to3/fixes/fix_itertools_imports.py +++ /dev/null @@ -1,57 +0,0 @@ -""" Fixer for imports of itertools.(imap|ifilter|izip|ifilterfalse) """ - -# Local imports -from lib2to3 import fixer_base -from lib2to3.fixer_util import BlankLine, syms, token - - -class FixItertoolsImports(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - import_from< 'from' 'itertools' 'import' imports=any > - """ %(locals()) - - def transform(self, node, results): - imports = results['imports'] - if imports.type == syms.import_as_name or not imports.children: - children = [imports] - else: - children = imports.children - for child in children[::2]: - if child.type == token.NAME: - member = child.value - name_node = child - elif child.type == token.STAR: - # Just leave the import as is. - return - else: - assert child.type == syms.import_as_name - name_node = child.children[0] - member_name = name_node.value - if member_name in ('imap', 'izip', 'ifilter'): - child.value = None - child.remove() - elif member_name in ('ifilterfalse', 'izip_longest'): - node.changed() - name_node.value = ('filterfalse' if member_name[1] == 'f' - else 'zip_longest') - - # Make sure the import statement is still sane - children = imports.children[:] or [imports] - remove_comma = True - for child in children: - if remove_comma and child.type == token.COMMA: - child.remove() - else: - remove_comma ^= True - - while children and children[-1].type == token.COMMA: - children.pop().remove() - - # If there are no imports left, just get rid of the entire statement - if (not (imports.children or getattr(imports, 'value', None)) or - imports.parent is None): - p = node.prefix - node = BlankLine() - node.prefix = p - return node diff --git a/Lib/lib2to3/fixes/fix_long.py b/Lib/lib2to3/fixes/fix_long.py deleted file mode 100644 index f227c9f4981538..00000000000000 --- a/Lib/lib2to3/fixes/fix_long.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that turns 'long' into 'int' everywhere. -""" - -# Local imports -from lib2to3 import fixer_base -from lib2to3.fixer_util import is_probably_builtin - - -class FixLong(fixer_base.BaseFix): - BM_compatible = True - PATTERN = "'long'" - - def transform(self, node, results): - if is_probably_builtin(node): - node.value = "int" - node.changed() diff --git a/Lib/lib2to3/fixes/fix_map.py b/Lib/lib2to3/fixes/fix_map.py deleted file mode 100644 index 78cf81c6f94098..00000000000000 --- a/Lib/lib2to3/fixes/fix_map.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that changes map(F, ...) into list(map(F, ...)) unless there -exists a 'from future_builtins import map' statement in the top-level -namespace. - -As a special case, map(None, X) is changed into list(X). (This is -necessary because the semantics are changed in this case -- the new -map(None, X) is equivalent to [(x,) for x in X].) - -We avoid the transformation (except for the special case mentioned -above) if the map() call is directly contained in iter(<>), list(<>), -tuple(<>), sorted(<>), ...join(<>), or for V in <>:. - -NOTE: This is still not correct if the original code was depending on -map(F, X, Y, ...) to go on until the longest argument is exhausted, -substituting None for missing values -- like zip(), it now stops as -soon as the shortest argument is exhausted. -""" - -# Local imports -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Name, ArgList, Call, ListComp, in_special_context -from ..pygram import python_symbols as syms -from ..pytree import Node - - -class FixMap(fixer_base.ConditionalFix): - BM_compatible = True - - PATTERN = """ - map_none=power< - 'map' - trailer< '(' arglist< 'None' ',' arg=any [','] > ')' > - [extra_trailers=trailer*] - > - | - map_lambda=power< - 'map' - trailer< - '(' - arglist< - lambdef< 'lambda' - (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any - > - ',' - it=any - > - ')' - > - [extra_trailers=trailer*] - > - | - power< - 'map' args=trailer< '(' [any] ')' > - [extra_trailers=trailer*] - > - """ - - skip_on = 'future_builtins.map' - - def transform(self, node, results): - if self.should_skip(node): - return - - trailers = [] - if 'extra_trailers' in results: - for t in results['extra_trailers']: - trailers.append(t.clone()) - - if node.parent.type == syms.simple_stmt: - self.warning(node, "You should use a for loop here") - new = node.clone() - new.prefix = "" - new = Call(Name("list"), [new]) - elif "map_lambda" in results: - new = ListComp(results["xp"].clone(), - results["fp"].clone(), - results["it"].clone()) - new = Node(syms.power, [new] + trailers, prefix="") - - else: - if "map_none" in results: - new = results["arg"].clone() - new.prefix = "" - else: - if "args" in results: - args = results["args"] - if args.type == syms.trailer and \ - args.children[1].type == syms.arglist and \ - args.children[1].children[0].type == token.NAME and \ - args.children[1].children[0].value == "None": - self.warning(node, "cannot convert map(None, ...) " - "with multiple arguments because map() " - "now truncates to the shortest sequence") - return - - new = Node(syms.power, [Name("map"), args.clone()]) - new.prefix = "" - - if in_special_context(node): - return None - - new = Node(syms.power, [Name("list"), ArgList([new])] + trailers) - new.prefix = "" - - new.prefix = node.prefix - return new diff --git a/Lib/lib2to3/fixes/fix_metaclass.py b/Lib/lib2to3/fixes/fix_metaclass.py deleted file mode 100644 index fe547b2228072a..00000000000000 --- a/Lib/lib2to3/fixes/fix_metaclass.py +++ /dev/null @@ -1,228 +0,0 @@ -"""Fixer for __metaclass__ = X -> (metaclass=X) methods. - - The various forms of classef (inherits nothing, inherits once, inherits - many) don't parse the same in the CST so we look at ALL classes for - a __metaclass__ and if we find one normalize the inherits to all be - an arglist. - - For one-liner classes ('class X: pass') there is no indent/dedent so - we normalize those into having a suite. - - Moving the __metaclass__ into the classdef can also cause the class - body to be empty so there is some special casing for that as well. - - This fixer also tries very hard to keep original indenting and spacing - in all those corner cases. - -""" -# Author: Jack Diederich - -# Local imports -from .. import fixer_base -from ..pygram import token -from ..fixer_util import syms, Node, Leaf - - -def has_metaclass(parent): - """ we have to check the cls_node without changing it. - There are two possibilities: - 1) clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta') - 2) clsdef => simple_stmt => expr_stmt => Leaf('__meta') - """ - for node in parent.children: - if node.type == syms.suite: - return has_metaclass(node) - elif node.type == syms.simple_stmt and node.children: - expr_node = node.children[0] - if expr_node.type == syms.expr_stmt and expr_node.children: - left_side = expr_node.children[0] - if isinstance(left_side, Leaf) and \ - left_side.value == '__metaclass__': - return True - return False - - -def fixup_parse_tree(cls_node): - """ one-line classes don't get a suite in the parse tree so we add - one to normalize the tree - """ - for node in cls_node.children: - if node.type == syms.suite: - # already in the preferred format, do nothing - return - - # !%@#! one-liners have no suite node, we have to fake one up - for i, node in enumerate(cls_node.children): - if node.type == token.COLON: - break - else: - raise ValueError("No class suite and no ':'!") - - # move everything into a suite node - suite = Node(syms.suite, []) - while cls_node.children[i+1:]: - move_node = cls_node.children[i+1] - suite.append_child(move_node.clone()) - move_node.remove() - cls_node.append_child(suite) - node = suite - - -def fixup_simple_stmt(parent, i, stmt_node): - """ if there is a semi-colon all the parts count as part of the same - simple_stmt. We just want the __metaclass__ part so we move - everything after the semi-colon into its own simple_stmt node - """ - for semi_ind, node in enumerate(stmt_node.children): - if node.type == token.SEMI: # *sigh* - break - else: - return - - node.remove() # kill the semicolon - new_expr = Node(syms.expr_stmt, []) - new_stmt = Node(syms.simple_stmt, [new_expr]) - while stmt_node.children[semi_ind:]: - move_node = stmt_node.children[semi_ind] - new_expr.append_child(move_node.clone()) - move_node.remove() - parent.insert_child(i, new_stmt) - new_leaf1 = new_stmt.children[0].children[0] - old_leaf1 = stmt_node.children[0].children[0] - new_leaf1.prefix = old_leaf1.prefix - - -def remove_trailing_newline(node): - if node.children and node.children[-1].type == token.NEWLINE: - node.children[-1].remove() - - -def find_metas(cls_node): - # find the suite node (Mmm, sweet nodes) - for node in cls_node.children: - if node.type == syms.suite: - break - else: - raise ValueError("No class suite!") - - # look for simple_stmt[ expr_stmt[ Leaf('__metaclass__') ] ] - for i, simple_node in list(enumerate(node.children)): - if simple_node.type == syms.simple_stmt and simple_node.children: - expr_node = simple_node.children[0] - if expr_node.type == syms.expr_stmt and expr_node.children: - # Check if the expr_node is a simple assignment. - left_node = expr_node.children[0] - if isinstance(left_node, Leaf) and \ - left_node.value == '__metaclass__': - # We found an assignment to __metaclass__. - fixup_simple_stmt(node, i, simple_node) - remove_trailing_newline(simple_node) - yield (node, i, simple_node) - - -def fixup_indent(suite): - """ If an INDENT is followed by a thing with a prefix then nuke the prefix - Otherwise we get in trouble when removing __metaclass__ at suite start - """ - kids = suite.children[::-1] - # find the first indent - while kids: - node = kids.pop() - if node.type == token.INDENT: - break - - # find the first Leaf - while kids: - node = kids.pop() - if isinstance(node, Leaf) and node.type != token.DEDENT: - if node.prefix: - node.prefix = '' - return - else: - kids.extend(node.children[::-1]) - - -class FixMetaclass(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - classdef - """ - - def transform(self, node, results): - if not has_metaclass(node): - return - - fixup_parse_tree(node) - - # find metaclasses, keep the last one - last_metaclass = None - for suite, i, stmt in find_metas(node): - last_metaclass = stmt - stmt.remove() - - text_type = node.children[0].type # always Leaf(nnn, 'class') - - # figure out what kind of classdef we have - if len(node.children) == 7: - # Node(classdef, ['class', 'name', '(', arglist, ')', ':', suite]) - # 0 1 2 3 4 5 6 - if node.children[3].type == syms.arglist: - arglist = node.children[3] - # Node(classdef, ['class', 'name', '(', 'Parent', ')', ':', suite]) - else: - parent = node.children[3].clone() - arglist = Node(syms.arglist, [parent]) - node.set_child(3, arglist) - elif len(node.children) == 6: - # Node(classdef, ['class', 'name', '(', ')', ':', suite]) - # 0 1 2 3 4 5 - arglist = Node(syms.arglist, []) - node.insert_child(3, arglist) - elif len(node.children) == 4: - # Node(classdef, ['class', 'name', ':', suite]) - # 0 1 2 3 - arglist = Node(syms.arglist, []) - node.insert_child(2, Leaf(token.RPAR, ')')) - node.insert_child(2, arglist) - node.insert_child(2, Leaf(token.LPAR, '(')) - else: - raise ValueError("Unexpected class definition") - - # now stick the metaclass in the arglist - meta_txt = last_metaclass.children[0].children[0] - meta_txt.value = 'metaclass' - orig_meta_prefix = meta_txt.prefix - - if arglist.children: - arglist.append_child(Leaf(token.COMMA, ',')) - meta_txt.prefix = ' ' - else: - meta_txt.prefix = '' - - # compact the expression "metaclass = Meta" -> "metaclass=Meta" - expr_stmt = last_metaclass.children[0] - assert expr_stmt.type == syms.expr_stmt - expr_stmt.children[1].prefix = '' - expr_stmt.children[2].prefix = '' - - arglist.append_child(last_metaclass) - - fixup_indent(suite) - - # check for empty suite - if not suite.children: - # one-liner that was just __metaclass_ - suite.remove() - pass_leaf = Leaf(text_type, 'pass') - pass_leaf.prefix = orig_meta_prefix - node.append_child(pass_leaf) - node.append_child(Leaf(token.NEWLINE, '\n')) - - elif len(suite.children) > 1 and \ - (suite.children[-2].type == token.INDENT and - suite.children[-1].type == token.DEDENT): - # there was only one line in the class body and it was __metaclass__ - pass_leaf = Leaf(text_type, 'pass') - suite.insert_child(-1, pass_leaf) - suite.insert_child(-1, Leaf(token.NEWLINE, '\n')) diff --git a/Lib/lib2to3/fixes/fix_methodattrs.py b/Lib/lib2to3/fixes/fix_methodattrs.py deleted file mode 100644 index 7f9004f00e6e8f..00000000000000 --- a/Lib/lib2to3/fixes/fix_methodattrs.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Fix bound method attributes (method.im_? -> method.__?__). -""" -# Author: Christian Heimes - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - -MAP = { - "im_func" : "__func__", - "im_self" : "__self__", - "im_class" : "__self__.__class__" - } - -class FixMethodattrs(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - power< any+ trailer< '.' attr=('im_func' | 'im_self' | 'im_class') > any* > - """ - - def transform(self, node, results): - attr = results["attr"][0] - new = MAP[attr.value] - attr.replace(Name(new, prefix=attr.prefix)) diff --git a/Lib/lib2to3/fixes/fix_ne.py b/Lib/lib2to3/fixes/fix_ne.py deleted file mode 100644 index e3ee10f4a63e0c..00000000000000 --- a/Lib/lib2to3/fixes/fix_ne.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that turns <> into !=.""" - -# Local imports -from .. import pytree -from ..pgen2 import token -from .. import fixer_base - - -class FixNe(fixer_base.BaseFix): - # This is so simple that we don't need the pattern compiler. - - _accept_type = token.NOTEQUAL - - def match(self, node): - # Override - return node.value == "<>" - - def transform(self, node, results): - new = pytree.Leaf(token.NOTEQUAL, "!=", prefix=node.prefix) - return new diff --git a/Lib/lib2to3/fixes/fix_next.py b/Lib/lib2to3/fixes/fix_next.py deleted file mode 100644 index 9f6305e1d49dc5..00000000000000 --- a/Lib/lib2to3/fixes/fix_next.py +++ /dev/null @@ -1,103 +0,0 @@ -"""Fixer for it.next() -> next(it), per PEP 3114.""" -# Author: Collin Winter - -# Things that currently aren't covered: -# - listcomp "next" names aren't warned -# - "with" statement targets aren't checked - -# Local imports -from ..pgen2 import token -from ..pygram import python_symbols as syms -from .. import fixer_base -from ..fixer_util import Name, Call, find_binding - -bind_warning = "Calls to builtin next() possibly shadowed by global binding" - - -class FixNext(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - power< base=any+ trailer< '.' attr='next' > trailer< '(' ')' > > - | - power< head=any+ trailer< '.' attr='next' > not trailer< '(' ')' > > - | - classdef< 'class' any+ ':' - suite< any* - funcdef< 'def' - name='next' - parameters< '(' NAME ')' > any+ > - any* > > - | - global=global_stmt< 'global' any* 'next' any* > - """ - - order = "pre" # Pre-order tree traversal - - def start_tree(self, tree, filename): - super(FixNext, self).start_tree(tree, filename) - - n = find_binding('next', tree) - if n: - self.warning(n, bind_warning) - self.shadowed_next = True - else: - self.shadowed_next = False - - def transform(self, node, results): - assert results - - base = results.get("base") - attr = results.get("attr") - name = results.get("name") - - if base: - if self.shadowed_next: - attr.replace(Name("__next__", prefix=attr.prefix)) - else: - base = [n.clone() for n in base] - base[0].prefix = "" - node.replace(Call(Name("next", prefix=node.prefix), base)) - elif name: - n = Name("__next__", prefix=name.prefix) - name.replace(n) - elif attr: - # We don't do this transformation if we're assigning to "x.next". - # Unfortunately, it doesn't seem possible to do this in PATTERN, - # so it's being done here. - if is_assign_target(node): - head = results["head"] - if "".join([str(n) for n in head]).strip() == '__builtin__': - self.warning(node, bind_warning) - return - attr.replace(Name("__next__")) - elif "global" in results: - self.warning(node, bind_warning) - self.shadowed_next = True - - -### The following functions help test if node is part of an assignment -### target. - -def is_assign_target(node): - assign = find_assign(node) - if assign is None: - return False - - for child in assign.children: - if child.type == token.EQUAL: - return False - elif is_subtree(child, node): - return True - return False - -def find_assign(node): - if node.type == syms.expr_stmt: - return node - if node.type == syms.simple_stmt or node.parent is None: - return None - return find_assign(node.parent) - -def is_subtree(root, node): - if root == node: - return True - return any(is_subtree(c, node) for c in root.children) diff --git a/Lib/lib2to3/fixes/fix_nonzero.py b/Lib/lib2to3/fixes/fix_nonzero.py deleted file mode 100644 index c2295969a7728f..00000000000000 --- a/Lib/lib2to3/fixes/fix_nonzero.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Fixer for __nonzero__ -> __bool__ methods.""" -# Author: Collin Winter - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - -class FixNonzero(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - classdef< 'class' any+ ':' - suite< any* - funcdef< 'def' name='__nonzero__' - parameters< '(' NAME ')' > any+ > - any* > > - """ - - def transform(self, node, results): - name = results["name"] - new = Name("__bool__", prefix=name.prefix) - name.replace(new) diff --git a/Lib/lib2to3/fixes/fix_numliterals.py b/Lib/lib2to3/fixes/fix_numliterals.py deleted file mode 100644 index 79207d4aa368ae..00000000000000 --- a/Lib/lib2to3/fixes/fix_numliterals.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Fixer that turns 1L into 1, 0755 into 0o755. -""" -# Copyright 2007 Georg Brandl. -# Licensed to PSF under a Contributor Agreement. - -# Local imports -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Number - - -class FixNumliterals(fixer_base.BaseFix): - # This is so simple that we don't need the pattern compiler. - - _accept_type = token.NUMBER - - def match(self, node): - # Override - return (node.value.startswith("0") or node.value[-1] in "Ll") - - def transform(self, node, results): - val = node.value - if val[-1] in 'Ll': - val = val[:-1] - elif val.startswith('0') and val.isdigit() and len(set(val)) > 1: - val = "0o" + val[1:] - - return Number(val, prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_operator.py b/Lib/lib2to3/fixes/fix_operator.py deleted file mode 100644 index d303cd2018befb..00000000000000 --- a/Lib/lib2to3/fixes/fix_operator.py +++ /dev/null @@ -1,97 +0,0 @@ -"""Fixer for operator functions. - -operator.isCallable(obj) -> callable(obj) -operator.sequenceIncludes(obj) -> operator.contains(obj) -operator.isSequenceType(obj) -> isinstance(obj, collections.abc.Sequence) -operator.isMappingType(obj) -> isinstance(obj, collections.abc.Mapping) -operator.isNumberType(obj) -> isinstance(obj, numbers.Number) -operator.repeat(obj, n) -> operator.mul(obj, n) -operator.irepeat(obj, n) -> operator.imul(obj, n) -""" - -import collections.abc - -# Local imports -from lib2to3 import fixer_base -from lib2to3.fixer_util import Call, Name, String, touch_import - - -def invocation(s): - def dec(f): - f.invocation = s - return f - return dec - - -class FixOperator(fixer_base.BaseFix): - BM_compatible = True - order = "pre" - - methods = """ - method=('isCallable'|'sequenceIncludes' - |'isSequenceType'|'isMappingType'|'isNumberType' - |'repeat'|'irepeat') - """ - obj = "'(' obj=any ')'" - PATTERN = """ - power< module='operator' - trailer< '.' %(methods)s > trailer< %(obj)s > > - | - power< %(methods)s trailer< %(obj)s > > - """ % dict(methods=methods, obj=obj) - - def transform(self, node, results): - method = self._check_method(node, results) - if method is not None: - return method(node, results) - - @invocation("operator.contains(%s)") - def _sequenceIncludes(self, node, results): - return self._handle_rename(node, results, "contains") - - @invocation("callable(%s)") - def _isCallable(self, node, results): - obj = results["obj"] - return Call(Name("callable"), [obj.clone()], prefix=node.prefix) - - @invocation("operator.mul(%s)") - def _repeat(self, node, results): - return self._handle_rename(node, results, "mul") - - @invocation("operator.imul(%s)") - def _irepeat(self, node, results): - return self._handle_rename(node, results, "imul") - - @invocation("isinstance(%s, collections.abc.Sequence)") - def _isSequenceType(self, node, results): - return self._handle_type2abc(node, results, "collections.abc", "Sequence") - - @invocation("isinstance(%s, collections.abc.Mapping)") - def _isMappingType(self, node, results): - return self._handle_type2abc(node, results, "collections.abc", "Mapping") - - @invocation("isinstance(%s, numbers.Number)") - def _isNumberType(self, node, results): - return self._handle_type2abc(node, results, "numbers", "Number") - - def _handle_rename(self, node, results, name): - method = results["method"][0] - method.value = name - method.changed() - - def _handle_type2abc(self, node, results, module, abc): - touch_import(None, module, node) - obj = results["obj"] - args = [obj.clone(), String(", " + ".".join([module, abc]))] - return Call(Name("isinstance"), args, prefix=node.prefix) - - def _check_method(self, node, results): - method = getattr(self, "_" + results["method"][0].value) - if isinstance(method, collections.abc.Callable): - if "module" in results: - return method - else: - sub = (str(results["obj"]),) - invocation_str = method.invocation % sub - self.warning(node, "You should use '%s' here." % invocation_str) - return None diff --git a/Lib/lib2to3/fixes/fix_paren.py b/Lib/lib2to3/fixes/fix_paren.py deleted file mode 100644 index df3da5f5232c9c..00000000000000 --- a/Lib/lib2to3/fixes/fix_paren.py +++ /dev/null @@ -1,44 +0,0 @@ -"""Fixer that adds parentheses where they are required - -This converts ``[x for x in 1, 2]`` to ``[x for x in (1, 2)]``.""" - -# By Taek Joo Kim and Benjamin Peterson - -# Local imports -from .. import fixer_base -from ..fixer_util import LParen, RParen - -# XXX This doesn't support nested for loops like [x for x in 1, 2 for x in 1, 2] -class FixParen(fixer_base.BaseFix): - BM_compatible = True - - PATTERN = """ - atom< ('[' | '(') - (listmaker< any - comp_for< - 'for' NAME 'in' - target=testlist_safe< any (',' any)+ [','] - > - [any] - > - > - | - testlist_gexp< any - comp_for< - 'for' NAME 'in' - target=testlist_safe< any (',' any)+ [','] - > - [any] - > - >) - (']' | ')') > - """ - - def transform(self, node, results): - target = results["target"] - - lparen = LParen() - lparen.prefix = target.prefix - target.prefix = "" # Make it hug the parentheses - target.insert_child(0, lparen) - target.append_child(RParen()) diff --git a/Lib/lib2to3/fixes/fix_print.py b/Lib/lib2to3/fixes/fix_print.py deleted file mode 100644 index 8780322265f6fe..00000000000000 --- a/Lib/lib2to3/fixes/fix_print.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for print. - -Change: - 'print' into 'print()' - 'print ...' into 'print(...)' - 'print ... ,' into 'print(..., end=" ")' - 'print >>x, ...' into 'print(..., file=x)' - -No changes are applied if print_function is imported from __future__ - -""" - -# Local imports -from .. import patcomp -from .. import pytree -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Name, Call, Comma, String - - -parend_expr = patcomp.compile_pattern( - """atom< '(' [atom|STRING|NAME] ')' >""" - ) - - -class FixPrint(fixer_base.BaseFix): - - BM_compatible = True - - PATTERN = """ - simple_stmt< any* bare='print' any* > | print_stmt - """ - - def transform(self, node, results): - assert results - - bare_print = results.get("bare") - - if bare_print: - # Special-case print all by itself - bare_print.replace(Call(Name("print"), [], - prefix=bare_print.prefix)) - return - assert node.children[0] == Name("print") - args = node.children[1:] - if len(args) == 1 and parend_expr.match(args[0]): - # We don't want to keep sticking parens around an - # already-parenthesised expression. - return - - sep = end = file = None - if args and args[-1] == Comma(): - args = args[:-1] - end = " " - if args and args[0] == pytree.Leaf(token.RIGHTSHIFT, ">>"): - assert len(args) >= 2 - file = args[1].clone() - args = args[3:] # Strip a possible comma after the file expression - # Now synthesize a print(args, sep=..., end=..., file=...) node. - l_args = [arg.clone() for arg in args] - if l_args: - l_args[0].prefix = "" - if sep is not None or end is not None or file is not None: - if sep is not None: - self.add_kwarg(l_args, "sep", String(repr(sep))) - if end is not None: - self.add_kwarg(l_args, "end", String(repr(end))) - if file is not None: - self.add_kwarg(l_args, "file", file) - n_stmt = Call(Name("print"), l_args) - n_stmt.prefix = node.prefix - return n_stmt - - def add_kwarg(self, l_nodes, s_kwd, n_expr): - # XXX All this prefix-setting may lose comments (though rarely) - n_expr.prefix = "" - n_argument = pytree.Node(self.syms.argument, - (Name(s_kwd), - pytree.Leaf(token.EQUAL, "="), - n_expr)) - if l_nodes: - l_nodes.append(Comma()) - n_argument.prefix = " " - l_nodes.append(n_argument) diff --git a/Lib/lib2to3/fixes/fix_raise.py b/Lib/lib2to3/fixes/fix_raise.py deleted file mode 100644 index 05aa21e74a30ff..00000000000000 --- a/Lib/lib2to3/fixes/fix_raise.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Fixer for 'raise E, V, T' - -raise -> raise -raise E -> raise E -raise E, V -> raise E(V) -raise E, V, T -> raise E(V).with_traceback(T) -raise E, None, T -> raise E.with_traceback(T) - -raise (((E, E'), E''), E'''), V -> raise E(V) -raise "foo", V, T -> warns about string exceptions - - -CAVEATS: -1) "raise E, V" will be incorrectly translated if V is an exception - instance. The correct Python 3 idiom is - - raise E from V - - but since we can't detect instance-hood by syntax alone and since - any client code would have to be changed as well, we don't automate - this. -""" -# Author: Collin Winter - -# Local imports -from .. import pytree -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Name, Call, Attr, ArgList, is_tuple - -class FixRaise(fixer_base.BaseFix): - - BM_compatible = True - PATTERN = """ - raise_stmt< 'raise' exc=any [',' val=any [',' tb=any]] > - """ - - def transform(self, node, results): - syms = self.syms - - exc = results["exc"].clone() - if exc.type == token.STRING: - msg = "Python 3 does not support string exceptions" - self.cannot_convert(node, msg) - return - - # Python 2 supports - # raise ((((E1, E2), E3), E4), E5), V - # as a synonym for - # raise E1, V - # Since Python 3 will not support this, we recurse down any tuple - # literals, always taking the first element. - if is_tuple(exc): - while is_tuple(exc): - # exc.children[1:-1] is the unparenthesized tuple - # exc.children[1].children[0] is the first element of the tuple - exc = exc.children[1].children[0].clone() - exc.prefix = " " - - if "val" not in results: - # One-argument raise - new = pytree.Node(syms.raise_stmt, [Name("raise"), exc]) - new.prefix = node.prefix - return new - - val = results["val"].clone() - if is_tuple(val): - args = [c.clone() for c in val.children[1:-1]] - else: - val.prefix = "" - args = [val] - - if "tb" in results: - tb = results["tb"].clone() - tb.prefix = "" - - e = exc - # If there's a traceback and None is passed as the value, then don't - # add a call, since the user probably just wants to add a - # traceback. See issue #9661. - if val.type != token.NAME or val.value != "None": - e = Call(exc, args) - with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])] - new = pytree.Node(syms.simple_stmt, [Name("raise")] + with_tb) - new.prefix = node.prefix - return new - else: - return pytree.Node(syms.raise_stmt, - [Name("raise"), Call(exc, args)], - prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_raw_input.py b/Lib/lib2to3/fixes/fix_raw_input.py deleted file mode 100644 index a51bb694b9e01e..00000000000000 --- a/Lib/lib2to3/fixes/fix_raw_input.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Fixer that changes raw_input(...) into input(...).""" -# Author: Andre Roberge - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - -class FixRawInput(fixer_base.BaseFix): - - BM_compatible = True - PATTERN = """ - power< name='raw_input' trailer< '(' [any] ')' > any* > - """ - - def transform(self, node, results): - name = results["name"] - name.replace(Name("input", prefix=name.prefix)) diff --git a/Lib/lib2to3/fixes/fix_reduce.py b/Lib/lib2to3/fixes/fix_reduce.py deleted file mode 100644 index 00e5aa1c33d482..00000000000000 --- a/Lib/lib2to3/fixes/fix_reduce.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2008 Armin Ronacher. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for reduce(). - -Makes sure reduce() is imported from the functools module if reduce is -used in that module. -""" - -from lib2to3 import fixer_base -from lib2to3.fixer_util import touch_import - - - -class FixReduce(fixer_base.BaseFix): - - BM_compatible = True - order = "pre" - - PATTERN = """ - power< 'reduce' - trailer< '(' - arglist< ( - (not(argument) any ',' - not(argument - > - """ - - def transform(self, node, results): - touch_import('functools', 'reduce', node) diff --git a/Lib/lib2to3/fixes/fix_reload.py b/Lib/lib2to3/fixes/fix_reload.py deleted file mode 100644 index b30841131c51f9..00000000000000 --- a/Lib/lib2to3/fixes/fix_reload.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Fixer for reload(). - -reload(s) -> importlib.reload(s)""" - -# Local imports -from .. import fixer_base -from ..fixer_util import ImportAndCall, touch_import - - -class FixReload(fixer_base.BaseFix): - BM_compatible = True - order = "pre" - - PATTERN = """ - power< 'reload' - trailer< lpar='(' - ( not(arglist | argument) any ','> ) - rpar=')' > - after=any* - > - """ - - def transform(self, node, results): - if results: - # I feel like we should be able to express this logic in the - # PATTERN above but I don't know how to do it so... - obj = results['obj'] - if obj: - if (obj.type == self.syms.argument and - obj.children[0].value in {'**', '*'}): - return # Make no change. - names = ('importlib', 'reload') - new = ImportAndCall(node, results, names) - touch_import(None, 'importlib', node) - return new diff --git a/Lib/lib2to3/fixes/fix_renames.py b/Lib/lib2to3/fixes/fix_renames.py deleted file mode 100644 index c0e3705ab7be19..00000000000000 --- a/Lib/lib2to3/fixes/fix_renames.py +++ /dev/null @@ -1,70 +0,0 @@ -"""Fix incompatible renames - -Fixes: - * sys.maxint -> sys.maxsize -""" -# Author: Christian Heimes -# based on Collin Winter's fix_import - -# Local imports -from .. import fixer_base -from ..fixer_util import Name, attr_chain - -MAPPING = {"sys": {"maxint" : "maxsize"}, - } -LOOKUP = {} - -def alternates(members): - return "(" + "|".join(map(repr, members)) + ")" - - -def build_pattern(): - #bare = set() - for module, replace in list(MAPPING.items()): - for old_attr, new_attr in list(replace.items()): - LOOKUP[(module, old_attr)] = new_attr - #bare.add(module) - #bare.add(old_attr) - #yield """ - # import_name< 'import' (module=%r - # | dotted_as_names< any* module=%r any* >) > - # """ % (module, module) - yield """ - import_from< 'from' module_name=%r 'import' - ( attr_name=%r | import_as_name< attr_name=%r 'as' any >) > - """ % (module, old_attr, old_attr) - yield """ - power< module_name=%r trailer< '.' attr_name=%r > any* > - """ % (module, old_attr) - #yield """bare_name=%s""" % alternates(bare) - - -class FixRenames(fixer_base.BaseFix): - BM_compatible = True - PATTERN = "|".join(build_pattern()) - - order = "pre" # Pre-order tree traversal - - # Don't match the node if it's within another match - def match(self, node): - match = super(FixRenames, self).match - results = match(node) - if results: - if any(match(obj) for obj in attr_chain(node, "parent")): - return False - return results - return False - - #def start_tree(self, tree, filename): - # super(FixRenames, self).start_tree(tree, filename) - # self.replace = {} - - def transform(self, node, results): - mod_name = results.get("module_name") - attr_name = results.get("attr_name") - #bare_name = results.get("bare_name") - #import_mod = results.get("module") - - if mod_name and attr_name: - new_attr = LOOKUP[(mod_name.value, attr_name.value)] - attr_name.replace(Name(new_attr, prefix=attr_name.prefix)) diff --git a/Lib/lib2to3/fixes/fix_repr.py b/Lib/lib2to3/fixes/fix_repr.py deleted file mode 100644 index 1150bb8b9db2af..00000000000000 --- a/Lib/lib2to3/fixes/fix_repr.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that transforms `xyzzy` into repr(xyzzy).""" - -# Local imports -from .. import fixer_base -from ..fixer_util import Call, Name, parenthesize - - -class FixRepr(fixer_base.BaseFix): - - BM_compatible = True - PATTERN = """ - atom < '`' expr=any '`' > - """ - - def transform(self, node, results): - expr = results["expr"].clone() - - if expr.type == self.syms.testlist1: - expr = parenthesize(expr) - return Call(Name("repr"), [expr], prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_set_literal.py b/Lib/lib2to3/fixes/fix_set_literal.py deleted file mode 100644 index 762550cf73dc0b..00000000000000 --- a/Lib/lib2to3/fixes/fix_set_literal.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Optional fixer to transform set() calls to set literals. -""" - -# Author: Benjamin Peterson - -from lib2to3 import fixer_base, pytree -from lib2to3.fixer_util import token, syms - - - -class FixSetLiteral(fixer_base.BaseFix): - - BM_compatible = True - explicit = True - - PATTERN = """power< 'set' trailer< '(' - (atom=atom< '[' (items=listmaker< any ((',' any)* [',']) > - | - single=any) ']' > - | - atom< '(' items=testlist_gexp< any ((',' any)* [',']) > ')' > - ) - ')' > > - """ - - def transform(self, node, results): - single = results.get("single") - if single: - # Make a fake listmaker - fake = pytree.Node(syms.listmaker, [single.clone()]) - single.replace(fake) - items = fake - else: - items = results["items"] - - # Build the contents of the literal - literal = [pytree.Leaf(token.LBRACE, "{")] - literal.extend(n.clone() for n in items.children) - literal.append(pytree.Leaf(token.RBRACE, "}")) - # Set the prefix of the right brace to that of the ')' or ']' - literal[-1].prefix = items.next_sibling.prefix - maker = pytree.Node(syms.dictsetmaker, literal) - maker.prefix = node.prefix - - # If the original was a one tuple, we need to remove the extra comma. - if len(maker.children) == 4: - n = maker.children[2] - n.remove() - maker.children[-1].prefix = n.prefix - - # Finally, replace the set call with our shiny new literal. - return maker diff --git a/Lib/lib2to3/fixes/fix_standarderror.py b/Lib/lib2to3/fixes/fix_standarderror.py deleted file mode 100644 index dc742167e6e9d4..00000000000000 --- a/Lib/lib2to3/fixes/fix_standarderror.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for StandardError -> Exception.""" - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - - -class FixStandarderror(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - 'StandardError' - """ - - def transform(self, node, results): - return Name("Exception", prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_sys_exc.py b/Lib/lib2to3/fixes/fix_sys_exc.py deleted file mode 100644 index f6039690374ab2..00000000000000 --- a/Lib/lib2to3/fixes/fix_sys_exc.py +++ /dev/null @@ -1,30 +0,0 @@ -"""Fixer for sys.exc_{type, value, traceback} - -sys.exc_type -> sys.exc_info()[0] -sys.exc_value -> sys.exc_info()[1] -sys.exc_traceback -> sys.exc_info()[2] -""" - -# By Jeff Balogh and Benjamin Peterson - -# Local imports -from .. import fixer_base -from ..fixer_util import Attr, Call, Name, Number, Subscript, Node, syms - -class FixSysExc(fixer_base.BaseFix): - # This order matches the ordering of sys.exc_info(). - exc_info = ["exc_type", "exc_value", "exc_traceback"] - BM_compatible = True - PATTERN = """ - power< 'sys' trailer< dot='.' attribute=(%s) > > - """ % '|'.join("'%s'" % e for e in exc_info) - - def transform(self, node, results): - sys_attr = results["attribute"][0] - index = Number(self.exc_info.index(sys_attr.value)) - - call = Call(Name("exc_info"), prefix=sys_attr.prefix) - attr = Attr(Name("sys"), call) - attr[1].children[0].prefix = results["dot"].prefix - attr.append(Subscript(index)) - return Node(syms.power, attr, prefix=node.prefix) diff --git a/Lib/lib2to3/fixes/fix_throw.py b/Lib/lib2to3/fixes/fix_throw.py deleted file mode 100644 index aac29169b4e98e..00000000000000 --- a/Lib/lib2to3/fixes/fix_throw.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Fixer for generator.throw(E, V, T). - -g.throw(E) -> g.throw(E) -g.throw(E, V) -> g.throw(E(V)) -g.throw(E, V, T) -> g.throw(E(V).with_traceback(T)) - -g.throw("foo"[, V[, T]]) will warn about string exceptions.""" -# Author: Collin Winter - -# Local imports -from .. import pytree -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Name, Call, ArgList, Attr, is_tuple - -class FixThrow(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - power< any trailer< '.' 'throw' > - trailer< '(' args=arglist< exc=any ',' val=any [',' tb=any] > ')' > - > - | - power< any trailer< '.' 'throw' > trailer< '(' exc=any ')' > > - """ - - def transform(self, node, results): - syms = self.syms - - exc = results["exc"].clone() - if exc.type is token.STRING: - self.cannot_convert(node, "Python 3 does not support string exceptions") - return - - # Leave "g.throw(E)" alone - val = results.get("val") - if val is None: - return - - val = val.clone() - if is_tuple(val): - args = [c.clone() for c in val.children[1:-1]] - else: - val.prefix = "" - args = [val] - - throw_args = results["args"] - - if "tb" in results: - tb = results["tb"].clone() - tb.prefix = "" - - e = Call(exc, args) - with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])] - throw_args.replace(pytree.Node(syms.power, with_tb)) - else: - throw_args.replace(Call(exc, args)) diff --git a/Lib/lib2to3/fixes/fix_tuple_params.py b/Lib/lib2to3/fixes/fix_tuple_params.py deleted file mode 100644 index cad755ffdbefb3..00000000000000 --- a/Lib/lib2to3/fixes/fix_tuple_params.py +++ /dev/null @@ -1,175 +0,0 @@ -"""Fixer for function definitions with tuple parameters. - -def func(((a, b), c), d): - ... - - -> - -def func(x, d): - ((a, b), c) = x - ... - -It will also support lambdas: - - lambda (x, y): x + y -> lambda t: t[0] + t[1] - - # The parens are a syntax error in Python 3 - lambda (x): x + y -> lambda x: x + y -""" -# Author: Collin Winter - -# Local imports -from .. import pytree -from ..pgen2 import token -from .. import fixer_base -from ..fixer_util import Assign, Name, Newline, Number, Subscript, syms - -def is_docstring(stmt): - return isinstance(stmt, pytree.Node) and \ - stmt.children[0].type == token.STRING - -class FixTupleParams(fixer_base.BaseFix): - run_order = 4 #use a lower order since lambda is part of other - #patterns - BM_compatible = True - - PATTERN = """ - funcdef< 'def' any parameters< '(' args=any ')' > - ['->' any] ':' suite=any+ > - | - lambda= - lambdef< 'lambda' args=vfpdef< '(' inner=any ')' > - ':' body=any - > - """ - - def transform(self, node, results): - if "lambda" in results: - return self.transform_lambda(node, results) - - new_lines = [] - suite = results["suite"] - args = results["args"] - # This crap is so "def foo(...): x = 5; y = 7" is handled correctly. - # TODO(cwinter): suite-cleanup - if suite[0].children[1].type == token.INDENT: - start = 2 - indent = suite[0].children[1].value - end = Newline() - else: - start = 0 - indent = "; " - end = pytree.Leaf(token.INDENT, "") - - # We need access to self for new_name(), and making this a method - # doesn't feel right. Closing over self and new_lines makes the - # code below cleaner. - def handle_tuple(tuple_arg, add_prefix=False): - n = Name(self.new_name()) - arg = tuple_arg.clone() - arg.prefix = "" - stmt = Assign(arg, n.clone()) - if add_prefix: - n.prefix = " " - tuple_arg.replace(n) - new_lines.append(pytree.Node(syms.simple_stmt, - [stmt, end.clone()])) - - if args.type == syms.tfpdef: - handle_tuple(args) - elif args.type == syms.typedargslist: - for i, arg in enumerate(args.children): - if arg.type == syms.tfpdef: - # Without add_prefix, the emitted code is correct, - # just ugly. - handle_tuple(arg, add_prefix=(i > 0)) - - if not new_lines: - return - - # This isn't strictly necessary, but it plays nicely with other fixers. - # TODO(cwinter) get rid of this when children becomes a smart list - for line in new_lines: - line.parent = suite[0] - - # TODO(cwinter) suite-cleanup - after = start - if start == 0: - new_lines[0].prefix = " " - elif is_docstring(suite[0].children[start]): - new_lines[0].prefix = indent - after = start + 1 - - for line in new_lines: - line.parent = suite[0] - suite[0].children[after:after] = new_lines - for i in range(after+1, after+len(new_lines)+1): - suite[0].children[i].prefix = indent - suite[0].changed() - - def transform_lambda(self, node, results): - args = results["args"] - body = results["body"] - inner = simplify_args(results["inner"]) - - # Replace lambda ((((x)))): x with lambda x: x - if inner.type == token.NAME: - inner = inner.clone() - inner.prefix = " " - args.replace(inner) - return - - params = find_params(args) - to_index = map_to_index(params) - tup_name = self.new_name(tuple_name(params)) - - new_param = Name(tup_name, prefix=" ") - args.replace(new_param.clone()) - for n in body.post_order(): - if n.type == token.NAME and n.value in to_index: - subscripts = [c.clone() for c in to_index[n.value]] - new = pytree.Node(syms.power, - [new_param.clone()] + subscripts) - new.prefix = n.prefix - n.replace(new) - - -### Helper functions for transform_lambda() - -def simplify_args(node): - if node.type in (syms.vfplist, token.NAME): - return node - elif node.type == syms.vfpdef: - # These look like vfpdef< '(' x ')' > where x is NAME - # or another vfpdef instance (leading to recursion). - while node.type == syms.vfpdef: - node = node.children[1] - return node - raise RuntimeError("Received unexpected node %s" % node) - -def find_params(node): - if node.type == syms.vfpdef: - return find_params(node.children[1]) - elif node.type == token.NAME: - return node.value - return [find_params(c) for c in node.children if c.type != token.COMMA] - -def map_to_index(param_list, prefix=[], d=None): - if d is None: - d = {} - for i, obj in enumerate(param_list): - trailer = [Subscript(Number(str(i)))] - if isinstance(obj, list): - map_to_index(obj, trailer, d=d) - else: - d[obj] = prefix + trailer - return d - -def tuple_name(param_list): - l = [] - for obj in param_list: - if isinstance(obj, list): - l.append(tuple_name(obj)) - else: - l.append(obj) - return "_".join(l) diff --git a/Lib/lib2to3/fixes/fix_types.py b/Lib/lib2to3/fixes/fix_types.py deleted file mode 100644 index 67bf51f2f5b85a..00000000000000 --- a/Lib/lib2to3/fixes/fix_types.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer for removing uses of the types module. - -These work for only the known names in the types module. The forms above -can include types. or not. ie, It is assumed the module is imported either as: - - import types - from types import ... # either * or specific types - -The import statements are not modified. - -There should be another fixer that handles at least the following constants: - - type([]) -> list - type(()) -> tuple - type('') -> str - -""" - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - -_TYPE_MAPPING = { - 'BooleanType' : 'bool', - 'BufferType' : 'memoryview', - 'ClassType' : 'type', - 'ComplexType' : 'complex', - 'DictType': 'dict', - 'DictionaryType' : 'dict', - 'EllipsisType' : 'type(Ellipsis)', - #'FileType' : 'io.IOBase', - 'FloatType': 'float', - 'IntType': 'int', - 'ListType': 'list', - 'LongType': 'int', - 'ObjectType' : 'object', - 'NoneType': 'type(None)', - 'NotImplementedType' : 'type(NotImplemented)', - 'SliceType' : 'slice', - 'StringType': 'bytes', # XXX ? - 'StringTypes' : '(str,)', # XXX ? - 'TupleType': 'tuple', - 'TypeType' : 'type', - 'UnicodeType': 'str', - 'XRangeType' : 'range', - } - -_pats = ["power< 'types' trailer< '.' name='%s' > >" % t for t in _TYPE_MAPPING] - -class FixTypes(fixer_base.BaseFix): - BM_compatible = True - PATTERN = '|'.join(_pats) - - def transform(self, node, results): - new_value = _TYPE_MAPPING.get(results["name"].value) - if new_value: - return Name(new_value, prefix=node.prefix) - return None diff --git a/Lib/lib2to3/fixes/fix_unicode.py b/Lib/lib2to3/fixes/fix_unicode.py deleted file mode 100644 index c7982c2b97c3e1..00000000000000 --- a/Lib/lib2to3/fixes/fix_unicode.py +++ /dev/null @@ -1,42 +0,0 @@ -r"""Fixer for unicode. - -* Changes unicode to str and unichr to chr. - -* If "...\u..." is not unicode literal change it into "...\\u...". - -* Change u"..." into "...". - -""" - -from ..pgen2 import token -from .. import fixer_base - -_mapping = {"unichr" : "chr", "unicode" : "str"} - -class FixUnicode(fixer_base.BaseFix): - BM_compatible = True - PATTERN = "STRING | 'unicode' | 'unichr'" - - def start_tree(self, tree, filename): - super(FixUnicode, self).start_tree(tree, filename) - self.unicode_literals = 'unicode_literals' in tree.future_features - - def transform(self, node, results): - if node.type == token.NAME: - new = node.clone() - new.value = _mapping[node.value] - return new - elif node.type == token.STRING: - val = node.value - if not self.unicode_literals and val[0] in '\'"' and '\\' in val: - val = r'\\'.join([ - v.replace('\\u', r'\\u').replace('\\U', r'\\U') - for v in val.split(r'\\') - ]) - if val[0] in 'uU': - val = val[1:] - if val == node.value: - return node - new = node.clone() - new.value = val - return new diff --git a/Lib/lib2to3/fixes/fix_urllib.py b/Lib/lib2to3/fixes/fix_urllib.py deleted file mode 100644 index ab892bc52494c2..00000000000000 --- a/Lib/lib2to3/fixes/fix_urllib.py +++ /dev/null @@ -1,196 +0,0 @@ -"""Fix changes imports of urllib which are now incompatible. - This is rather similar to fix_imports, but because of the more - complex nature of the fixing for urllib, it has its own fixer. -""" -# Author: Nick Edds - -# Local imports -from lib2to3.fixes.fix_imports import alternates, FixImports -from lib2to3.fixer_util import (Name, Comma, FromImport, Newline, - find_indentation, Node, syms) - -MAPPING = {"urllib": [ - ("urllib.request", - ["URLopener", "FancyURLopener", "urlretrieve", - "_urlopener", "urlopen", "urlcleanup", - "pathname2url", "url2pathname", "getproxies"]), - ("urllib.parse", - ["quote", "quote_plus", "unquote", "unquote_plus", - "urlencode", "splitattr", "splithost", "splitnport", - "splitpasswd", "splitport", "splitquery", "splittag", - "splittype", "splituser", "splitvalue", ]), - ("urllib.error", - ["ContentTooShortError"])], - "urllib2" : [ - ("urllib.request", - ["urlopen", "install_opener", "build_opener", - "Request", "OpenerDirector", "BaseHandler", - "HTTPDefaultErrorHandler", "HTTPRedirectHandler", - "HTTPCookieProcessor", "ProxyHandler", - "HTTPPasswordMgr", - "HTTPPasswordMgrWithDefaultRealm", - "AbstractBasicAuthHandler", - "HTTPBasicAuthHandler", "ProxyBasicAuthHandler", - "AbstractDigestAuthHandler", - "HTTPDigestAuthHandler", "ProxyDigestAuthHandler", - "HTTPHandler", "HTTPSHandler", "FileHandler", - "FTPHandler", "CacheFTPHandler", - "UnknownHandler"]), - ("urllib.error", - ["URLError", "HTTPError"]), - ] -} - -# Duplicate the url parsing functions for urllib2. -MAPPING["urllib2"].append(MAPPING["urllib"][1]) - - -def build_pattern(): - bare = set() - for old_module, changes in MAPPING.items(): - for change in changes: - new_module, members = change - members = alternates(members) - yield """import_name< 'import' (module=%r - | dotted_as_names< any* module=%r any* >) > - """ % (old_module, old_module) - yield """import_from< 'from' mod_member=%r 'import' - ( member=%s | import_as_name< member=%s 'as' any > | - import_as_names< members=any* >) > - """ % (old_module, members, members) - yield """import_from< 'from' module_star=%r 'import' star='*' > - """ % old_module - yield """import_name< 'import' - dotted_as_name< module_as=%r 'as' any > > - """ % old_module - # bare_with_attr has a special significance for FixImports.match(). - yield """power< bare_with_attr=%r trailer< '.' member=%s > any* > - """ % (old_module, members) - - -class FixUrllib(FixImports): - - def build_pattern(self): - return "|".join(build_pattern()) - - def transform_import(self, node, results): - """Transform for the basic import case. Replaces the old - import name with a comma separated list of its - replacements. - """ - import_mod = results.get("module") - pref = import_mod.prefix - - names = [] - - # create a Node list of the replacement modules - for name in MAPPING[import_mod.value][:-1]: - names.extend([Name(name[0], prefix=pref), Comma()]) - names.append(Name(MAPPING[import_mod.value][-1][0], prefix=pref)) - import_mod.replace(names) - - def transform_member(self, node, results): - """Transform for imports of specific module elements. Replaces - the module to be imported from with the appropriate new - module. - """ - mod_member = results.get("mod_member") - pref = mod_member.prefix - member = results.get("member") - - # Simple case with only a single member being imported - if member: - # this may be a list of length one, or just a node - if isinstance(member, list): - member = member[0] - new_name = None - for change in MAPPING[mod_member.value]: - if member.value in change[1]: - new_name = change[0] - break - if new_name: - mod_member.replace(Name(new_name, prefix=pref)) - else: - self.cannot_convert(node, "This is an invalid module element") - - # Multiple members being imported - else: - # a dictionary for replacements, order matters - modules = [] - mod_dict = {} - members = results["members"] - for member in members: - # we only care about the actual members - if member.type == syms.import_as_name: - as_name = member.children[2].value - member_name = member.children[0].value - else: - member_name = member.value - as_name = None - if member_name != ",": - for change in MAPPING[mod_member.value]: - if member_name in change[1]: - if change[0] not in mod_dict: - modules.append(change[0]) - mod_dict.setdefault(change[0], []).append(member) - - new_nodes = [] - indentation = find_indentation(node) - first = True - def handle_name(name, prefix): - if name.type == syms.import_as_name: - kids = [Name(name.children[0].value, prefix=prefix), - name.children[1].clone(), - name.children[2].clone()] - return [Node(syms.import_as_name, kids)] - return [Name(name.value, prefix=prefix)] - for module in modules: - elts = mod_dict[module] - names = [] - for elt in elts[:-1]: - names.extend(handle_name(elt, pref)) - names.append(Comma()) - names.extend(handle_name(elts[-1], pref)) - new = FromImport(module, names) - if not first or node.parent.prefix.endswith(indentation): - new.prefix = indentation - new_nodes.append(new) - first = False - if new_nodes: - nodes = [] - for new_node in new_nodes[:-1]: - nodes.extend([new_node, Newline()]) - nodes.append(new_nodes[-1]) - node.replace(nodes) - else: - self.cannot_convert(node, "All module elements are invalid") - - def transform_dot(self, node, results): - """Transform for calls to module members in code.""" - module_dot = results.get("bare_with_attr") - member = results.get("member") - new_name = None - if isinstance(member, list): - member = member[0] - for change in MAPPING[module_dot.value]: - if member.value in change[1]: - new_name = change[0] - break - if new_name: - module_dot.replace(Name(new_name, - prefix=module_dot.prefix)) - else: - self.cannot_convert(node, "This is an invalid module element") - - def transform(self, node, results): - if results.get("module"): - self.transform_import(node, results) - elif results.get("mod_member"): - self.transform_member(node, results) - elif results.get("bare_with_attr"): - self.transform_dot(node, results) - # Renaming and star imports are not supported for these modules. - elif results.get("module_star"): - self.cannot_convert(node, "Cannot handle star imports.") - elif results.get("module_as"): - self.cannot_convert(node, "This module is now multiple modules") diff --git a/Lib/lib2to3/fixes/fix_ws_comma.py b/Lib/lib2to3/fixes/fix_ws_comma.py deleted file mode 100644 index a54a376c472afb..00000000000000 --- a/Lib/lib2to3/fixes/fix_ws_comma.py +++ /dev/null @@ -1,39 +0,0 @@ -"""Fixer that changes 'a ,b' into 'a, b'. - -This also changes '{a :b}' into '{a: b}', but does not touch other -uses of colons. It does not touch other uses of whitespace. - -""" - -from .. import pytree -from ..pgen2 import token -from .. import fixer_base - -class FixWsComma(fixer_base.BaseFix): - - explicit = True # The user must ask for this fixers - - PATTERN = """ - any<(not(',') any)+ ',' ((not(',') any)+ ',')* [not(',') any]> - """ - - COMMA = pytree.Leaf(token.COMMA, ",") - COLON = pytree.Leaf(token.COLON, ":") - SEPS = (COMMA, COLON) - - def transform(self, node, results): - new = node.clone() - comma = False - for child in new.children: - if child in self.SEPS: - prefix = child.prefix - if prefix.isspace() and "\n" not in prefix: - child.prefix = "" - comma = True - else: - if comma: - prefix = child.prefix - if not prefix: - child.prefix = " " - comma = False - return new diff --git a/Lib/lib2to3/fixes/fix_xrange.py b/Lib/lib2to3/fixes/fix_xrange.py deleted file mode 100644 index 1e491e166a3f1c..00000000000000 --- a/Lib/lib2to3/fixes/fix_xrange.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2007 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Fixer that changes xrange(...) into range(...).""" - -# Local imports -from .. import fixer_base -from ..fixer_util import Name, Call, consuming_calls -from .. import patcomp - - -class FixXrange(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - power< - (name='range'|name='xrange') trailer< '(' args=any ')' > - rest=any* > - """ - - def start_tree(self, tree, filename): - super(FixXrange, self).start_tree(tree, filename) - self.transformed_xranges = set() - - def finish_tree(self, tree, filename): - self.transformed_xranges = None - - def transform(self, node, results): - name = results["name"] - if name.value == "xrange": - return self.transform_xrange(node, results) - elif name.value == "range": - return self.transform_range(node, results) - else: - raise ValueError(repr(name)) - - def transform_xrange(self, node, results): - name = results["name"] - name.replace(Name("range", prefix=name.prefix)) - # This prevents the new range call from being wrapped in a list later. - self.transformed_xranges.add(id(node)) - - def transform_range(self, node, results): - if (id(node) not in self.transformed_xranges and - not self.in_special_context(node)): - range_call = Call(Name("range"), [results["args"].clone()]) - # Encase the range call in list(). - list_call = Call(Name("list"), [range_call], - prefix=node.prefix) - # Put things that were after the range() call after the list call. - for n in results["rest"]: - list_call.append_child(n) - return list_call - - P1 = "power< func=NAME trailer< '(' node=any ')' > any* >" - p1 = patcomp.compile_pattern(P1) - - P2 = """for_stmt< 'for' any 'in' node=any ':' any* > - | comp_for< 'for' any 'in' node=any any* > - | comparison< any 'in' node=any any*> - """ - p2 = patcomp.compile_pattern(P2) - - def in_special_context(self, node): - if node.parent is None: - return False - results = {} - if (node.parent.parent is not None and - self.p1.match(node.parent.parent, results) and - results["node"] is node): - # list(d.keys()) -> list(d.keys()), etc. - return results["func"].value in consuming_calls - # for ... in d.iterkeys() -> for ... in d.keys(), etc. - return self.p2.match(node.parent, results) and results["node"] is node diff --git a/Lib/lib2to3/fixes/fix_xreadlines.py b/Lib/lib2to3/fixes/fix_xreadlines.py deleted file mode 100644 index 3e3f71ab045573..00000000000000 --- a/Lib/lib2to3/fixes/fix_xreadlines.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Fix "for x in f.xreadlines()" -> "for x in f". - -This fixer will also convert g(f.xreadlines) into g(f.__iter__).""" -# Author: Collin Winter - -# Local imports -from .. import fixer_base -from ..fixer_util import Name - - -class FixXreadlines(fixer_base.BaseFix): - BM_compatible = True - PATTERN = """ - power< call=any+ trailer< '.' 'xreadlines' > trailer< '(' ')' > > - | - power< any+ trailer< '.' no_call='xreadlines' > > - """ - - def transform(self, node, results): - no_call = results.get("no_call") - - if no_call: - no_call.replace(Name("__iter__", prefix=no_call.prefix)) - else: - node.replace([x.clone() for x in results["call"]]) diff --git a/Lib/lib2to3/fixes/fix_zip.py b/Lib/lib2to3/fixes/fix_zip.py deleted file mode 100644 index 52c28df6aab411..00000000000000 --- a/Lib/lib2to3/fixes/fix_zip.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Fixer that changes zip(seq0, seq1, ...) into list(zip(seq0, seq1, ...) -unless there exists a 'from future_builtins import zip' statement in the -top-level namespace. - -We avoid the transformation if the zip() call is directly contained in -iter(<>), list(<>), tuple(<>), sorted(<>), ...join(<>), or for V in <>:. -""" - -# Local imports -from .. import fixer_base -from ..pytree import Node -from ..pygram import python_symbols as syms -from ..fixer_util import Name, ArgList, in_special_context - - -class FixZip(fixer_base.ConditionalFix): - - BM_compatible = True - PATTERN = """ - power< 'zip' args=trailer< '(' [any] ')' > [trailers=trailer*] - > - """ - - skip_on = "future_builtins.zip" - - def transform(self, node, results): - if self.should_skip(node): - return - - if in_special_context(node): - return None - - args = results['args'].clone() - args.prefix = "" - - trailers = [] - if 'trailers' in results: - trailers = [n.clone() for n in results['trailers']] - for n in trailers: - n.prefix = "" - - new = Node(syms.power, [Name("zip"), args], prefix="") - new = Node(syms.power, [Name("list"), ArgList([new])] + trailers) - new.prefix = node.prefix - return new diff --git a/Lib/lib2to3/main.py b/Lib/lib2to3/main.py deleted file mode 100644 index f2849fd6be3fd9..00000000000000 --- a/Lib/lib2to3/main.py +++ /dev/null @@ -1,273 +0,0 @@ -""" -Main program for 2to3. -""" - -from __future__ import with_statement, print_function - -import sys -import os -import difflib -import logging -import shutil -import optparse - -from . import refactor - - -def diff_texts(a, b, filename): - """Return a unified diff of two strings.""" - a = a.splitlines() - b = b.splitlines() - return difflib.unified_diff(a, b, filename, filename, - "(original)", "(refactored)", - lineterm="") - - -class StdoutRefactoringTool(refactor.MultiprocessRefactoringTool): - """ - A refactoring tool that can avoid overwriting its input files. - Prints output to stdout. - - Output files can optionally be written to a different directory and or - have an extra file suffix appended to their name for use in situations - where you do not want to replace the input files. - """ - - def __init__(self, fixers, options, explicit, nobackups, show_diffs, - input_base_dir='', output_dir='', append_suffix=''): - """ - Args: - fixers: A list of fixers to import. - options: A dict with RefactoringTool configuration. - explicit: A list of fixers to run even if they are explicit. - nobackups: If true no backup '.bak' files will be created for those - files that are being refactored. - show_diffs: Should diffs of the refactoring be printed to stdout? - input_base_dir: The base directory for all input files. This class - will strip this path prefix off of filenames before substituting - it with output_dir. Only meaningful if output_dir is supplied. - All files processed by refactor() must start with this path. - output_dir: If supplied, all converted files will be written into - this directory tree instead of input_base_dir. - append_suffix: If supplied, all files output by this tool will have - this appended to their filename. Useful for changing .py to - .py3 for example by passing append_suffix='3'. - """ - self.nobackups = nobackups - self.show_diffs = show_diffs - if input_base_dir and not input_base_dir.endswith(os.sep): - input_base_dir += os.sep - self._input_base_dir = input_base_dir - self._output_dir = output_dir - self._append_suffix = append_suffix - super(StdoutRefactoringTool, self).__init__(fixers, options, explicit) - - def log_error(self, msg, *args, **kwargs): - self.errors.append((msg, args, kwargs)) - self.logger.error(msg, *args, **kwargs) - - def write_file(self, new_text, filename, old_text, encoding): - orig_filename = filename - if self._output_dir: - if filename.startswith(self._input_base_dir): - filename = os.path.join(self._output_dir, - filename[len(self._input_base_dir):]) - else: - raise ValueError('filename %s does not start with the ' - 'input_base_dir %s' % ( - filename, self._input_base_dir)) - if self._append_suffix: - filename += self._append_suffix - if orig_filename != filename: - output_dir = os.path.dirname(filename) - if not os.path.isdir(output_dir) and output_dir: - os.makedirs(output_dir) - self.log_message('Writing converted %s to %s.', orig_filename, - filename) - if not self.nobackups: - # Make backup - backup = filename + ".bak" - if os.path.lexists(backup): - try: - os.remove(backup) - except OSError: - self.log_message("Can't remove backup %s", backup) - try: - os.rename(filename, backup) - except OSError: - self.log_message("Can't rename %s to %s", filename, backup) - # Actually write the new file - write = super(StdoutRefactoringTool, self).write_file - write(new_text, filename, old_text, encoding) - if not self.nobackups: - shutil.copymode(backup, filename) - if orig_filename != filename: - # Preserve the file mode in the new output directory. - shutil.copymode(orig_filename, filename) - - def print_output(self, old, new, filename, equal): - if equal: - self.log_message("No changes to %s", filename) - else: - self.log_message("Refactored %s", filename) - if self.show_diffs: - diff_lines = diff_texts(old, new, filename) - try: - if self.output_lock is not None: - with self.output_lock: - for line in diff_lines: - print(line) - sys.stdout.flush() - else: - for line in diff_lines: - print(line) - except UnicodeEncodeError: - warn("couldn't encode %s's diff for your terminal" % - (filename,)) - return - -def warn(msg): - print("WARNING: %s" % (msg,), file=sys.stderr) - - -def main(fixer_pkg, args=None): - """Main program. - - Args: - fixer_pkg: the name of a package where the fixers are located. - args: optional; a list of command line arguments. If omitted, - sys.argv[1:] is used. - - Returns a suggested exit status (0, 1, 2). - """ - # Set up option parser - parser = optparse.OptionParser(usage="2to3 [options] file|dir ...") - parser.add_option("-d", "--doctests_only", action="store_true", - help="Fix up doctests only") - parser.add_option("-f", "--fix", action="append", default=[], - help="Each FIX specifies a transformation; default: all") - parser.add_option("-j", "--processes", action="store", default=1, - type="int", help="Run 2to3 concurrently") - parser.add_option("-x", "--nofix", action="append", default=[], - help="Prevent a transformation from being run") - parser.add_option("-l", "--list-fixes", action="store_true", - help="List available transformations") - parser.add_option("-p", "--print-function", action="store_true", - help="Modify the grammar so that print() is a function") - parser.add_option("-e", "--exec-function", action="store_true", - help="Modify the grammar so that exec() is a function") - parser.add_option("-v", "--verbose", action="store_true", - help="More verbose logging") - parser.add_option("--no-diffs", action="store_true", - help="Don't show diffs of the refactoring") - parser.add_option("-w", "--write", action="store_true", - help="Write back modified files") - parser.add_option("-n", "--nobackups", action="store_true", default=False, - help="Don't write backups for modified files") - parser.add_option("-o", "--output-dir", action="store", type="str", - default="", help="Put output files in this directory " - "instead of overwriting the input files. Requires -n.") - parser.add_option("-W", "--write-unchanged-files", action="store_true", - help="Also write files even if no changes were required" - " (useful with --output-dir); implies -w.") - parser.add_option("--add-suffix", action="store", type="str", default="", - help="Append this string to all output filenames." - " Requires -n if non-empty. " - "ex: --add-suffix='3' will generate .py3 files.") - - # Parse command line arguments - refactor_stdin = False - flags = {} - options, args = parser.parse_args(args) - if options.write_unchanged_files: - flags["write_unchanged_files"] = True - if not options.write: - warn("--write-unchanged-files/-W implies -w.") - options.write = True - # If we allowed these, the original files would be renamed to backup names - # but not replaced. - if options.output_dir and not options.nobackups: - parser.error("Can't use --output-dir/-o without -n.") - if options.add_suffix and not options.nobackups: - parser.error("Can't use --add-suffix without -n.") - - if not options.write and options.no_diffs: - warn("not writing files and not printing diffs; that's not very useful") - if not options.write and options.nobackups: - parser.error("Can't use -n without -w") - if options.list_fixes: - print("Available transformations for the -f/--fix option:") - for fixname in refactor.get_all_fix_names(fixer_pkg): - print(fixname) - if not args: - return 0 - if not args: - print("At least one file or directory argument required.", file=sys.stderr) - print("Use --help to show usage.", file=sys.stderr) - return 2 - if "-" in args: - refactor_stdin = True - if options.write: - print("Can't write to stdin.", file=sys.stderr) - return 2 - if options.print_function: - flags["print_function"] = True - - if options.exec_function: - flags["exec_function"] = True - - # Set up logging handler - level = logging.DEBUG if options.verbose else logging.INFO - logging.basicConfig(format='%(name)s: %(message)s', level=level) - logger = logging.getLogger('lib2to3.main') - - # Initialize the refactoring tool - avail_fixes = set(refactor.get_fixers_from_package(fixer_pkg)) - unwanted_fixes = set(fixer_pkg + ".fix_" + fix for fix in options.nofix) - explicit = set() - if options.fix: - all_present = False - for fix in options.fix: - if fix == "all": - all_present = True - else: - explicit.add(fixer_pkg + ".fix_" + fix) - requested = avail_fixes.union(explicit) if all_present else explicit - else: - requested = avail_fixes.union(explicit) - fixer_names = requested.difference(unwanted_fixes) - input_base_dir = os.path.commonprefix(args) - if (input_base_dir and not input_base_dir.endswith(os.sep) - and not os.path.isdir(input_base_dir)): - # One or more similar names were passed, their directory is the base. - # os.path.commonprefix() is ignorant of path elements, this corrects - # for that weird API. - input_base_dir = os.path.dirname(input_base_dir) - if options.output_dir: - input_base_dir = input_base_dir.rstrip(os.sep) - logger.info('Output in %r will mirror the input directory %r layout.', - options.output_dir, input_base_dir) - rt = StdoutRefactoringTool( - sorted(fixer_names), flags, sorted(explicit), - options.nobackups, not options.no_diffs, - input_base_dir=input_base_dir, - output_dir=options.output_dir, - append_suffix=options.add_suffix) - - # Refactor all files and directories passed as arguments - if not rt.errors: - if refactor_stdin: - rt.refactor_stdin() - else: - try: - rt.refactor(args, options.write, options.doctests_only, - options.processes) - except refactor.MultiprocessingUnsupported: - assert options.processes > 1 - print("Sorry, -j isn't supported on this platform.", - file=sys.stderr) - return 1 - rt.summarize() - - # Return error status (0 if rt.errors is zero) - return int(bool(rt.errors)) diff --git a/Lib/lib2to3/patcomp.py b/Lib/lib2to3/patcomp.py deleted file mode 100644 index f57f4954b26ce7..00000000000000 --- a/Lib/lib2to3/patcomp.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Pattern compiler. - -The grammar is taken from PatternGrammar.txt. - -The compiler compiles a pattern to a pytree.*Pattern instance. -""" - -__author__ = "Guido van Rossum " - -# Python imports -import io - -# Fairly local imports -from .pgen2 import driver, literals, token, tokenize, parse, grammar - -# Really local imports -from . import pytree -from . import pygram - - -class PatternSyntaxError(Exception): - pass - - -def tokenize_wrapper(input): - """Tokenizes a string suppressing significant whitespace.""" - skip = {token.NEWLINE, token.INDENT, token.DEDENT} - tokens = tokenize.generate_tokens(io.StringIO(input).readline) - for quintuple in tokens: - type, value, start, end, line_text = quintuple - if type not in skip: - yield quintuple - - -class PatternCompiler(object): - - def __init__(self, grammar_file=None): - """Initializer. - - Takes an optional alternative filename for the pattern grammar. - """ - if grammar_file is None: - self.grammar = pygram.pattern_grammar - self.syms = pygram.pattern_symbols - else: - self.grammar = driver.load_grammar(grammar_file) - self.syms = pygram.Symbols(self.grammar) - self.pygrammar = pygram.python_grammar - self.pysyms = pygram.python_symbols - self.driver = driver.Driver(self.grammar, convert=pattern_convert) - - def compile_pattern(self, input, debug=False, with_tree=False): - """Compiles a pattern string to a nested pytree.*Pattern object.""" - tokens = tokenize_wrapper(input) - try: - root = self.driver.parse_tokens(tokens, debug=debug) - except parse.ParseError as e: - raise PatternSyntaxError(str(e)) from None - if with_tree: - return self.compile_node(root), root - else: - return self.compile_node(root) - - def compile_node(self, node): - """Compiles a node, recursively. - - This is one big switch on the node type. - """ - # XXX Optimize certain Wildcard-containing-Wildcard patterns - # that can be merged - if node.type == self.syms.Matcher: - node = node.children[0] # Avoid unneeded recursion - - if node.type == self.syms.Alternatives: - # Skip the odd children since they are just '|' tokens - alts = [self.compile_node(ch) for ch in node.children[::2]] - if len(alts) == 1: - return alts[0] - p = pytree.WildcardPattern([[a] for a in alts], min=1, max=1) - return p.optimize() - - if node.type == self.syms.Alternative: - units = [self.compile_node(ch) for ch in node.children] - if len(units) == 1: - return units[0] - p = pytree.WildcardPattern([units], min=1, max=1) - return p.optimize() - - if node.type == self.syms.NegatedUnit: - pattern = self.compile_basic(node.children[1:]) - p = pytree.NegatedPattern(pattern) - return p.optimize() - - assert node.type == self.syms.Unit - - name = None - nodes = node.children - if len(nodes) >= 3 and nodes[1].type == token.EQUAL: - name = nodes[0].value - nodes = nodes[2:] - repeat = None - if len(nodes) >= 2 and nodes[-1].type == self.syms.Repeater: - repeat = nodes[-1] - nodes = nodes[:-1] - - # Now we've reduced it to: STRING | NAME [Details] | (...) | [...] - pattern = self.compile_basic(nodes, repeat) - - if repeat is not None: - assert repeat.type == self.syms.Repeater - children = repeat.children - child = children[0] - if child.type == token.STAR: - min = 0 - max = pytree.HUGE - elif child.type == token.PLUS: - min = 1 - max = pytree.HUGE - elif child.type == token.LBRACE: - assert children[-1].type == token.RBRACE - assert len(children) in (3, 5) - min = max = self.get_int(children[1]) - if len(children) == 5: - max = self.get_int(children[3]) - else: - assert False - if min != 1 or max != 1: - pattern = pattern.optimize() - pattern = pytree.WildcardPattern([[pattern]], min=min, max=max) - - if name is not None: - pattern.name = name - return pattern.optimize() - - def compile_basic(self, nodes, repeat=None): - # Compile STRING | NAME [Details] | (...) | [...] - assert len(nodes) >= 1 - node = nodes[0] - if node.type == token.STRING: - value = str(literals.evalString(node.value)) - return pytree.LeafPattern(_type_of_literal(value), value) - elif node.type == token.NAME: - value = node.value - if value.isupper(): - if value not in TOKEN_MAP: - raise PatternSyntaxError("Invalid token: %r" % value) - if nodes[1:]: - raise PatternSyntaxError("Can't have details for token") - return pytree.LeafPattern(TOKEN_MAP[value]) - else: - if value == "any": - type = None - elif not value.startswith("_"): - type = getattr(self.pysyms, value, None) - if type is None: - raise PatternSyntaxError("Invalid symbol: %r" % value) - if nodes[1:]: # Details present - content = [self.compile_node(nodes[1].children[1])] - else: - content = None - return pytree.NodePattern(type, content) - elif node.value == "(": - return self.compile_node(nodes[1]) - elif node.value == "[": - assert repeat is None - subpattern = self.compile_node(nodes[1]) - return pytree.WildcardPattern([[subpattern]], min=0, max=1) - assert False, node - - def get_int(self, node): - assert node.type == token.NUMBER - return int(node.value) - - -# Map named tokens to the type value for a LeafPattern -TOKEN_MAP = {"NAME": token.NAME, - "STRING": token.STRING, - "NUMBER": token.NUMBER, - "TOKEN": None} - - -def _type_of_literal(value): - if value[0].isalpha(): - return token.NAME - elif value in grammar.opmap: - return grammar.opmap[value] - else: - return None - - -def pattern_convert(grammar, raw_node_info): - """Converts raw node information to a Node or Leaf instance.""" - type, value, context, children = raw_node_info - if children or type in grammar.number2symbol: - return pytree.Node(type, children, context=context) - else: - return pytree.Leaf(type, value, context=context) - - -def compile_pattern(pattern): - return PatternCompiler().compile_pattern(pattern) diff --git a/Lib/lib2to3/pgen2/__init__.py b/Lib/lib2to3/pgen2/__init__.py deleted file mode 100644 index af390484528d87..00000000000000 --- a/Lib/lib2to3/pgen2/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""The pgen2 package.""" diff --git a/Lib/lib2to3/pgen2/conv.py b/Lib/lib2to3/pgen2/conv.py deleted file mode 100644 index ed0cac532e4249..00000000000000 --- a/Lib/lib2to3/pgen2/conv.py +++ /dev/null @@ -1,257 +0,0 @@ -# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Convert graminit.[ch] spit out by pgen to Python code. - -Pgen is the Python parser generator. It is useful to quickly create a -parser from a grammar file in Python's grammar notation. But I don't -want my parsers to be written in C (yet), so I'm translating the -parsing tables to Python data structures and writing a Python parse -engine. - -Note that the token numbers are constants determined by the standard -Python tokenizer. The standard token module defines these numbers and -their names (the names are not used much). The token numbers are -hardcoded into the Python tokenizer and into pgen. A Python -implementation of the Python tokenizer is also available, in the -standard tokenize module. - -On the other hand, symbol numbers (representing the grammar's -non-terminals) are assigned by pgen based on the actual grammar -input. - -Note: this module is pretty much obsolete; the pgen module generates -equivalent grammar tables directly from the Grammar.txt input file -without having to invoke the Python pgen C program. - -""" - -# Python imports -import re - -# Local imports -from pgen2 import grammar, token - - -class Converter(grammar.Grammar): - """Grammar subclass that reads classic pgen output files. - - The run() method reads the tables as produced by the pgen parser - generator, typically contained in two C files, graminit.h and - graminit.c. The other methods are for internal use only. - - See the base class for more documentation. - - """ - - def run(self, graminit_h, graminit_c): - """Load the grammar tables from the text files written by pgen.""" - self.parse_graminit_h(graminit_h) - self.parse_graminit_c(graminit_c) - self.finish_off() - - def parse_graminit_h(self, filename): - """Parse the .h file written by pgen. (Internal) - - This file is a sequence of #define statements defining the - nonterminals of the grammar as numbers. We build two tables - mapping the numbers to names and back. - - """ - try: - f = open(filename) - except OSError as err: - print("Can't open %s: %s" % (filename, err)) - return False - self.symbol2number = {} - self.number2symbol = {} - lineno = 0 - for line in f: - lineno += 1 - mo = re.match(r"^#define\s+(\w+)\s+(\d+)$", line) - if not mo and line.strip(): - print("%s(%s): can't parse %s" % (filename, lineno, - line.strip())) - else: - symbol, number = mo.groups() - number = int(number) - assert symbol not in self.symbol2number - assert number not in self.number2symbol - self.symbol2number[symbol] = number - self.number2symbol[number] = symbol - return True - - def parse_graminit_c(self, filename): - """Parse the .c file written by pgen. (Internal) - - The file looks as follows. The first two lines are always this: - - #include "pgenheaders.h" - #include "grammar.h" - - After that come four blocks: - - 1) one or more state definitions - 2) a table defining dfas - 3) a table defining labels - 4) a struct defining the grammar - - A state definition has the following form: - - one or more arc arrays, each of the form: - static arc arcs__[] = { - {, }, - ... - }; - - followed by a state array, of the form: - static state states_[] = { - {, arcs__}, - ... - }; - - """ - try: - f = open(filename) - except OSError as err: - print("Can't open %s: %s" % (filename, err)) - return False - # The code below essentially uses f's iterator-ness! - lineno = 0 - - # Expect the two #include lines - lineno, line = lineno+1, next(f) - assert line == '#include "pgenheaders.h"\n', (lineno, line) - lineno, line = lineno+1, next(f) - assert line == '#include "grammar.h"\n', (lineno, line) - - # Parse the state definitions - lineno, line = lineno+1, next(f) - allarcs = {} - states = [] - while line.startswith("static arc "): - while line.startswith("static arc "): - mo = re.match(r"static arc arcs_(\d+)_(\d+)\[(\d+)\] = {$", - line) - assert mo, (lineno, line) - n, m, k = list(map(int, mo.groups())) - arcs = [] - for _ in range(k): - lineno, line = lineno+1, next(f) - mo = re.match(r"\s+{(\d+), (\d+)},$", line) - assert mo, (lineno, line) - i, j = list(map(int, mo.groups())) - arcs.append((i, j)) - lineno, line = lineno+1, next(f) - assert line == "};\n", (lineno, line) - allarcs[(n, m)] = arcs - lineno, line = lineno+1, next(f) - mo = re.match(r"static state states_(\d+)\[(\d+)\] = {$", line) - assert mo, (lineno, line) - s, t = list(map(int, mo.groups())) - assert s == len(states), (lineno, line) - state = [] - for _ in range(t): - lineno, line = lineno+1, next(f) - mo = re.match(r"\s+{(\d+), arcs_(\d+)_(\d+)},$", line) - assert mo, (lineno, line) - k, n, m = list(map(int, mo.groups())) - arcs = allarcs[n, m] - assert k == len(arcs), (lineno, line) - state.append(arcs) - states.append(state) - lineno, line = lineno+1, next(f) - assert line == "};\n", (lineno, line) - lineno, line = lineno+1, next(f) - self.states = states - - # Parse the dfas - dfas = {} - mo = re.match(r"static dfa dfas\[(\d+)\] = {$", line) - assert mo, (lineno, line) - ndfas = int(mo.group(1)) - for i in range(ndfas): - lineno, line = lineno+1, next(f) - mo = re.match(r'\s+{(\d+), "(\w+)", (\d+), (\d+), states_(\d+),$', - line) - assert mo, (lineno, line) - symbol = mo.group(2) - number, x, y, z = list(map(int, mo.group(1, 3, 4, 5))) - assert self.symbol2number[symbol] == number, (lineno, line) - assert self.number2symbol[number] == symbol, (lineno, line) - assert x == 0, (lineno, line) - state = states[z] - assert y == len(state), (lineno, line) - lineno, line = lineno+1, next(f) - mo = re.match(r'\s+("(?:\\\d\d\d)*")},$', line) - assert mo, (lineno, line) - first = {} - rawbitset = eval(mo.group(1)) - for i, c in enumerate(rawbitset): - byte = ord(c) - for j in range(8): - if byte & (1<= os.path.getmtime(b) - - -def load_packaged_grammar(package, grammar_source): - """Normally, loads a pickled grammar by doing - pkgutil.get_data(package, pickled_grammar) - where *pickled_grammar* is computed from *grammar_source* by adding the - Python version and using a ``.pickle`` extension. - - However, if *grammar_source* is an extant file, load_grammar(grammar_source) - is called instead. This facilitates using a packaged grammar file when needed - but preserves load_grammar's automatic regeneration behavior when possible. - - """ - if os.path.isfile(grammar_source): - return load_grammar(grammar_source) - pickled_name = _generate_pickle_name(os.path.basename(grammar_source)) - data = pkgutil.get_data(package, pickled_name) - g = grammar.Grammar() - g.loads(data) - return g - - -def main(*args): - """Main program, when run as a script: produce grammar pickle files. - - Calls load_grammar for each argument, a path to a grammar text file. - """ - if not args: - args = sys.argv[1:] - logging.basicConfig(level=logging.INFO, stream=sys.stdout, - format='%(message)s') - for gt in args: - load_grammar(gt, save=True, force=True) - return True - -if __name__ == "__main__": - sys.exit(int(not main())) diff --git a/Lib/lib2to3/pgen2/grammar.py b/Lib/lib2to3/pgen2/grammar.py deleted file mode 100644 index 5d550aeb65e8dd..00000000000000 --- a/Lib/lib2to3/pgen2/grammar.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""This module defines the data structures used to represent a grammar. - -These are a bit arcane because they are derived from the data -structures used by Python's 'pgen' parser generator. - -There's also a table here mapping operators to their names in the -token module; the Python tokenize module reports all operators as the -fallback token code OP, but the parser needs the actual token code. - -""" - -# Python imports -import pickle - -# Local imports -from . import token - - -class Grammar(object): - """Pgen parsing tables conversion class. - - Once initialized, this class supplies the grammar tables for the - parsing engine implemented by parse.py. The parsing engine - accesses the instance variables directly. The class here does not - provide initialization of the tables; several subclasses exist to - do this (see the conv and pgen modules). - - The load() method reads the tables from a pickle file, which is - much faster than the other ways offered by subclasses. The pickle - file is written by calling dump() (after loading the grammar - tables using a subclass). The report() method prints a readable - representation of the tables to stdout, for debugging. - - The instance variables are as follows: - - symbol2number -- a dict mapping symbol names to numbers. Symbol - numbers are always 256 or higher, to distinguish - them from token numbers, which are between 0 and - 255 (inclusive). - - number2symbol -- a dict mapping numbers to symbol names; - these two are each other's inverse. - - states -- a list of DFAs, where each DFA is a list of - states, each state is a list of arcs, and each - arc is a (i, j) pair where i is a label and j is - a state number. The DFA number is the index into - this list. (This name is slightly confusing.) - Final states are represented by a special arc of - the form (0, j) where j is its own state number. - - dfas -- a dict mapping symbol numbers to (DFA, first) - pairs, where DFA is an item from the states list - above, and first is a set of tokens that can - begin this grammar rule (represented by a dict - whose values are always 1). - - labels -- a list of (x, y) pairs where x is either a token - number or a symbol number, and y is either None - or a string; the strings are keywords. The label - number is the index in this list; label numbers - are used to mark state transitions (arcs) in the - DFAs. - - start -- the number of the grammar's start symbol. - - keywords -- a dict mapping keyword strings to arc labels. - - tokens -- a dict mapping token numbers to arc labels. - - """ - - def __init__(self): - self.symbol2number = {} - self.number2symbol = {} - self.states = [] - self.dfas = {} - self.labels = [(0, "EMPTY")] - self.keywords = {} - self.tokens = {} - self.symbol2label = {} - self.start = 256 - - def dump(self, filename): - """Dump the grammar tables to a pickle file.""" - with open(filename, "wb") as f: - pickle.dump(self.__dict__, f, pickle.HIGHEST_PROTOCOL) - - def load(self, filename): - """Load the grammar tables from a pickle file.""" - with open(filename, "rb") as f: - d = pickle.load(f) - self.__dict__.update(d) - - def loads(self, pkl): - """Load the grammar tables from a pickle bytes object.""" - self.__dict__.update(pickle.loads(pkl)) - - def copy(self): - """ - Copy the grammar. - """ - new = self.__class__() - for dict_attr in ("symbol2number", "number2symbol", "dfas", "keywords", - "tokens", "symbol2label"): - setattr(new, dict_attr, getattr(self, dict_attr).copy()) - new.labels = self.labels[:] - new.states = self.states[:] - new.start = self.start - return new - - def report(self): - """Dump the grammar tables to standard output, for debugging.""" - from pprint import pprint - print("s2n") - pprint(self.symbol2number) - print("n2s") - pprint(self.number2symbol) - print("states") - pprint(self.states) - print("dfas") - pprint(self.dfas) - print("labels") - pprint(self.labels) - print("start", self.start) - - -# Map from operator to number (since tokenize doesn't do this) - -opmap_raw = """ -( LPAR -) RPAR -[ LSQB -] RSQB -: COLON -, COMMA -; SEMI -+ PLUS -- MINUS -* STAR -/ SLASH -| VBAR -& AMPER -< LESS -> GREATER -= EQUAL -. DOT -% PERCENT -` BACKQUOTE -{ LBRACE -} RBRACE -@ AT -@= ATEQUAL -== EQEQUAL -!= NOTEQUAL -<> NOTEQUAL -<= LESSEQUAL ->= GREATEREQUAL -~ TILDE -^ CIRCUMFLEX -<< LEFTSHIFT ->> RIGHTSHIFT -** DOUBLESTAR -+= PLUSEQUAL --= MINEQUAL -*= STAREQUAL -/= SLASHEQUAL -%= PERCENTEQUAL -&= AMPEREQUAL -|= VBAREQUAL -^= CIRCUMFLEXEQUAL -<<= LEFTSHIFTEQUAL ->>= RIGHTSHIFTEQUAL -**= DOUBLESTAREQUAL -// DOUBLESLASH -//= DOUBLESLASHEQUAL --> RARROW -:= COLONEQUAL -""" - -opmap = {} -for line in opmap_raw.splitlines(): - if line: - op, name = line.split() - opmap[op] = getattr(token, name) -del line, op, name diff --git a/Lib/lib2to3/pgen2/literals.py b/Lib/lib2to3/pgen2/literals.py deleted file mode 100644 index b9b63e6e5572c1..00000000000000 --- a/Lib/lib2to3/pgen2/literals.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Safely evaluate Python string literals without using eval().""" - -import re - -simple_escapes = {"a": "\a", - "b": "\b", - "f": "\f", - "n": "\n", - "r": "\r", - "t": "\t", - "v": "\v", - "'": "'", - '"': '"', - "\\": "\\"} - -def escape(m): - all, tail = m.group(0, 1) - assert all.startswith("\\") - esc = simple_escapes.get(tail) - if esc is not None: - return esc - if tail.startswith("x"): - hexes = tail[1:] - if len(hexes) < 2: - raise ValueError("invalid hex string escape ('\\%s')" % tail) - try: - i = int(hexes, 16) - except ValueError: - raise ValueError("invalid hex string escape ('\\%s')" % tail) from None - else: - try: - i = int(tail, 8) - except ValueError: - raise ValueError("invalid octal string escape ('\\%s')" % tail) from None - return chr(i) - -def evalString(s): - assert s.startswith("'") or s.startswith('"'), repr(s[:1]) - q = s[0] - if s[:3] == q*3: - q = q*3 - assert s.endswith(q), repr(s[-len(q):]) - assert len(s) >= 2*len(q) - s = s[len(q):-len(q)] - return re.sub(r"\\(\'|\"|\\|[abfnrtv]|x.{0,2}|[0-7]{1,3})", escape, s) - -def test(): - for i in range(256): - c = chr(i) - s = repr(c) - e = evalString(s) - if e != c: - print(i, c, s, e) - - -if __name__ == "__main__": - test() diff --git a/Lib/lib2to3/pgen2/parse.py b/Lib/lib2to3/pgen2/parse.py deleted file mode 100644 index cf3fcf7e99fd11..00000000000000 --- a/Lib/lib2to3/pgen2/parse.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Parser engine for the grammar tables generated by pgen. - -The grammar table must be loaded first. - -See Parser/parser.c in the Python distribution for additional info on -how this parsing engine works. - -""" - -# Local imports -from . import token - -class ParseError(Exception): - """Exception to signal the parser is stuck.""" - - def __init__(self, msg, type, value, context): - Exception.__init__(self, "%s: type=%r, value=%r, context=%r" % - (msg, type, value, context)) - self.msg = msg - self.type = type - self.value = value - self.context = context - - def __reduce__(self): - return type(self), (self.msg, self.type, self.value, self.context) - -class Parser(object): - """Parser engine. - - The proper usage sequence is: - - p = Parser(grammar, [converter]) # create instance - p.setup([start]) # prepare for parsing - : - if p.addtoken(...): # parse a token; may raise ParseError - break - root = p.rootnode # root of abstract syntax tree - - A Parser instance may be reused by calling setup() repeatedly. - - A Parser instance contains state pertaining to the current token - sequence, and should not be used concurrently by different threads - to parse separate token sequences. - - See driver.py for how to get input tokens by tokenizing a file or - string. - - Parsing is complete when addtoken() returns True; the root of the - abstract syntax tree can then be retrieved from the rootnode - instance variable. When a syntax error occurs, addtoken() raises - the ParseError exception. There is no error recovery; the parser - cannot be used after a syntax error was reported (but it can be - reinitialized by calling setup()). - - """ - - def __init__(self, grammar, convert=None): - """Constructor. - - The grammar argument is a grammar.Grammar instance; see the - grammar module for more information. - - The parser is not ready yet for parsing; you must call the - setup() method to get it started. - - The optional convert argument is a function mapping concrete - syntax tree nodes to abstract syntax tree nodes. If not - given, no conversion is done and the syntax tree produced is - the concrete syntax tree. If given, it must be a function of - two arguments, the first being the grammar (a grammar.Grammar - instance), and the second being the concrete syntax tree node - to be converted. The syntax tree is converted from the bottom - up. - - A concrete syntax tree node is a (type, value, context, nodes) - tuple, where type is the node type (a token or symbol number), - value is None for symbols and a string for tokens, context is - None or an opaque value used for error reporting (typically a - (lineno, offset) pair), and nodes is a list of children for - symbols, and None for tokens. - - An abstract syntax tree node may be anything; this is entirely - up to the converter function. - - """ - self.grammar = grammar - self.convert = convert or (lambda grammar, node: node) - - def setup(self, start=None): - """Prepare for parsing. - - This *must* be called before starting to parse. - - The optional argument is an alternative start symbol; it - defaults to the grammar's start symbol. - - You can use a Parser instance to parse any number of programs; - each time you call setup() the parser is reset to an initial - state determined by the (implicit or explicit) start symbol. - - """ - if start is None: - start = self.grammar.start - # Each stack entry is a tuple: (dfa, state, node). - # A node is a tuple: (type, value, context, children), - # where children is a list of nodes or None, and context may be None. - newnode = (start, None, None, []) - stackentry = (self.grammar.dfas[start], 0, newnode) - self.stack = [stackentry] - self.rootnode = None - self.used_names = set() # Aliased to self.rootnode.used_names in pop() - - def addtoken(self, type, value, context): - """Add a token; return True iff this is the end of the program.""" - # Map from token to label - ilabel = self.classify(type, value, context) - # Loop until the token is shifted; may raise exceptions - while True: - dfa, state, node = self.stack[-1] - states, first = dfa - arcs = states[state] - # Look for a state with this label - for i, newstate in arcs: - t, v = self.grammar.labels[i] - if ilabel == i: - # Look it up in the list of labels - assert t < 256 - # Shift a token; we're done with it - self.shift(type, value, newstate, context) - # Pop while we are in an accept-only state - state = newstate - while states[state] == [(0, state)]: - self.pop() - if not self.stack: - # Done parsing! - return True - dfa, state, node = self.stack[-1] - states, first = dfa - # Done with this token - return False - elif t >= 256: - # See if it's a symbol and if we're in its first set - itsdfa = self.grammar.dfas[t] - itsstates, itsfirst = itsdfa - if ilabel in itsfirst: - # Push a symbol - self.push(t, self.grammar.dfas[t], newstate, context) - break # To continue the outer while loop - else: - if (0, state) in arcs: - # An accepting state, pop it and try something else - self.pop() - if not self.stack: - # Done parsing, but another token is input - raise ParseError("too much input", - type, value, context) - else: - # No success finding a transition - raise ParseError("bad input", type, value, context) - - def classify(self, type, value, context): - """Turn a token into a label. (Internal)""" - if type == token.NAME: - # Keep a listing of all used names - self.used_names.add(value) - # Check for reserved words - ilabel = self.grammar.keywords.get(value) - if ilabel is not None: - return ilabel - ilabel = self.grammar.tokens.get(type) - if ilabel is None: - raise ParseError("bad token", type, value, context) - return ilabel - - def shift(self, type, value, newstate, context): - """Shift a token. (Internal)""" - dfa, state, node = self.stack[-1] - newnode = (type, value, context, None) - newnode = self.convert(self.grammar, newnode) - if newnode is not None: - node[-1].append(newnode) - self.stack[-1] = (dfa, newstate, node) - - def push(self, type, newdfa, newstate, context): - """Push a nonterminal. (Internal)""" - dfa, state, node = self.stack[-1] - newnode = (type, None, context, []) - self.stack[-1] = (dfa, newstate, node) - self.stack.append((newdfa, 0, newnode)) - - def pop(self): - """Pop a nonterminal. (Internal)""" - popdfa, popstate, popnode = self.stack.pop() - newnode = self.convert(self.grammar, popnode) - if newnode is not None: - if self.stack: - dfa, state, node = self.stack[-1] - node[-1].append(newnode) - else: - self.rootnode = newnode - self.rootnode.used_names = self.used_names diff --git a/Lib/lib2to3/pgen2/pgen.py b/Lib/lib2to3/pgen2/pgen.py deleted file mode 100644 index 7abd5cef1c36bb..00000000000000 --- a/Lib/lib2to3/pgen2/pgen.py +++ /dev/null @@ -1,386 +0,0 @@ -# Copyright 2004-2005 Elemental Security, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -# Pgen imports -from . import grammar, token, tokenize - -class PgenGrammar(grammar.Grammar): - pass - -class ParserGenerator(object): - - def __init__(self, filename, stream=None): - close_stream = None - if stream is None: - stream = open(filename, encoding="utf-8") - close_stream = stream.close - self.filename = filename - self.stream = stream - self.generator = tokenize.generate_tokens(stream.readline) - self.gettoken() # Initialize lookahead - self.dfas, self.startsymbol = self.parse() - if close_stream is not None: - close_stream() - self.first = {} # map from symbol name to set of tokens - self.addfirstsets() - - def make_grammar(self): - c = PgenGrammar() - names = list(self.dfas.keys()) - names.sort() - names.remove(self.startsymbol) - names.insert(0, self.startsymbol) - for name in names: - i = 256 + len(c.symbol2number) - c.symbol2number[name] = i - c.number2symbol[i] = name - for name in names: - dfa = self.dfas[name] - states = [] - for state in dfa: - arcs = [] - for label, next in sorted(state.arcs.items()): - arcs.append((self.make_label(c, label), dfa.index(next))) - if state.isfinal: - arcs.append((0, dfa.index(state))) - states.append(arcs) - c.states.append(states) - c.dfas[c.symbol2number[name]] = (states, self.make_first(c, name)) - c.start = c.symbol2number[self.startsymbol] - return c - - def make_first(self, c, name): - rawfirst = self.first[name] - first = {} - for label in sorted(rawfirst): - ilabel = self.make_label(c, label) - ##assert ilabel not in first # XXX failed on <> ... != - first[ilabel] = 1 - return first - - def make_label(self, c, label): - # XXX Maybe this should be a method on a subclass of converter? - ilabel = len(c.labels) - if label[0].isalpha(): - # Either a symbol name or a named token - if label in c.symbol2number: - # A symbol name (a non-terminal) - if label in c.symbol2label: - return c.symbol2label[label] - else: - c.labels.append((c.symbol2number[label], None)) - c.symbol2label[label] = ilabel - return ilabel - else: - # A named token (NAME, NUMBER, STRING) - itoken = getattr(token, label, None) - assert isinstance(itoken, int), label - assert itoken in token.tok_name, label - if itoken in c.tokens: - return c.tokens[itoken] - else: - c.labels.append((itoken, None)) - c.tokens[itoken] = ilabel - return ilabel - else: - # Either a keyword or an operator - assert label[0] in ('"', "'"), label - value = eval(label) - if value[0].isalpha(): - # A keyword - if value in c.keywords: - return c.keywords[value] - else: - c.labels.append((token.NAME, value)) - c.keywords[value] = ilabel - return ilabel - else: - # An operator (any non-numeric token) - itoken = grammar.opmap[value] # Fails if unknown token - if itoken in c.tokens: - return c.tokens[itoken] - else: - c.labels.append((itoken, None)) - c.tokens[itoken] = ilabel - return ilabel - - def addfirstsets(self): - names = list(self.dfas.keys()) - names.sort() - for name in names: - if name not in self.first: - self.calcfirst(name) - #print name, self.first[name].keys() - - def calcfirst(self, name): - dfa = self.dfas[name] - self.first[name] = None # dummy to detect left recursion - state = dfa[0] - totalset = {} - overlapcheck = {} - for label, next in state.arcs.items(): - if label in self.dfas: - if label in self.first: - fset = self.first[label] - if fset is None: - raise ValueError("recursion for rule %r" % name) - else: - self.calcfirst(label) - fset = self.first[label] - totalset.update(fset) - overlapcheck[label] = fset - else: - totalset[label] = 1 - overlapcheck[label] = {label: 1} - inverse = {} - for label, itsfirst in overlapcheck.items(): - for symbol in itsfirst: - if symbol in inverse: - raise ValueError("rule %s is ambiguous; %s is in the" - " first sets of %s as well as %s" % - (name, symbol, label, inverse[symbol])) - inverse[symbol] = label - self.first[name] = totalset - - def parse(self): - dfas = {} - startsymbol = None - # MSTART: (NEWLINE | RULE)* ENDMARKER - while self.type != token.ENDMARKER: - while self.type == token.NEWLINE: - self.gettoken() - # RULE: NAME ':' RHS NEWLINE - name = self.expect(token.NAME) - self.expect(token.OP, ":") - a, z = self.parse_rhs() - self.expect(token.NEWLINE) - #self.dump_nfa(name, a, z) - dfa = self.make_dfa(a, z) - #self.dump_dfa(name, dfa) - oldlen = len(dfa) - self.simplify_dfa(dfa) - newlen = len(dfa) - dfas[name] = dfa - #print name, oldlen, newlen - if startsymbol is None: - startsymbol = name - return dfas, startsymbol - - def make_dfa(self, start, finish): - # To turn an NFA into a DFA, we define the states of the DFA - # to correspond to *sets* of states of the NFA. Then do some - # state reduction. Let's represent sets as dicts with 1 for - # values. - assert isinstance(start, NFAState) - assert isinstance(finish, NFAState) - def closure(state): - base = {} - addclosure(state, base) - return base - def addclosure(state, base): - assert isinstance(state, NFAState) - if state in base: - return - base[state] = 1 - for label, next in state.arcs: - if label is None: - addclosure(next, base) - states = [DFAState(closure(start), finish)] - for state in states: # NB states grows while we're iterating - arcs = {} - for nfastate in state.nfaset: - for label, next in nfastate.arcs: - if label is not None: - addclosure(next, arcs.setdefault(label, {})) - for label, nfaset in sorted(arcs.items()): - for st in states: - if st.nfaset == nfaset: - break - else: - st = DFAState(nfaset, finish) - states.append(st) - state.addarc(st, label) - return states # List of DFAState instances; first one is start - - def dump_nfa(self, name, start, finish): - print("Dump of NFA for", name) - todo = [start] - for i, state in enumerate(todo): - print(" State", i, state is finish and "(final)" or "") - for label, next in state.arcs: - if next in todo: - j = todo.index(next) - else: - j = len(todo) - todo.append(next) - if label is None: - print(" -> %d" % j) - else: - print(" %s -> %d" % (label, j)) - - def dump_dfa(self, name, dfa): - print("Dump of DFA for", name) - for i, state in enumerate(dfa): - print(" State", i, state.isfinal and "(final)" or "") - for label, next in sorted(state.arcs.items()): - print(" %s -> %d" % (label, dfa.index(next))) - - def simplify_dfa(self, dfa): - # This is not theoretically optimal, but works well enough. - # Algorithm: repeatedly look for two states that have the same - # set of arcs (same labels pointing to the same nodes) and - # unify them, until things stop changing. - - # dfa is a list of DFAState instances - changes = True - while changes: - changes = False - for i, state_i in enumerate(dfa): - for j in range(i+1, len(dfa)): - state_j = dfa[j] - if state_i == state_j: - #print " unify", i, j - del dfa[j] - for state in dfa: - state.unifystate(state_j, state_i) - changes = True - break - - def parse_rhs(self): - # RHS: ALT ('|' ALT)* - a, z = self.parse_alt() - if self.value != "|": - return a, z - else: - aa = NFAState() - zz = NFAState() - aa.addarc(a) - z.addarc(zz) - while self.value == "|": - self.gettoken() - a, z = self.parse_alt() - aa.addarc(a) - z.addarc(zz) - return aa, zz - - def parse_alt(self): - # ALT: ITEM+ - a, b = self.parse_item() - while (self.value in ("(", "[") or - self.type in (token.NAME, token.STRING)): - c, d = self.parse_item() - b.addarc(c) - b = d - return a, b - - def parse_item(self): - # ITEM: '[' RHS ']' | ATOM ['+' | '*'] - if self.value == "[": - self.gettoken() - a, z = self.parse_rhs() - self.expect(token.OP, "]") - a.addarc(z) - return a, z - else: - a, z = self.parse_atom() - value = self.value - if value not in ("+", "*"): - return a, z - self.gettoken() - z.addarc(a) - if value == "+": - return a, z - else: - return a, a - - def parse_atom(self): - # ATOM: '(' RHS ')' | NAME | STRING - if self.value == "(": - self.gettoken() - a, z = self.parse_rhs() - self.expect(token.OP, ")") - return a, z - elif self.type in (token.NAME, token.STRING): - a = NFAState() - z = NFAState() - a.addarc(z, self.value) - self.gettoken() - return a, z - else: - self.raise_error("expected (...) or NAME or STRING, got %s/%s", - self.type, self.value) - - def expect(self, type, value=None): - if self.type != type or (value is not None and self.value != value): - self.raise_error("expected %s/%s, got %s/%s", - type, value, self.type, self.value) - value = self.value - self.gettoken() - return value - - def gettoken(self): - tup = next(self.generator) - while tup[0] in (tokenize.COMMENT, tokenize.NL): - tup = next(self.generator) - self.type, self.value, self.begin, self.end, self.line = tup - #print token.tok_name[self.type], repr(self.value) - - def raise_error(self, msg, *args): - if args: - try: - msg = msg % args - except: - msg = " ".join([msg] + list(map(str, args))) - raise SyntaxError(msg, (self.filename, self.end[0], - self.end[1], self.line)) - -class NFAState(object): - - def __init__(self): - self.arcs = [] # list of (label, NFAState) pairs - - def addarc(self, next, label=None): - assert label is None or isinstance(label, str) - assert isinstance(next, NFAState) - self.arcs.append((label, next)) - -class DFAState(object): - - def __init__(self, nfaset, final): - assert isinstance(nfaset, dict) - assert isinstance(next(iter(nfaset)), NFAState) - assert isinstance(final, NFAState) - self.nfaset = nfaset - self.isfinal = final in nfaset - self.arcs = {} # map from label to DFAState - - def addarc(self, next, label): - assert isinstance(label, str) - assert label not in self.arcs - assert isinstance(next, DFAState) - self.arcs[label] = next - - def unifystate(self, old, new): - for label, next in self.arcs.items(): - if next is old: - self.arcs[label] = new - - def __eq__(self, other): - # Equality test -- ignore the nfaset instance variable - assert isinstance(other, DFAState) - if self.isfinal != other.isfinal: - return False - # Can't just return self.arcs == other.arcs, because that - # would invoke this method recursively, with cycles... - if len(self.arcs) != len(other.arcs): - return False - for label, next in self.arcs.items(): - if next is not other.arcs.get(label): - return False - return True - - __hash__ = None # For Py3 compatibility. - -def generate_grammar(filename="Grammar.txt"): - p = ParserGenerator(filename) - return p.make_grammar() diff --git a/Lib/lib2to3/pgen2/token.py b/Lib/lib2to3/pgen2/token.py deleted file mode 100755 index 2a55138e48237b..00000000000000 --- a/Lib/lib2to3/pgen2/token.py +++ /dev/null @@ -1,86 +0,0 @@ -#! /usr/bin/env python3 - -"""Token constants (from "token.h").""" - -# Taken from Python (r53757) and modified to include some tokens -# originally monkeypatched in by pgen2.tokenize - -#--start constants-- -ENDMARKER = 0 -NAME = 1 -NUMBER = 2 -STRING = 3 -NEWLINE = 4 -INDENT = 5 -DEDENT = 6 -LPAR = 7 -RPAR = 8 -LSQB = 9 -RSQB = 10 -COLON = 11 -COMMA = 12 -SEMI = 13 -PLUS = 14 -MINUS = 15 -STAR = 16 -SLASH = 17 -VBAR = 18 -AMPER = 19 -LESS = 20 -GREATER = 21 -EQUAL = 22 -DOT = 23 -PERCENT = 24 -BACKQUOTE = 25 -LBRACE = 26 -RBRACE = 27 -EQEQUAL = 28 -NOTEQUAL = 29 -LESSEQUAL = 30 -GREATEREQUAL = 31 -TILDE = 32 -CIRCUMFLEX = 33 -LEFTSHIFT = 34 -RIGHTSHIFT = 35 -DOUBLESTAR = 36 -PLUSEQUAL = 37 -MINEQUAL = 38 -STAREQUAL = 39 -SLASHEQUAL = 40 -PERCENTEQUAL = 41 -AMPEREQUAL = 42 -VBAREQUAL = 43 -CIRCUMFLEXEQUAL = 44 -LEFTSHIFTEQUAL = 45 -RIGHTSHIFTEQUAL = 46 -DOUBLESTAREQUAL = 47 -DOUBLESLASH = 48 -DOUBLESLASHEQUAL = 49 -AT = 50 -ATEQUAL = 51 -OP = 52 -COMMENT = 53 -NL = 54 -RARROW = 55 -AWAIT = 56 -ASYNC = 57 -ERRORTOKEN = 58 -COLONEQUAL = 59 -N_TOKENS = 60 -NT_OFFSET = 256 -#--end constants-- - -tok_name = {} -for _name, _value in list(globals().items()): - if isinstance(_value, int): - tok_name[_value] = _name - - -def ISTERMINAL(x): - return x < NT_OFFSET - -def ISNONTERMINAL(x): - return x >= NT_OFFSET - -def ISEOF(x): - return x == ENDMARKER diff --git a/Lib/lib2to3/pgen2/tokenize.py b/Lib/lib2to3/pgen2/tokenize.py deleted file mode 100644 index 099dfa7798afd4..00000000000000 --- a/Lib/lib2to3/pgen2/tokenize.py +++ /dev/null @@ -1,564 +0,0 @@ -# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation. -# All rights reserved. - -"""Tokenization help for Python programs. - -generate_tokens(readline) is a generator that breaks a stream of -text into Python tokens. It accepts a readline-like method which is called -repeatedly to get the next line of input (or "" for EOF). It generates -5-tuples with these members: - - the token type (see token.py) - the token (a string) - the starting (row, column) indices of the token (a 2-tuple of ints) - the ending (row, column) indices of the token (a 2-tuple of ints) - the original line (string) - -It is designed to match the working of the Python tokenizer exactly, except -that it produces COMMENT tokens for comments and gives type OP for all -operators - -Older entry points - tokenize_loop(readline, tokeneater) - tokenize(readline, tokeneater=printtoken) -are the same, except instead of generating tokens, tokeneater is a callback -function to which the 5 fields described above are passed as 5 arguments, -each time a new token is found.""" - -__author__ = 'Ka-Ping Yee ' -__credits__ = \ - 'GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, Skip Montanaro' - -import string, re -from codecs import BOM_UTF8, lookup -from lib2to3.pgen2.token import * - -from . import token -__all__ = [x for x in dir(token) if x[0] != '_'] + ["tokenize", - "generate_tokens", "untokenize"] -del token - -try: - bytes -except NameError: - # Support bytes type in Python <= 2.5, so 2to3 turns itself into - # valid Python 3 code. - bytes = str - -def group(*choices): return '(' + '|'.join(choices) + ')' -def any(*choices): return group(*choices) + '*' -def maybe(*choices): return group(*choices) + '?' -def _combinations(*l): - return set( - x + y for x in l for y in l + ("",) if x.casefold() != y.casefold() - ) - -Whitespace = r'[ \f\t]*' -Comment = r'#[^\r\n]*' -Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment) -Name = r'\w+' - -Binnumber = r'0[bB]_?[01]+(?:_[01]+)*' -Hexnumber = r'0[xX]_?[\da-fA-F]+(?:_[\da-fA-F]+)*[lL]?' -Octnumber = r'0[oO]?_?[0-7]+(?:_[0-7]+)*[lL]?' -Decnumber = group(r'[1-9]\d*(?:_\d+)*[lL]?', '0[lL]?') -Intnumber = group(Binnumber, Hexnumber, Octnumber, Decnumber) -Exponent = r'[eE][-+]?\d+(?:_\d+)*' -Pointfloat = group(r'\d+(?:_\d+)*\.(?:\d+(?:_\d+)*)?', r'\.\d+(?:_\d+)*') + maybe(Exponent) -Expfloat = r'\d+(?:_\d+)*' + Exponent -Floatnumber = group(Pointfloat, Expfloat) -Imagnumber = group(r'\d+(?:_\d+)*[jJ]', Floatnumber + r'[jJ]') -Number = group(Imagnumber, Floatnumber, Intnumber) - -# Tail end of ' string. -Single = r"[^'\\]*(?:\\.[^'\\]*)*'" -# Tail end of " string. -Double = r'[^"\\]*(?:\\.[^"\\]*)*"' -# Tail end of ''' string. -Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''" -# Tail end of """ string. -Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""' -_litprefix = r"(?:[uUrRbBfF]|[rR][fFbB]|[fFbBuU][rR])?" -Triple = group(_litprefix + "'''", _litprefix + '"""') -# Single-line ' or " string. -String = group(_litprefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*'", - _litprefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*"') - -# Because of leftmost-then-longest match semantics, be sure to put the -# longest operators first (e.g., if = came before ==, == would get -# recognized as two instances of =). -Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"<>", r"!=", - r"//=?", r"->", - r"[+\-*/%&@|^=<>]=?", - r"~") - -Bracket = '[][(){}]' -Special = group(r'\r?\n', r':=', r'[:;.,`@]') -Funny = group(Operator, Bracket, Special) - -PlainToken = group(Number, Funny, String, Name) -Token = Ignore + PlainToken - -# First (or only) line of ' or " string. -ContStr = group(_litprefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*" + - group("'", r'\\\r?\n'), - _litprefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' + - group('"', r'\\\r?\n')) -PseudoExtras = group(r'\\\r?\n', Comment, Triple) -PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) - -tokenprog, pseudoprog, single3prog, double3prog = map( - re.compile, (Token, PseudoToken, Single3, Double3)) - -_strprefixes = ( - _combinations('r', 'R', 'f', 'F') | - _combinations('r', 'R', 'b', 'B') | - {'u', 'U', 'ur', 'uR', 'Ur', 'UR'} -) - -endprogs = {"'": re.compile(Single), '"': re.compile(Double), - "'''": single3prog, '"""': double3prog, - **{f"{prefix}'''": single3prog for prefix in _strprefixes}, - **{f'{prefix}"""': double3prog for prefix in _strprefixes}, - **{prefix: None for prefix in _strprefixes}} - -triple_quoted = ( - {"'''", '"""'} | - {f"{prefix}'''" for prefix in _strprefixes} | - {f'{prefix}"""' for prefix in _strprefixes} -) -single_quoted = ( - {"'", '"'} | - {f"{prefix}'" for prefix in _strprefixes} | - {f'{prefix}"' for prefix in _strprefixes} -) - -tabsize = 8 - -class TokenError(Exception): pass - -class StopTokenizing(Exception): pass - -def printtoken(type, token, xxx_todo_changeme, xxx_todo_changeme1, line): # for testing - (srow, scol) = xxx_todo_changeme - (erow, ecol) = xxx_todo_changeme1 - print("%d,%d-%d,%d:\t%s\t%s" % \ - (srow, scol, erow, ecol, tok_name[type], repr(token))) - -def tokenize(readline, tokeneater=printtoken): - """ - The tokenize() function accepts two parameters: one representing the - input stream, and one providing an output mechanism for tokenize(). - - The first parameter, readline, must be a callable object which provides - the same interface as the readline() method of built-in file objects. - Each call to the function should return one line of input as a string. - - The second parameter, tokeneater, must also be a callable object. It is - called once for each token, with five arguments, corresponding to the - tuples generated by generate_tokens(). - """ - try: - tokenize_loop(readline, tokeneater) - except StopTokenizing: - pass - -# backwards compatible interface -def tokenize_loop(readline, tokeneater): - for token_info in generate_tokens(readline): - tokeneater(*token_info) - -class Untokenizer: - - def __init__(self): - self.tokens = [] - self.prev_row = 1 - self.prev_col = 0 - - def add_whitespace(self, start): - row, col = start - assert row <= self.prev_row - col_offset = col - self.prev_col - if col_offset: - self.tokens.append(" " * col_offset) - - def untokenize(self, iterable): - for t in iterable: - if len(t) == 2: - self.compat(t, iterable) - break - tok_type, token, start, end, line = t - self.add_whitespace(start) - self.tokens.append(token) - self.prev_row, self.prev_col = end - if tok_type in (NEWLINE, NL): - self.prev_row += 1 - self.prev_col = 0 - return "".join(self.tokens) - - def compat(self, token, iterable): - startline = False - indents = [] - toks_append = self.tokens.append - toknum, tokval = token - if toknum in (NAME, NUMBER): - tokval += ' ' - if toknum in (NEWLINE, NL): - startline = True - for tok in iterable: - toknum, tokval = tok[:2] - - if toknum in (NAME, NUMBER, ASYNC, AWAIT): - tokval += ' ' - - if toknum == INDENT: - indents.append(tokval) - continue - elif toknum == DEDENT: - indents.pop() - continue - elif toknum in (NEWLINE, NL): - startline = True - elif startline and indents: - toks_append(indents[-1]) - startline = False - toks_append(tokval) - -cookie_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII) -blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII) - -def _get_normal_name(orig_enc): - """Imitates get_normal_name in tokenizer.c.""" - # Only care about the first 12 characters. - enc = orig_enc[:12].lower().replace("_", "-") - if enc == "utf-8" or enc.startswith("utf-8-"): - return "utf-8" - if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ - enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): - return "iso-8859-1" - return orig_enc - -def detect_encoding(readline): - """ - The detect_encoding() function is used to detect the encoding that should - be used to decode a Python source file. It requires one argument, readline, - in the same way as the tokenize() generator. - - It will call readline a maximum of twice, and return the encoding used - (as a string) and a list of any lines (left as bytes) it has read - in. - - It detects the encoding from the presence of a utf-8 bom or an encoding - cookie as specified in pep-0263. If both a bom and a cookie are present, but - disagree, a SyntaxError will be raised. If the encoding cookie is an invalid - charset, raise a SyntaxError. Note that if a utf-8 bom is found, - 'utf-8-sig' is returned. - - If no encoding is specified, then the default of 'utf-8' will be returned. - """ - bom_found = False - encoding = None - default = 'utf-8' - def read_or_stop(): - try: - return readline() - except StopIteration: - return bytes() - - def find_cookie(line): - try: - line_string = line.decode('ascii') - except UnicodeDecodeError: - return None - match = cookie_re.match(line_string) - if not match: - return None - encoding = _get_normal_name(match.group(1)) - try: - codec = lookup(encoding) - except LookupError: - # This behaviour mimics the Python interpreter - raise SyntaxError("unknown encoding: " + encoding) - - if bom_found: - if codec.name != 'utf-8': - # This behaviour mimics the Python interpreter - raise SyntaxError('encoding problem: utf-8') - encoding += '-sig' - return encoding - - first = read_or_stop() - if first.startswith(BOM_UTF8): - bom_found = True - first = first[3:] - default = 'utf-8-sig' - if not first: - return default, [] - - encoding = find_cookie(first) - if encoding: - return encoding, [first] - if not blank_re.match(first): - return default, [first] - - second = read_or_stop() - if not second: - return default, [first] - - encoding = find_cookie(second) - if encoding: - return encoding, [first, second] - - return default, [first, second] - -def untokenize(iterable): - """Transform tokens back into Python source code. - - Each element returned by the iterable must be a token sequence - with at least two elements, a token number and token value. If - only two tokens are passed, the resulting output is poor. - - Round-trip invariant for full input: - Untokenized source will match input source exactly - - Round-trip invariant for limited input: - # Output text will tokenize the back to the input - t1 = [tok[:2] for tok in generate_tokens(f.readline)] - newcode = untokenize(t1) - readline = iter(newcode.splitlines(1)).next - t2 = [tok[:2] for tokin generate_tokens(readline)] - assert t1 == t2 - """ - ut = Untokenizer() - return ut.untokenize(iterable) - -def generate_tokens(readline): - """ - The generate_tokens() generator requires one argument, readline, which - must be a callable object which provides the same interface as the - readline() method of built-in file objects. Each call to the function - should return one line of input as a string. Alternately, readline - can be a callable function terminating with StopIteration: - readline = open(myfile).next # Example of alternate readline - - The generator produces 5-tuples with these members: the token type; the - token string; a 2-tuple (srow, scol) of ints specifying the row and - column where the token begins in the source; a 2-tuple (erow, ecol) of - ints specifying the row and column where the token ends in the source; - and the line on which the token was found. The line passed is the - physical line. - """ - lnum = parenlev = continued = 0 - contstr, needcont = '', 0 - contline = None - indents = [0] - - # 'stashed' and 'async_*' are used for async/await parsing - stashed = None - async_def = False - async_def_indent = 0 - async_def_nl = False - - while 1: # loop over lines in stream - try: - line = readline() - except StopIteration: - line = '' - lnum = lnum + 1 - pos, max = 0, len(line) - - if contstr: # continued string - if not line: - raise TokenError("EOF in multi-line string", strstart) - endmatch = endprog.match(line) - if endmatch: - pos = end = endmatch.end(0) - yield (STRING, contstr + line[:end], - strstart, (lnum, end), contline + line) - contstr, needcont = '', 0 - contline = None - elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': - yield (ERRORTOKEN, contstr + line, - strstart, (lnum, len(line)), contline) - contstr = '' - contline = None - continue - else: - contstr = contstr + line - contline = contline + line - continue - - elif parenlev == 0 and not continued: # new statement - if not line: break - column = 0 - while pos < max: # measure leading whitespace - if line[pos] == ' ': column = column + 1 - elif line[pos] == '\t': column = (column//tabsize + 1)*tabsize - elif line[pos] == '\f': column = 0 - else: break - pos = pos + 1 - if pos == max: break - - if stashed: - yield stashed - stashed = None - - if line[pos] in '#\r\n': # skip comments or blank lines - if line[pos] == '#': - comment_token = line[pos:].rstrip('\r\n') - nl_pos = pos + len(comment_token) - yield (COMMENT, comment_token, - (lnum, pos), (lnum, pos + len(comment_token)), line) - yield (NL, line[nl_pos:], - (lnum, nl_pos), (lnum, len(line)), line) - else: - yield ((NL, COMMENT)[line[pos] == '#'], line[pos:], - (lnum, pos), (lnum, len(line)), line) - continue - - if column > indents[-1]: # count indents or dedents - indents.append(column) - yield (INDENT, line[:pos], (lnum, 0), (lnum, pos), line) - while column < indents[-1]: - if column not in indents: - raise IndentationError( - "unindent does not match any outer indentation level", - ("", lnum, pos, line)) - indents = indents[:-1] - - if async_def and async_def_indent >= indents[-1]: - async_def = False - async_def_nl = False - async_def_indent = 0 - - yield (DEDENT, '', (lnum, pos), (lnum, pos), line) - - if async_def and async_def_nl and async_def_indent >= indents[-1]: - async_def = False - async_def_nl = False - async_def_indent = 0 - - else: # continued statement - if not line: - raise TokenError("EOF in multi-line statement", (lnum, 0)) - continued = 0 - - while pos < max: - pseudomatch = pseudoprog.match(line, pos) - if pseudomatch: # scan for tokens - start, end = pseudomatch.span(1) - spos, epos, pos = (lnum, start), (lnum, end), end - token, initial = line[start:end], line[start] - - if initial in string.digits or \ - (initial == '.' and token != '.'): # ordinary number - yield (NUMBER, token, spos, epos, line) - elif initial in '\r\n': - newline = NEWLINE - if parenlev > 0: - newline = NL - elif async_def: - async_def_nl = True - if stashed: - yield stashed - stashed = None - yield (newline, token, spos, epos, line) - - elif initial == '#': - assert not token.endswith("\n") - if stashed: - yield stashed - stashed = None - yield (COMMENT, token, spos, epos, line) - elif token in triple_quoted: - endprog = endprogs[token] - endmatch = endprog.match(line, pos) - if endmatch: # all on one line - pos = endmatch.end(0) - token = line[start:pos] - if stashed: - yield stashed - stashed = None - yield (STRING, token, spos, (lnum, pos), line) - else: - strstart = (lnum, start) # multiple lines - contstr = line[start:] - contline = line - break - elif initial in single_quoted or \ - token[:2] in single_quoted or \ - token[:3] in single_quoted: - if token[-1] == '\n': # continued string - strstart = (lnum, start) - endprog = (endprogs[initial] or endprogs[token[1]] or - endprogs[token[2]]) - contstr, needcont = line[start:], 1 - contline = line - break - else: # ordinary string - if stashed: - yield stashed - stashed = None - yield (STRING, token, spos, epos, line) - elif initial.isidentifier(): # ordinary name - if token in ('async', 'await'): - if async_def: - yield (ASYNC if token == 'async' else AWAIT, - token, spos, epos, line) - continue - - tok = (NAME, token, spos, epos, line) - if token == 'async' and not stashed: - stashed = tok - continue - - if token in ('def', 'for'): - if (stashed - and stashed[0] == NAME - and stashed[1] == 'async'): - - if token == 'def': - async_def = True - async_def_indent = indents[-1] - - yield (ASYNC, stashed[1], - stashed[2], stashed[3], - stashed[4]) - stashed = None - - if stashed: - yield stashed - stashed = None - - yield tok - elif initial == '\\': # continued stmt - # This yield is new; needed for better idempotency: - if stashed: - yield stashed - stashed = None - yield (NL, token, spos, (lnum, pos), line) - continued = 1 - else: - if initial in '([{': parenlev = parenlev + 1 - elif initial in ')]}': parenlev = parenlev - 1 - if stashed: - yield stashed - stashed = None - yield (OP, token, spos, epos, line) - else: - yield (ERRORTOKEN, line[pos], - (lnum, pos), (lnum, pos+1), line) - pos = pos + 1 - - if stashed: - yield stashed - stashed = None - - for indent in indents[1:]: # pop remaining indent levels - yield (DEDENT, '', (lnum, 0), (lnum, 0), '') - yield (ENDMARKER, '', (lnum, 0), (lnum, 0), '') - -if __name__ == '__main__': # testing - import sys - if len(sys.argv) > 1: tokenize(open(sys.argv[1]).readline) - else: tokenize(sys.stdin.readline) diff --git a/Lib/lib2to3/pygram.py b/Lib/lib2to3/pygram.py deleted file mode 100644 index 24d9db9217f131..00000000000000 --- a/Lib/lib2to3/pygram.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Export the Python grammar and symbols.""" - -# Python imports -import os - -# Local imports -from .pgen2 import token -from .pgen2 import driver -from . import pytree - -# The grammar file -_GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), "Grammar.txt") -_PATTERN_GRAMMAR_FILE = os.path.join(os.path.dirname(__file__), - "PatternGrammar.txt") - - -class Symbols(object): - - def __init__(self, grammar): - """Initializer. - - Creates an attribute for each grammar symbol (nonterminal), - whose value is the symbol's type (an int >= 256). - """ - for name, symbol in grammar.symbol2number.items(): - setattr(self, name, symbol) - - -python_grammar = driver.load_packaged_grammar("lib2to3", _GRAMMAR_FILE) - -python_symbols = Symbols(python_grammar) - -python_grammar_no_print_statement = python_grammar.copy() -del python_grammar_no_print_statement.keywords["print"] - -python_grammar_no_print_and_exec_statement = python_grammar_no_print_statement.copy() -del python_grammar_no_print_and_exec_statement.keywords["exec"] - -pattern_grammar = driver.load_packaged_grammar("lib2to3", _PATTERN_GRAMMAR_FILE) -pattern_symbols = Symbols(pattern_grammar) diff --git a/Lib/lib2to3/pytree.py b/Lib/lib2to3/pytree.py deleted file mode 100644 index 729023df0284e1..00000000000000 --- a/Lib/lib2to3/pytree.py +++ /dev/null @@ -1,853 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -""" -Python parse tree definitions. - -This is a very concrete parse tree; we need to keep every token and -even the comments and whitespace between tokens. - -There's also a pattern matching implementation here. -""" - -__author__ = "Guido van Rossum " - -import sys -from io import StringIO - -HUGE = 0x7FFFFFFF # maximum repeat count, default max - -_type_reprs = {} -def type_repr(type_num): - global _type_reprs - if not _type_reprs: - from .pygram import python_symbols - # printing tokens is possible but not as useful - # from .pgen2 import token // token.__dict__.items(): - for name, val in python_symbols.__dict__.items(): - if type(val) == int: _type_reprs[val] = name - return _type_reprs.setdefault(type_num, type_num) - -class Base(object): - - """ - Abstract base class for Node and Leaf. - - This provides some default functionality and boilerplate using the - template pattern. - - A node may be a subnode of at most one parent. - """ - - # Default values for instance variables - type = None # int: token number (< 256) or symbol number (>= 256) - parent = None # Parent node pointer, or None - children = () # Tuple of subnodes - was_changed = False - was_checked = False - - def __new__(cls, *args, **kwds): - """Constructor that prevents Base from being instantiated.""" - assert cls is not Base, "Cannot instantiate Base" - return object.__new__(cls) - - def __eq__(self, other): - """ - Compare two nodes for equality. - - This calls the method _eq(). - """ - if self.__class__ is not other.__class__: - return NotImplemented - return self._eq(other) - - __hash__ = None # For Py3 compatibility. - - def _eq(self, other): - """ - Compare two nodes for equality. - - This is called by __eq__ and __ne__. It is only called if the two nodes - have the same type. This must be implemented by the concrete subclass. - Nodes should be considered equal if they have the same structure, - ignoring the prefix string and other context information. - """ - raise NotImplementedError - - def clone(self): - """ - Return a cloned (deep) copy of self. - - This must be implemented by the concrete subclass. - """ - raise NotImplementedError - - def post_order(self): - """ - Return a post-order iterator for the tree. - - This must be implemented by the concrete subclass. - """ - raise NotImplementedError - - def pre_order(self): - """ - Return a pre-order iterator for the tree. - - This must be implemented by the concrete subclass. - """ - raise NotImplementedError - - def replace(self, new): - """Replace this node with a new one in the parent.""" - assert self.parent is not None, str(self) - assert new is not None - if not isinstance(new, list): - new = [new] - l_children = [] - found = False - for ch in self.parent.children: - if ch is self: - assert not found, (self.parent.children, self, new) - if new is not None: - l_children.extend(new) - found = True - else: - l_children.append(ch) - assert found, (self.children, self, new) - self.parent.changed() - self.parent.children = l_children - for x in new: - x.parent = self.parent - self.parent = None - - def get_lineno(self): - """Return the line number which generated the invocant node.""" - node = self - while not isinstance(node, Leaf): - if not node.children: - return - node = node.children[0] - return node.lineno - - def changed(self): - if self.parent: - self.parent.changed() - self.was_changed = True - - def remove(self): - """ - Remove the node from the tree. Returns the position of the node in its - parent's children before it was removed. - """ - if self.parent: - for i, node in enumerate(self.parent.children): - if node is self: - self.parent.changed() - del self.parent.children[i] - self.parent = None - return i - - @property - def next_sibling(self): - """ - The node immediately following the invocant in their parent's children - list. If the invocant does not have a next sibling, it is None - """ - if self.parent is None: - return None - - # Can't use index(); we need to test by identity - for i, child in enumerate(self.parent.children): - if child is self: - try: - return self.parent.children[i+1] - except IndexError: - return None - - @property - def prev_sibling(self): - """ - The node immediately preceding the invocant in their parent's children - list. If the invocant does not have a previous sibling, it is None. - """ - if self.parent is None: - return None - - # Can't use index(); we need to test by identity - for i, child in enumerate(self.parent.children): - if child is self: - if i == 0: - return None - return self.parent.children[i-1] - - def leaves(self): - for child in self.children: - yield from child.leaves() - - def depth(self): - if self.parent is None: - return 0 - return 1 + self.parent.depth() - - def get_suffix(self): - """ - Return the string immediately following the invocant node. This is - effectively equivalent to node.next_sibling.prefix - """ - next_sib = self.next_sibling - if next_sib is None: - return "" - return next_sib.prefix - - if sys.version_info < (3, 0): - def __str__(self): - return str(self).encode("ascii") - -class Node(Base): - - """Concrete implementation for interior nodes.""" - - def __init__(self,type, children, - context=None, - prefix=None, - fixers_applied=None): - """ - Initializer. - - Takes a type constant (a symbol number >= 256), a sequence of - child nodes, and an optional context keyword argument. - - As a side effect, the parent pointers of the children are updated. - """ - assert type >= 256, type - self.type = type - self.children = list(children) - for ch in self.children: - assert ch.parent is None, repr(ch) - ch.parent = self - if prefix is not None: - self.prefix = prefix - if fixers_applied: - self.fixers_applied = fixers_applied[:] - else: - self.fixers_applied = None - - def __repr__(self): - """Return a canonical string representation.""" - return "%s(%s, %r)" % (self.__class__.__name__, - type_repr(self.type), - self.children) - - def __unicode__(self): - """ - Return a pretty string representation. - - This reproduces the input source exactly. - """ - return "".join(map(str, self.children)) - - if sys.version_info > (3, 0): - __str__ = __unicode__ - - def _eq(self, other): - """Compare two nodes for equality.""" - return (self.type, self.children) == (other.type, other.children) - - def clone(self): - """Return a cloned (deep) copy of self.""" - return Node(self.type, [ch.clone() for ch in self.children], - fixers_applied=self.fixers_applied) - - def post_order(self): - """Return a post-order iterator for the tree.""" - for child in self.children: - yield from child.post_order() - yield self - - def pre_order(self): - """Return a pre-order iterator for the tree.""" - yield self - for child in self.children: - yield from child.pre_order() - - @property - def prefix(self): - """ - The whitespace and comments preceding this node in the input. - """ - if not self.children: - return "" - return self.children[0].prefix - - @prefix.setter - def prefix(self, prefix): - if self.children: - self.children[0].prefix = prefix - - def set_child(self, i, child): - """ - Equivalent to 'node.children[i] = child'. This method also sets the - child's parent attribute appropriately. - """ - child.parent = self - self.children[i].parent = None - self.children[i] = child - self.changed() - - def insert_child(self, i, child): - """ - Equivalent to 'node.children.insert(i, child)'. This method also sets - the child's parent attribute appropriately. - """ - child.parent = self - self.children.insert(i, child) - self.changed() - - def append_child(self, child): - """ - Equivalent to 'node.children.append(child)'. This method also sets the - child's parent attribute appropriately. - """ - child.parent = self - self.children.append(child) - self.changed() - - -class Leaf(Base): - - """Concrete implementation for leaf nodes.""" - - # Default values for instance variables - _prefix = "" # Whitespace and comments preceding this token in the input - lineno = 0 # Line where this token starts in the input - column = 0 # Column where this token tarts in the input - - def __init__(self, type, value, - context=None, - prefix=None, - fixers_applied=[]): - """ - Initializer. - - Takes a type constant (a token number < 256), a string value, and an - optional context keyword argument. - """ - assert 0 <= type < 256, type - if context is not None: - self._prefix, (self.lineno, self.column) = context - self.type = type - self.value = value - if prefix is not None: - self._prefix = prefix - self.fixers_applied = fixers_applied[:] - - def __repr__(self): - """Return a canonical string representation.""" - return "%s(%r, %r)" % (self.__class__.__name__, - self.type, - self.value) - - def __unicode__(self): - """ - Return a pretty string representation. - - This reproduces the input source exactly. - """ - return self.prefix + str(self.value) - - if sys.version_info > (3, 0): - __str__ = __unicode__ - - def _eq(self, other): - """Compare two nodes for equality.""" - return (self.type, self.value) == (other.type, other.value) - - def clone(self): - """Return a cloned (deep) copy of self.""" - return Leaf(self.type, self.value, - (self.prefix, (self.lineno, self.column)), - fixers_applied=self.fixers_applied) - - def leaves(self): - yield self - - def post_order(self): - """Return a post-order iterator for the tree.""" - yield self - - def pre_order(self): - """Return a pre-order iterator for the tree.""" - yield self - - @property - def prefix(self): - """ - The whitespace and comments preceding this token in the input. - """ - return self._prefix - - @prefix.setter - def prefix(self, prefix): - self.changed() - self._prefix = prefix - -def convert(gr, raw_node): - """ - Convert raw node information to a Node or Leaf instance. - - This is passed to the parser driver which calls it whenever a reduction of a - grammar rule produces a new complete node, so that the tree is build - strictly bottom-up. - """ - type, value, context, children = raw_node - if children or type in gr.number2symbol: - # If there's exactly one child, return that child instead of - # creating a new node. - if len(children) == 1: - return children[0] - return Node(type, children, context=context) - else: - return Leaf(type, value, context=context) - - -class BasePattern(object): - - """ - A pattern is a tree matching pattern. - - It looks for a specific node type (token or symbol), and - optionally for a specific content. - - This is an abstract base class. There are three concrete - subclasses: - - - LeafPattern matches a single leaf node; - - NodePattern matches a single node (usually non-leaf); - - WildcardPattern matches a sequence of nodes of variable length. - """ - - # Defaults for instance variables - type = None # Node type (token if < 256, symbol if >= 256) - content = None # Optional content matching pattern - name = None # Optional name used to store match in results dict - - def __new__(cls, *args, **kwds): - """Constructor that prevents BasePattern from being instantiated.""" - assert cls is not BasePattern, "Cannot instantiate BasePattern" - return object.__new__(cls) - - def __repr__(self): - args = [type_repr(self.type), self.content, self.name] - while args and args[-1] is None: - del args[-1] - return "%s(%s)" % (self.__class__.__name__, ", ".join(map(repr, args))) - - def optimize(self): - """ - A subclass can define this as a hook for optimizations. - - Returns either self or another node with the same effect. - """ - return self - - def match(self, node, results=None): - """ - Does this pattern exactly match a node? - - Returns True if it matches, False if not. - - If results is not None, it must be a dict which will be - updated with the nodes matching named subpatterns. - - Default implementation for non-wildcard patterns. - """ - if self.type is not None and node.type != self.type: - return False - if self.content is not None: - r = None - if results is not None: - r = {} - if not self._submatch(node, r): - return False - if r: - results.update(r) - if results is not None and self.name: - results[self.name] = node - return True - - def match_seq(self, nodes, results=None): - """ - Does this pattern exactly match a sequence of nodes? - - Default implementation for non-wildcard patterns. - """ - if len(nodes) != 1: - return False - return self.match(nodes[0], results) - - def generate_matches(self, nodes): - """ - Generator yielding all matches for this pattern. - - Default implementation for non-wildcard patterns. - """ - r = {} - if nodes and self.match(nodes[0], r): - yield 1, r - - -class LeafPattern(BasePattern): - - def __init__(self, type=None, content=None, name=None): - """ - Initializer. Takes optional type, content, and name. - - The type, if given must be a token type (< 256). If not given, - this matches any *leaf* node; the content may still be required. - - The content, if given, must be a string. - - If a name is given, the matching node is stored in the results - dict under that key. - """ - if type is not None: - assert 0 <= type < 256, type - if content is not None: - assert isinstance(content, str), repr(content) - self.type = type - self.content = content - self.name = name - - def match(self, node, results=None): - """Override match() to insist on a leaf node.""" - if not isinstance(node, Leaf): - return False - return BasePattern.match(self, node, results) - - def _submatch(self, node, results=None): - """ - Match the pattern's content to the node's children. - - This assumes the node type matches and self.content is not None. - - Returns True if it matches, False if not. - - If results is not None, it must be a dict which will be - updated with the nodes matching named subpatterns. - - When returning False, the results dict may still be updated. - """ - return self.content == node.value - - -class NodePattern(BasePattern): - - wildcards = False - - def __init__(self, type=None, content=None, name=None): - """ - Initializer. Takes optional type, content, and name. - - The type, if given, must be a symbol type (>= 256). If the - type is None this matches *any* single node (leaf or not), - except if content is not None, in which it only matches - non-leaf nodes that also match the content pattern. - - The content, if not None, must be a sequence of Patterns that - must match the node's children exactly. If the content is - given, the type must not be None. - - If a name is given, the matching node is stored in the results - dict under that key. - """ - if type is not None: - assert type >= 256, type - if content is not None: - assert not isinstance(content, str), repr(content) - content = list(content) - for i, item in enumerate(content): - assert isinstance(item, BasePattern), (i, item) - if isinstance(item, WildcardPattern): - self.wildcards = True - self.type = type - self.content = content - self.name = name - - def _submatch(self, node, results=None): - """ - Match the pattern's content to the node's children. - - This assumes the node type matches and self.content is not None. - - Returns True if it matches, False if not. - - If results is not None, it must be a dict which will be - updated with the nodes matching named subpatterns. - - When returning False, the results dict may still be updated. - """ - if self.wildcards: - for c, r in generate_matches(self.content, node.children): - if c == len(node.children): - if results is not None: - results.update(r) - return True - return False - if len(self.content) != len(node.children): - return False - for subpattern, child in zip(self.content, node.children): - if not subpattern.match(child, results): - return False - return True - - -class WildcardPattern(BasePattern): - - """ - A wildcard pattern can match zero or more nodes. - - This has all the flexibility needed to implement patterns like: - - .* .+ .? .{m,n} - (a b c | d e | f) - (...)* (...)+ (...)? (...){m,n} - - except it always uses non-greedy matching. - """ - - def __init__(self, content=None, min=0, max=HUGE, name=None): - """ - Initializer. - - Args: - content: optional sequence of subsequences of patterns; - if absent, matches one node; - if present, each subsequence is an alternative [*] - min: optional minimum number of times to match, default 0 - max: optional maximum number of times to match, default HUGE - name: optional name assigned to this match - - [*] Thus, if content is [[a, b, c], [d, e], [f, g, h]] this is - equivalent to (a b c | d e | f g h); if content is None, - this is equivalent to '.' in regular expression terms. - The min and max parameters work as follows: - min=0, max=maxint: .* - min=1, max=maxint: .+ - min=0, max=1: .? - min=1, max=1: . - If content is not None, replace the dot with the parenthesized - list of alternatives, e.g. (a b c | d e | f g h)* - """ - assert 0 <= min <= max <= HUGE, (min, max) - if content is not None: - content = tuple(map(tuple, content)) # Protect against alterations - # Check sanity of alternatives - assert len(content), repr(content) # Can't have zero alternatives - for alt in content: - assert len(alt), repr(alt) # Can have empty alternatives - self.content = content - self.min = min - self.max = max - self.name = name - - def optimize(self): - """Optimize certain stacked wildcard patterns.""" - subpattern = None - if (self.content is not None and - len(self.content) == 1 and len(self.content[0]) == 1): - subpattern = self.content[0][0] - if self.min == 1 and self.max == 1: - if self.content is None: - return NodePattern(name=self.name) - if subpattern is not None and self.name == subpattern.name: - return subpattern.optimize() - if (self.min <= 1 and isinstance(subpattern, WildcardPattern) and - subpattern.min <= 1 and self.name == subpattern.name): - return WildcardPattern(subpattern.content, - self.min*subpattern.min, - self.max*subpattern.max, - subpattern.name) - return self - - def match(self, node, results=None): - """Does this pattern exactly match a node?""" - return self.match_seq([node], results) - - def match_seq(self, nodes, results=None): - """Does this pattern exactly match a sequence of nodes?""" - for c, r in self.generate_matches(nodes): - if c == len(nodes): - if results is not None: - results.update(r) - if self.name: - results[self.name] = list(nodes) - return True - return False - - def generate_matches(self, nodes): - """ - Generator yielding matches for a sequence of nodes. - - Args: - nodes: sequence of nodes - - Yields: - (count, results) tuples where: - count: the match comprises nodes[:count]; - results: dict containing named submatches. - """ - if self.content is None: - # Shortcut for special case (see __init__.__doc__) - for count in range(self.min, 1 + min(len(nodes), self.max)): - r = {} - if self.name: - r[self.name] = nodes[:count] - yield count, r - elif self.name == "bare_name": - yield self._bare_name_matches(nodes) - else: - # The reason for this is that hitting the recursion limit usually - # results in some ugly messages about how RuntimeErrors are being - # ignored. We only have to do this on CPython, though, because other - # implementations don't have this nasty bug in the first place. - if hasattr(sys, "getrefcount"): - save_stderr = sys.stderr - sys.stderr = StringIO() - try: - for count, r in self._recursive_matches(nodes, 0): - if self.name: - r[self.name] = nodes[:count] - yield count, r - except RuntimeError: - # Fall back to the iterative pattern matching scheme if the - # recursive scheme hits the recursion limit (RecursionError). - for count, r in self._iterative_matches(nodes): - if self.name: - r[self.name] = nodes[:count] - yield count, r - finally: - if hasattr(sys, "getrefcount"): - sys.stderr = save_stderr - - def _iterative_matches(self, nodes): - """Helper to iteratively yield the matches.""" - nodelen = len(nodes) - if 0 >= self.min: - yield 0, {} - - results = [] - # generate matches that use just one alt from self.content - for alt in self.content: - for c, r in generate_matches(alt, nodes): - yield c, r - results.append((c, r)) - - # for each match, iterate down the nodes - while results: - new_results = [] - for c0, r0 in results: - # stop if the entire set of nodes has been matched - if c0 < nodelen and c0 <= self.max: - for alt in self.content: - for c1, r1 in generate_matches(alt, nodes[c0:]): - if c1 > 0: - r = {} - r.update(r0) - r.update(r1) - yield c0 + c1, r - new_results.append((c0 + c1, r)) - results = new_results - - def _bare_name_matches(self, nodes): - """Special optimized matcher for bare_name.""" - count = 0 - r = {} - done = False - max = len(nodes) - while not done and count < max: - done = True - for leaf in self.content: - if leaf[0].match(nodes[count], r): - count += 1 - done = False - break - r[self.name] = nodes[:count] - return count, r - - def _recursive_matches(self, nodes, count): - """Helper to recursively yield the matches.""" - assert self.content is not None - if count >= self.min: - yield 0, {} - if count < self.max: - for alt in self.content: - for c0, r0 in generate_matches(alt, nodes): - for c1, r1 in self._recursive_matches(nodes[c0:], count+1): - r = {} - r.update(r0) - r.update(r1) - yield c0 + c1, r - - -class NegatedPattern(BasePattern): - - def __init__(self, content=None): - """ - Initializer. - - The argument is either a pattern or None. If it is None, this - only matches an empty sequence (effectively '$' in regex - lingo). If it is not None, this matches whenever the argument - pattern doesn't have any matches. - """ - if content is not None: - assert isinstance(content, BasePattern), repr(content) - self.content = content - - def match(self, node): - # We never match a node in its entirety - return False - - def match_seq(self, nodes): - # We only match an empty sequence of nodes in its entirety - return len(nodes) == 0 - - def generate_matches(self, nodes): - if self.content is None: - # Return a match if there is an empty sequence - if len(nodes) == 0: - yield 0, {} - else: - # Return a match if the argument pattern has no matches - for c, r in self.content.generate_matches(nodes): - return - yield 0, {} - - -def generate_matches(patterns, nodes): - """ - Generator yielding matches for a sequence of patterns and nodes. - - Args: - patterns: a sequence of patterns - nodes: a sequence of nodes - - Yields: - (count, results) tuples where: - count: the entire sequence of patterns matches nodes[:count]; - results: dict containing named submatches. - """ - if not patterns: - yield 0, {} - else: - p, rest = patterns[0], patterns[1:] - for c0, r0 in p.generate_matches(nodes): - if not rest: - yield c0, r0 - else: - for c1, r1 in generate_matches(rest, nodes[c0:]): - r = {} - r.update(r0) - r.update(r1) - yield c0 + c1, r diff --git a/Lib/lib2to3/refactor.py b/Lib/lib2to3/refactor.py deleted file mode 100644 index 3a5aafffc6df07..00000000000000 --- a/Lib/lib2to3/refactor.py +++ /dev/null @@ -1,732 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Refactoring framework. - -Used as a main program, this can refactor any number of files and/or -recursively descend down directories. Imported as a module, this -provides infrastructure to write your own refactoring tool. -""" - -__author__ = "Guido van Rossum " - - -# Python imports -import io -import os -import pkgutil -import sys -import logging -import operator -import collections -from itertools import chain - -# Local imports -from .pgen2 import driver, tokenize, token -from .fixer_util import find_root -from . import pytree, pygram -from . import btm_matcher as bm - - -def get_all_fix_names(fixer_pkg, remove_prefix=True): - """Return a sorted list of all available fix names in the given package.""" - pkg = __import__(fixer_pkg, [], [], ["*"]) - fix_names = [] - for finder, name, ispkg in pkgutil.iter_modules(pkg.__path__): - if name.startswith("fix_"): - if remove_prefix: - name = name[4:] - fix_names.append(name) - return fix_names - - -class _EveryNode(Exception): - pass - - -def _get_head_types(pat): - """ Accepts a pytree Pattern Node and returns a set - of the pattern types which will match first. """ - - if isinstance(pat, (pytree.NodePattern, pytree.LeafPattern)): - # NodePatters must either have no type and no content - # or a type and content -- so they don't get any farther - # Always return leafs - if pat.type is None: - raise _EveryNode - return {pat.type} - - if isinstance(pat, pytree.NegatedPattern): - if pat.content: - return _get_head_types(pat.content) - raise _EveryNode # Negated Patterns don't have a type - - if isinstance(pat, pytree.WildcardPattern): - # Recurse on each node in content - r = set() - for p in pat.content: - for x in p: - r.update(_get_head_types(x)) - return r - - raise Exception("Oh no! I don't understand pattern %s" %(pat)) - - -def _get_headnode_dict(fixer_list): - """ Accepts a list of fixers and returns a dictionary - of head node type --> fixer list. """ - head_nodes = collections.defaultdict(list) - every = [] - for fixer in fixer_list: - if fixer.pattern: - try: - heads = _get_head_types(fixer.pattern) - except _EveryNode: - every.append(fixer) - else: - for node_type in heads: - head_nodes[node_type].append(fixer) - else: - if fixer._accept_type is not None: - head_nodes[fixer._accept_type].append(fixer) - else: - every.append(fixer) - for node_type in chain(pygram.python_grammar.symbol2number.values(), - pygram.python_grammar.tokens): - head_nodes[node_type].extend(every) - return dict(head_nodes) - - -def get_fixers_from_package(pkg_name): - """ - Return the fully qualified names for fixers in the package pkg_name. - """ - return [pkg_name + "." + fix_name - for fix_name in get_all_fix_names(pkg_name, False)] - -def _identity(obj): - return obj - - -def _detect_future_features(source): - have_docstring = False - gen = tokenize.generate_tokens(io.StringIO(source).readline) - def advance(): - tok = next(gen) - return tok[0], tok[1] - ignore = frozenset({token.NEWLINE, tokenize.NL, token.COMMENT}) - features = set() - try: - while True: - tp, value = advance() - if tp in ignore: - continue - elif tp == token.STRING: - if have_docstring: - break - have_docstring = True - elif tp == token.NAME and value == "from": - tp, value = advance() - if tp != token.NAME or value != "__future__": - break - tp, value = advance() - if tp != token.NAME or value != "import": - break - tp, value = advance() - if tp == token.OP and value == "(": - tp, value = advance() - while tp == token.NAME: - features.add(value) - tp, value = advance() - if tp != token.OP or value != ",": - break - tp, value = advance() - else: - break - except StopIteration: - pass - return frozenset(features) - - -class FixerError(Exception): - """A fixer could not be loaded.""" - - -class RefactoringTool(object): - - _default_options = {"print_function" : False, - "exec_function": False, - "write_unchanged_files" : False} - - CLASS_PREFIX = "Fix" # The prefix for fixer classes - FILE_PREFIX = "fix_" # The prefix for modules with a fixer within - - def __init__(self, fixer_names, options=None, explicit=None): - """Initializer. - - Args: - fixer_names: a list of fixers to import - options: a dict with configuration. - explicit: a list of fixers to run even if they are explicit. - """ - self.fixers = fixer_names - self.explicit = explicit or [] - self.options = self._default_options.copy() - if options is not None: - self.options.update(options) - self.grammar = pygram.python_grammar.copy() - - if self.options['print_function']: - del self.grammar.keywords["print"] - elif self.options['exec_function']: - del self.grammar.keywords["exec"] - - # When this is True, the refactor*() methods will call write_file() for - # files processed even if they were not changed during refactoring. If - # and only if the refactor method's write parameter was True. - self.write_unchanged_files = self.options.get("write_unchanged_files") - self.errors = [] - self.logger = logging.getLogger("RefactoringTool") - self.fixer_log = [] - self.wrote = False - self.driver = driver.Driver(self.grammar, - convert=pytree.convert, - logger=self.logger) - self.pre_order, self.post_order = self.get_fixers() - - - self.files = [] # List of files that were or should be modified - - self.BM = bm.BottomMatcher() - self.bmi_pre_order = [] # Bottom Matcher incompatible fixers - self.bmi_post_order = [] - - for fixer in chain(self.post_order, self.pre_order): - if fixer.BM_compatible: - self.BM.add_fixer(fixer) - # remove fixers that will be handled by the bottom-up - # matcher - elif fixer in self.pre_order: - self.bmi_pre_order.append(fixer) - elif fixer in self.post_order: - self.bmi_post_order.append(fixer) - - self.bmi_pre_order_heads = _get_headnode_dict(self.bmi_pre_order) - self.bmi_post_order_heads = _get_headnode_dict(self.bmi_post_order) - - - - def get_fixers(self): - """Inspects the options to load the requested patterns and handlers. - - Returns: - (pre_order, post_order), where pre_order is the list of fixers that - want a pre-order AST traversal, and post_order is the list that want - post-order traversal. - """ - pre_order_fixers = [] - post_order_fixers = [] - for fix_mod_path in self.fixers: - mod = __import__(fix_mod_path, {}, {}, ["*"]) - fix_name = fix_mod_path.rsplit(".", 1)[-1] - if fix_name.startswith(self.FILE_PREFIX): - fix_name = fix_name[len(self.FILE_PREFIX):] - parts = fix_name.split("_") - class_name = self.CLASS_PREFIX + "".join([p.title() for p in parts]) - try: - fix_class = getattr(mod, class_name) - except AttributeError: - raise FixerError("Can't find %s.%s" % (fix_name, class_name)) from None - fixer = fix_class(self.options, self.fixer_log) - if fixer.explicit and self.explicit is not True and \ - fix_mod_path not in self.explicit: - self.log_message("Skipping optional fixer: %s", fix_name) - continue - - self.log_debug("Adding transformation: %s", fix_name) - if fixer.order == "pre": - pre_order_fixers.append(fixer) - elif fixer.order == "post": - post_order_fixers.append(fixer) - else: - raise FixerError("Illegal fixer order: %r" % fixer.order) - - key_func = operator.attrgetter("run_order") - pre_order_fixers.sort(key=key_func) - post_order_fixers.sort(key=key_func) - return (pre_order_fixers, post_order_fixers) - - def log_error(self, msg, *args, **kwds): - """Called when an error occurs.""" - raise - - def log_message(self, msg, *args): - """Hook to log a message.""" - if args: - msg = msg % args - self.logger.info(msg) - - def log_debug(self, msg, *args): - if args: - msg = msg % args - self.logger.debug(msg) - - def print_output(self, old_text, new_text, filename, equal): - """Called with the old version, new version, and filename of a - refactored file.""" - pass - - def refactor(self, items, write=False, doctests_only=False): - """Refactor a list of files and directories.""" - - for dir_or_file in items: - if os.path.isdir(dir_or_file): - self.refactor_dir(dir_or_file, write, doctests_only) - else: - self.refactor_file(dir_or_file, write, doctests_only) - - def refactor_dir(self, dir_name, write=False, doctests_only=False): - """Descends down a directory and refactor every Python file found. - - Python files are assumed to have a .py extension. - - Files and subdirectories starting with '.' are skipped. - """ - py_ext = os.extsep + "py" - for dirpath, dirnames, filenames in os.walk(dir_name): - self.log_debug("Descending into %s", dirpath) - dirnames.sort() - filenames.sort() - for name in filenames: - if (not name.startswith(".") and - os.path.splitext(name)[1] == py_ext): - fullname = os.path.join(dirpath, name) - self.refactor_file(fullname, write, doctests_only) - # Modify dirnames in-place to remove subdirs with leading dots - dirnames[:] = [dn for dn in dirnames if not dn.startswith(".")] - - def _read_python_source(self, filename): - """ - Do our best to decode a Python source file correctly. - """ - try: - f = open(filename, "rb") - except OSError as err: - self.log_error("Can't open %s: %s", filename, err) - return None, None - try: - encoding = tokenize.detect_encoding(f.readline)[0] - finally: - f.close() - with io.open(filename, "r", encoding=encoding, newline='') as f: - return f.read(), encoding - - def refactor_file(self, filename, write=False, doctests_only=False): - """Refactors a file.""" - input, encoding = self._read_python_source(filename) - if input is None: - # Reading the file failed. - return - input += "\n" # Silence certain parse errors - if doctests_only: - self.log_debug("Refactoring doctests in %s", filename) - output = self.refactor_docstring(input, filename) - if self.write_unchanged_files or output != input: - self.processed_file(output, filename, input, write, encoding) - else: - self.log_debug("No doctest changes in %s", filename) - else: - tree = self.refactor_string(input, filename) - if self.write_unchanged_files or (tree and tree.was_changed): - # The [:-1] is to take off the \n we added earlier - self.processed_file(str(tree)[:-1], filename, - write=write, encoding=encoding) - else: - self.log_debug("No changes in %s", filename) - - def refactor_string(self, data, name): - """Refactor a given input string. - - Args: - data: a string holding the code to be refactored. - name: a human-readable name for use in error/log messages. - - Returns: - An AST corresponding to the refactored input stream; None if - there were errors during the parse. - """ - features = _detect_future_features(data) - if "print_function" in features: - self.driver.grammar = pygram.python_grammar_no_print_statement - try: - tree = self.driver.parse_string(data) - except Exception as err: - self.log_error("Can't parse %s: %s: %s", - name, err.__class__.__name__, err) - return - finally: - self.driver.grammar = self.grammar - tree.future_features = features - self.log_debug("Refactoring %s", name) - self.refactor_tree(tree, name) - return tree - - def refactor_stdin(self, doctests_only=False): - input = sys.stdin.read() - if doctests_only: - self.log_debug("Refactoring doctests in stdin") - output = self.refactor_docstring(input, "") - if self.write_unchanged_files or output != input: - self.processed_file(output, "", input) - else: - self.log_debug("No doctest changes in stdin") - else: - tree = self.refactor_string(input, "") - if self.write_unchanged_files or (tree and tree.was_changed): - self.processed_file(str(tree), "", input) - else: - self.log_debug("No changes in stdin") - - def refactor_tree(self, tree, name): - """Refactors a parse tree (modifying the tree in place). - - For compatible patterns the bottom matcher module is - used. Otherwise the tree is traversed node-to-node for - matches. - - Args: - tree: a pytree.Node instance representing the root of the tree - to be refactored. - name: a human-readable name for this tree. - - Returns: - True if the tree was modified, False otherwise. - """ - - for fixer in chain(self.pre_order, self.post_order): - fixer.start_tree(tree, name) - - #use traditional matching for the incompatible fixers - self.traverse_by(self.bmi_pre_order_heads, tree.pre_order()) - self.traverse_by(self.bmi_post_order_heads, tree.post_order()) - - # obtain a set of candidate nodes - match_set = self.BM.run(tree.leaves()) - - while any(match_set.values()): - for fixer in self.BM.fixers: - if fixer in match_set and match_set[fixer]: - #sort by depth; apply fixers from bottom(of the AST) to top - match_set[fixer].sort(key=pytree.Base.depth, reverse=True) - - if fixer.keep_line_order: - #some fixers(eg fix_imports) must be applied - #with the original file's line order - match_set[fixer].sort(key=pytree.Base.get_lineno) - - for node in list(match_set[fixer]): - if node in match_set[fixer]: - match_set[fixer].remove(node) - - try: - find_root(node) - except ValueError: - # this node has been cut off from a - # previous transformation ; skip - continue - - if node.fixers_applied and fixer in node.fixers_applied: - # do not apply the same fixer again - continue - - results = fixer.match(node) - - if results: - new = fixer.transform(node, results) - if new is not None: - node.replace(new) - #new.fixers_applied.append(fixer) - for node in new.post_order(): - # do not apply the fixer again to - # this or any subnode - if not node.fixers_applied: - node.fixers_applied = [] - node.fixers_applied.append(fixer) - - # update the original match set for - # the added code - new_matches = self.BM.run(new.leaves()) - for fxr in new_matches: - if not fxr in match_set: - match_set[fxr]=[] - - match_set[fxr].extend(new_matches[fxr]) - - for fixer in chain(self.pre_order, self.post_order): - fixer.finish_tree(tree, name) - return tree.was_changed - - def traverse_by(self, fixers, traversal): - """Traverse an AST, applying a set of fixers to each node. - - This is a helper method for refactor_tree(). - - Args: - fixers: a list of fixer instances. - traversal: a generator that yields AST nodes. - - Returns: - None - """ - if not fixers: - return - for node in traversal: - for fixer in fixers[node.type]: - results = fixer.match(node) - if results: - new = fixer.transform(node, results) - if new is not None: - node.replace(new) - node = new - - def processed_file(self, new_text, filename, old_text=None, write=False, - encoding=None): - """ - Called when a file has been refactored and there may be changes. - """ - self.files.append(filename) - if old_text is None: - old_text = self._read_python_source(filename)[0] - if old_text is None: - return - equal = old_text == new_text - self.print_output(old_text, new_text, filename, equal) - if equal: - self.log_debug("No changes to %s", filename) - if not self.write_unchanged_files: - return - if write: - self.write_file(new_text, filename, old_text, encoding) - else: - self.log_debug("Not writing changes to %s", filename) - - def write_file(self, new_text, filename, old_text, encoding=None): - """Writes a string to a file. - - It first shows a unified diff between the old text and the new text, and - then rewrites the file; the latter is only done if the write option is - set. - """ - try: - fp = io.open(filename, "w", encoding=encoding, newline='') - except OSError as err: - self.log_error("Can't create %s: %s", filename, err) - return - - with fp: - try: - fp.write(new_text) - except OSError as err: - self.log_error("Can't write %s: %s", filename, err) - self.log_debug("Wrote changes to %s", filename) - self.wrote = True - - PS1 = ">>> " - PS2 = "... " - - def refactor_docstring(self, input, filename): - """Refactors a docstring, looking for doctests. - - This returns a modified version of the input string. It looks - for doctests, which start with a ">>>" prompt, and may be - continued with "..." prompts, as long as the "..." is indented - the same as the ">>>". - - (Unfortunately we can't use the doctest module's parser, - since, like most parsers, it is not geared towards preserving - the original source.) - """ - result = [] - block = None - block_lineno = None - indent = None - lineno = 0 - for line in input.splitlines(keepends=True): - lineno += 1 - if line.lstrip().startswith(self.PS1): - if block is not None: - result.extend(self.refactor_doctest(block, block_lineno, - indent, filename)) - block_lineno = lineno - block = [line] - i = line.find(self.PS1) - indent = line[:i] - elif (indent is not None and - (line.startswith(indent + self.PS2) or - line == indent + self.PS2.rstrip() + "\n")): - block.append(line) - else: - if block is not None: - result.extend(self.refactor_doctest(block, block_lineno, - indent, filename)) - block = None - indent = None - result.append(line) - if block is not None: - result.extend(self.refactor_doctest(block, block_lineno, - indent, filename)) - return "".join(result) - - def refactor_doctest(self, block, lineno, indent, filename): - """Refactors one doctest. - - A doctest is given as a block of lines, the first of which starts - with ">>>" (possibly indented), while the remaining lines start - with "..." (identically indented). - - """ - try: - tree = self.parse_block(block, lineno, indent) - except Exception as err: - if self.logger.isEnabledFor(logging.DEBUG): - for line in block: - self.log_debug("Source: %s", line.rstrip("\n")) - self.log_error("Can't parse docstring in %s line %s: %s: %s", - filename, lineno, err.__class__.__name__, err) - return block - if self.refactor_tree(tree, filename): - new = str(tree).splitlines(keepends=True) - # Undo the adjustment of the line numbers in wrap_toks() below. - clipped, new = new[:lineno-1], new[lineno-1:] - assert clipped == ["\n"] * (lineno-1), clipped - if not new[-1].endswith("\n"): - new[-1] += "\n" - block = [indent + self.PS1 + new.pop(0)] - if new: - block += [indent + self.PS2 + line for line in new] - return block - - def summarize(self): - if self.wrote: - were = "were" - else: - were = "need to be" - if not self.files: - self.log_message("No files %s modified.", were) - else: - self.log_message("Files that %s modified:", were) - for file in self.files: - self.log_message(file) - if self.fixer_log: - self.log_message("Warnings/messages while refactoring:") - for message in self.fixer_log: - self.log_message(message) - if self.errors: - if len(self.errors) == 1: - self.log_message("There was 1 error:") - else: - self.log_message("There were %d errors:", len(self.errors)) - for msg, args, kwds in self.errors: - self.log_message(msg, *args, **kwds) - - def parse_block(self, block, lineno, indent): - """Parses a block into a tree. - - This is necessary to get correct line number / offset information - in the parser diagnostics and embedded into the parse tree. - """ - tree = self.driver.parse_tokens(self.wrap_toks(block, lineno, indent)) - tree.future_features = frozenset() - return tree - - def wrap_toks(self, block, lineno, indent): - """Wraps a tokenize stream to systematically modify start/end.""" - tokens = tokenize.generate_tokens(self.gen_lines(block, indent).__next__) - for type, value, (line0, col0), (line1, col1), line_text in tokens: - line0 += lineno - 1 - line1 += lineno - 1 - # Don't bother updating the columns; this is too complicated - # since line_text would also have to be updated and it would - # still break for tokens spanning lines. Let the user guess - # that the column numbers for doctests are relative to the - # end of the prompt string (PS1 or PS2). - yield type, value, (line0, col0), (line1, col1), line_text - - - def gen_lines(self, block, indent): - """Generates lines as expected by tokenize from a list of lines. - - This strips the first len(indent + self.PS1) characters off each line. - """ - prefix1 = indent + self.PS1 - prefix2 = indent + self.PS2 - prefix = prefix1 - for line in block: - if line.startswith(prefix): - yield line[len(prefix):] - elif line == prefix.rstrip() + "\n": - yield "\n" - else: - raise AssertionError("line=%r, prefix=%r" % (line, prefix)) - prefix = prefix2 - while True: - yield "" - - -class MultiprocessingUnsupported(Exception): - pass - - -class MultiprocessRefactoringTool(RefactoringTool): - - def __init__(self, *args, **kwargs): - super(MultiprocessRefactoringTool, self).__init__(*args, **kwargs) - self.queue = None - self.output_lock = None - - def refactor(self, items, write=False, doctests_only=False, - num_processes=1): - if num_processes == 1: - return super(MultiprocessRefactoringTool, self).refactor( - items, write, doctests_only) - try: - import multiprocessing - except ImportError: - raise MultiprocessingUnsupported - if self.queue is not None: - raise RuntimeError("already doing multiple processes") - self.queue = multiprocessing.JoinableQueue() - self.output_lock = multiprocessing.Lock() - processes = [multiprocessing.Process(target=self._child) - for i in range(num_processes)] - try: - for p in processes: - p.start() - super(MultiprocessRefactoringTool, self).refactor(items, write, - doctests_only) - finally: - self.queue.join() - for i in range(num_processes): - self.queue.put(None) - for p in processes: - if p.is_alive(): - p.join() - self.queue = None - - def _child(self): - task = self.queue.get() - while task is not None: - args, kwargs = task - try: - super(MultiprocessRefactoringTool, self).refactor_file( - *args, **kwargs) - finally: - self.queue.task_done() - task = self.queue.get() - - def refactor_file(self, *args, **kwargs): - if self.queue is not None: - self.queue.put((args, kwargs)) - else: - return super(MultiprocessRefactoringTool, self).refactor_file( - *args, **kwargs) diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 16c54a6a4f7a2f..a68281d3e359fd 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -29,6 +29,7 @@ import io import logging import logging.handlers +import os import queue import re import struct @@ -60,15 +61,24 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=Non """ import configparser + if isinstance(fname, str): + if not os.path.exists(fname): + raise FileNotFoundError(f"{fname} doesn't exist") + elif not os.path.getsize(fname): + raise RuntimeError(f'{fname} is an empty file') + if isinstance(fname, configparser.RawConfigParser): cp = fname else: - cp = configparser.ConfigParser(defaults) - if hasattr(fname, 'readline'): - cp.read_file(fname) - else: - encoding = io.text_encoding(encoding) - cp.read(fname, encoding=encoding) + try: + cp = configparser.ConfigParser(defaults) + if hasattr(fname, 'readline'): + cp.read_file(fname) + else: + encoding = io.text_encoding(encoding) + cp.read(fname, encoding=encoding) + except configparser.ParsingError as e: + raise RuntimeError(f'{fname} is invalid: {e}') formatters = _create_formatters(cp) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index 1a8822b9db012d..04eaea811cfbbe 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -722,11 +722,11 @@ def PipeClient(address): # Authentication stuff # -MESSAGE_LENGTH = 20 +MESSAGE_LENGTH = 40 # MUST be > 20 -CHALLENGE = b'#CHALLENGE#' -WELCOME = b'#WELCOME#' -FAILURE = b'#FAILURE#' +_CHALLENGE = b'#CHALLENGE#' +_WELCOME = b'#WELCOME#' +_FAILURE = b'#FAILURE#' # multiprocessing.connection Authentication Handshake Protocol Description # (as documented for reference after reading the existing code) @@ -750,7 +750,12 @@ def PipeClient(address): # ------------------------------ --------------------------------------- # 0. Open a connection on the pipe. # 1. Accept connection. -# 2. New random 20 bytes -> MESSAGE +# 2. Random 20+ bytes -> MESSAGE +# Modern servers always send +# more than 20 bytes and include +# a {digest} prefix on it with +# their preferred HMAC digest. +# Legacy ones send ==20 bytes. # 3. send 4 byte length (net order) # prefix followed by: # b'#CHALLENGE#' + MESSAGE @@ -763,14 +768,32 @@ def PipeClient(address): # 6. Assert that M1 starts with: # b'#CHALLENGE#' # 7. Strip that prefix from M1 into -> M2 -# 8. Compute HMAC-MD5 of AUTHKEY, M2 -> C_DIGEST +# 7.1. Parse M2: if it is exactly 20 bytes in +# length this indicates a legacy server +# supporting only HMAC-MD5. Otherwise the +# 7.2. preferred digest is looked up from an +# expected "{digest}" prefix on M2. No prefix +# or unsupported digest? <- AuthenticationError +# 7.3. Put divined algorithm name in -> D_NAME +# 8. Compute HMAC-D_NAME of AUTHKEY, M2 -> C_DIGEST # 9. Send 4 byte length prefix (net order) # followed by C_DIGEST bytes. -# 10. Compute HMAC-MD5 of AUTHKEY, -# MESSAGE into -> M_DIGEST. -# 11. Receive 4 or 4+8 byte length +# 10. Receive 4 or 4+8 byte length # prefix (#4 dance) -> SIZE. -# 12. Receive min(SIZE, 256) -> C_D. +# 11. Receive min(SIZE, 256) -> C_D. +# 11.1. Parse C_D: legacy servers +# accept it as is, "md5" -> D_NAME +# 11.2. modern servers check the length +# of C_D, IF it is 16 bytes? +# 11.2.1. "md5" -> D_NAME +# and skip to step 12. +# 11.3. longer? expect and parse a "{digest}" +# prefix into -> D_NAME. +# Strip the prefix and store remaining +# bytes in -> C_D. +# 11.4. Don't like D_NAME? <- AuthenticationError +# 12. Compute HMAC-D_NAME of AUTHKEY, +# MESSAGE into -> M_DIGEST. # 13. Compare M_DIGEST == C_D: # 14a: Match? Send length prefix & # b'#WELCOME#' @@ -787,42 +810,139 @@ def PipeClient(address): # # If this RETURNed, the connection remains open: it has been authenticated. # -# Length prefixes are used consistently even though every step so far has -# always been a singular specific fixed length. This may help us evolve -# the protocol in the future without breaking backwards compatibility. -# -# Similarly the initial challenge message from the serving side has always -# been 20 bytes, but clients can accept a 100+ so using the length of the -# opening challenge message as an indicator of protocol version may work. +# Length prefixes are used consistently. Even on the legacy protocol, this +# was good fortune and allowed us to evolve the protocol by using the length +# of the opening challenge or length of the returned digest as a signal as +# to which protocol the other end supports. + +_ALLOWED_DIGESTS = frozenset( + {b'md5', b'sha256', b'sha384', b'sha3_256', b'sha3_384'}) +_MAX_DIGEST_LEN = max(len(_) for _ in _ALLOWED_DIGESTS) + +# Old hmac-md5 only server versions from Python <=3.11 sent a message of this +# length. It happens to not match the length of any supported digest so we can +# use a message of this length to indicate that we should work in backwards +# compatible md5-only mode without a {digest_name} prefix on our response. +_MD5ONLY_MESSAGE_LENGTH = 20 +_MD5_DIGEST_LEN = 16 +_LEGACY_LENGTHS = (_MD5ONLY_MESSAGE_LENGTH, _MD5_DIGEST_LEN) + + +def _get_digest_name_and_payload(message: bytes) -> (str, bytes): + """Returns a digest name and the payload for a response hash. + + If a legacy protocol is detected based on the message length + or contents the digest name returned will be empty to indicate + legacy mode where MD5 and no digest prefix should be sent. + """ + # modern message format: b"{digest}payload" longer than 20 bytes + # legacy message format: 16 or 20 byte b"payload" + if len(message) in _LEGACY_LENGTHS: + # Either this was a legacy server challenge, or we're processing + # a reply from a legacy client that sent an unprefixed 16-byte + # HMAC-MD5 response. All messages using the modern protocol will + # be longer than either of these lengths. + return '', message + if (message.startswith(b'{') and + (curly := message.find(b'}', 1, _MAX_DIGEST_LEN+2)) > 0): + digest = message[1:curly] + if digest in _ALLOWED_DIGESTS: + payload = message[curly+1:] + return digest.decode('ascii'), payload + raise AuthenticationError( + 'unsupported message length, missing digest prefix, ' + f'or unsupported digest: {message=}') + + +def _create_response(authkey, message): + """Create a MAC based on authkey and message + + The MAC algorithm defaults to HMAC-MD5, unless MD5 is not available or + the message has a '{digest_name}' prefix. For legacy HMAC-MD5, the response + is the raw MAC, otherwise the response is prefixed with '{digest_name}', + e.g. b'{sha256}abcdefg...' + + Note: The MAC protects the entire message including the digest_name prefix. + """ + import hmac + digest_name = _get_digest_name_and_payload(message)[0] + # The MAC protects the entire message: digest header and payload. + if not digest_name: + # Legacy server without a {digest} prefix on message. + # Generate a legacy non-prefixed HMAC-MD5 reply. + try: + return hmac.new(authkey, message, 'md5').digest() + except ValueError: + # HMAC-MD5 is not available (FIPS mode?), fall back to + # HMAC-SHA2-256 modern protocol. The legacy server probably + # doesn't support it and will reject us anyways. :shrug: + digest_name = 'sha256' + # Modern protocol, indicate the digest used in the reply. + response = hmac.new(authkey, message, digest_name).digest() + return b'{%s}%s' % (digest_name.encode('ascii'), response) + + +def _verify_challenge(authkey, message, response): + """Verify MAC challenge + + If our message did not include a digest_name prefix, the client is allowed + to select a stronger digest_name from _ALLOWED_DIGESTS. + + In case our message is prefixed, a client cannot downgrade to a weaker + algorithm, because the MAC is calculated over the entire message + including the '{digest_name}' prefix. + """ + import hmac + response_digest, response_mac = _get_digest_name_and_payload(response) + response_digest = response_digest or 'md5' + try: + expected = hmac.new(authkey, message, response_digest).digest() + except ValueError: + raise AuthenticationError(f'{response_digest=} unsupported') + if len(expected) != len(response_mac): + raise AuthenticationError( + f'expected {response_digest!r} of length {len(expected)} ' + f'got {len(response_mac)}') + if not hmac.compare_digest(expected, response_mac): + raise AuthenticationError('digest received was wrong') -def deliver_challenge(connection, authkey): - import hmac +def deliver_challenge(connection, authkey: bytes, digest_name='sha256'): if not isinstance(authkey, bytes): raise ValueError( "Authkey must be bytes, not {0!s}".format(type(authkey))) + assert MESSAGE_LENGTH > _MD5ONLY_MESSAGE_LENGTH, "protocol constraint" message = os.urandom(MESSAGE_LENGTH) - connection.send_bytes(CHALLENGE + message) - digest = hmac.new(authkey, message, 'md5').digest() + message = b'{%s}%s' % (digest_name.encode('ascii'), message) + # Even when sending a challenge to a legacy client that does not support + # digest prefixes, they'll take the entire thing as a challenge and + # respond to it with a raw HMAC-MD5. + connection.send_bytes(_CHALLENGE + message) response = connection.recv_bytes(256) # reject large message - if response == digest: - connection.send_bytes(WELCOME) + try: + _verify_challenge(authkey, message, response) + except AuthenticationError: + connection.send_bytes(_FAILURE) + raise else: - connection.send_bytes(FAILURE) - raise AuthenticationError('digest received was wrong') + connection.send_bytes(_WELCOME) -def answer_challenge(connection, authkey): - import hmac + +def answer_challenge(connection, authkey: bytes): if not isinstance(authkey, bytes): raise ValueError( "Authkey must be bytes, not {0!s}".format(type(authkey))) message = connection.recv_bytes(256) # reject large message - assert message[:len(CHALLENGE)] == CHALLENGE, 'message = %r' % message - message = message[len(CHALLENGE):] - digest = hmac.new(authkey, message, 'md5').digest() + if not message.startswith(_CHALLENGE): + raise AuthenticationError( + f'Protocol error, expected challenge: {message=}') + message = message[len(_CHALLENGE):] + if len(message) < _MD5ONLY_MESSAGE_LENGTH: + raise AuthenticationError('challenge too short: {len(message)} bytes') + digest = _create_response(authkey, message) connection.send_bytes(digest) response = connection.recv_bytes(256) # reject large message - if response != WELCOME: + if response != _WELCOME: raise AuthenticationError('digest sent was rejected') # diff --git a/Lib/multiprocessing/process.py b/Lib/multiprocessing/process.py index c03c859baa795b..271ba3fd325138 100644 --- a/Lib/multiprocessing/process.py +++ b/Lib/multiprocessing/process.py @@ -61,7 +61,7 @@ def parent_process(): def _cleanup(): # check for processes which have finished for p in list(_children): - if p._popen.poll() is not None: + if (child_popen := p._popen) and child_popen.poll() is not None: _children.discard(p) # diff --git a/Lib/opcode.py b/Lib/opcode.py index 155466b1ab85f1..6bb2f1c140b15a 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -131,6 +131,7 @@ def pseudo_op(name, op, real_ops): def_op('RETURN_VALUE', 83) def_op('SETUP_ANNOTATIONS', 85) +def_op('LOAD_LOCALS', 87) def_op('POP_EXCEPT', 89) @@ -206,7 +207,6 @@ def pseudo_op(name, op, real_ops): def_op('LIST_APPEND', 145) def_op('SET_ADD', 146) def_op('MAP_ADD', 147) -def_op('LOAD_CLASSDEREF', 148) hasfree.append(148) def_op('COPY_FREE_VARS', 149) def_op('YIELD_VALUE', 150) @@ -228,9 +228,14 @@ def pseudo_op(name, op, real_ops): def_op('CALL_INTRINSIC_1', 173) def_op('CALL_INTRINSIC_2', 174) +name_op('LOAD_FROM_DICT_OR_GLOBALS', 175) +def_op('LOAD_FROM_DICT_OR_DEREF', 176) +hasfree.append(176) + # Instrumented instructions -MIN_INSTRUMENTED_OPCODE = 238 +MIN_INSTRUMENTED_OPCODE = 237 +def_op('INSTRUMENTED_LOAD_SUPER_ATTR', 237) def_op('INSTRUMENTED_POP_JUMP_IF_NONE', 238) def_op('INSTRUMENTED_POP_JUMP_IF_NOT_NONE', 239) def_op('INSTRUMENTED_RESUME', 240) @@ -318,12 +323,20 @@ def pseudo_op(name, op, real_ops): "INTRINSIC_ASYNC_GEN_WRAP", "INTRINSIC_UNARY_POSITIVE", "INTRINSIC_LIST_TO_TUPLE", + "INTRINSIC_TYPEVAR", + "INTRINSIC_PARAMSPEC", + "INTRINSIC_TYPEVARTUPLE", + "INTRINSIC_SUBSCRIPT_GENERIC", + "INTRINSIC_TYPEALIAS", ] _intrinsic_2_descs = [ - 'INTRINSIC_2_INVALID', - 'INTRINSIC_PREP_RERAISE_STAR', - ] + "INTRINSIC_2_INVALID", + "INTRINSIC_PREP_RERAISE_STAR", + "INTRINSIC_TYPEVAR_WITH_BOUND", + "INTRINSIC_TYPEVAR_WITH_CONSTRAINTS", + "INTRINSIC_SET_FUNCTION_TYPE_PARAMS", +] _specializations = { "BINARY_OP": [ diff --git a/Lib/pathlib.py b/Lib/pathlib.py index f7a059956eda1b..2d60dc83aeed10 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -86,6 +86,12 @@ def _make_selector(pattern_parts, flavour, case_sensitive): return cls(pat, child_parts, flavour, case_sensitive) +@functools.lru_cache(maxsize=256) +def _compile_pattern(pat, case_sensitive): + flags = re.NOFLAG if case_sensitive else re.IGNORECASE + return re.compile(fnmatch.translate(pat), flags).match + + class _Selector: """A selector matches a specific glob pattern part against the children of a given path.""" @@ -133,8 +139,7 @@ def __init__(self, pat, child_parts, flavour, case_sensitive): if case_sensitive is None: # TODO: evaluate case-sensitivity of each directory in _select_from() case_sensitive = _is_case_sensitive(flavour) - flags = re.NOFLAG if case_sensitive else re.IGNORECASE - self.match = re.compile(fnmatch.translate(pat), flags=flags).fullmatch + self.match = _compile_pattern(pat, case_sensitive) def _select_from(self, parent_path, scandir, follow_symlinks): follow_dirlinks = True if follow_symlinks is None else follow_symlinks @@ -682,22 +687,25 @@ def is_reserved(self): name = self._tail[-1].partition('.')[0].partition(':')[0].rstrip(' ') return name.upper() in _WIN_RESERVED_NAMES - def match(self, path_pattern): + def match(self, path_pattern, *, case_sensitive=None): """ Return True if this path matches the given pattern. """ + if case_sensitive is None: + case_sensitive = _is_case_sensitive(self._flavour) pat = self.with_segments(path_pattern) if not pat.parts: raise ValueError("empty pattern") - pat_parts = pat._parts_normcase - parts = self._parts_normcase + pat_parts = pat.parts + parts = self.parts if pat.drive or pat.root: if len(pat_parts) != len(parts): return False elif len(pat_parts) > len(parts): return False for part, pat in zip(reversed(parts), reversed(pat_parts)): - if not fnmatch.fnmatchcase(part, pat): + match = _compile_pattern(pat, case_sensitive) + if not match(part): return False return True diff --git a/Lib/pty.py b/Lib/pty.py index 6571050886bd1d..1d97994abef3c8 100644 --- a/Lib/pty.py +++ b/Lib/pty.py @@ -115,12 +115,6 @@ def fork(): # Parent and child process. return pid, master_fd -def _writen(fd, data): - """Write all the data to a descriptor.""" - while data: - n = os.write(fd, data) - data = data[n:] - def _read(fd): """Default read function.""" return os.read(fd, 1024) @@ -130,9 +124,42 @@ def _copy(master_fd, master_read=_read, stdin_read=_read): Copies pty master -> standard output (master_read) standard input -> pty master (stdin_read)""" - fds = [master_fd, STDIN_FILENO] - while fds: - rfds, _wfds, _xfds = select(fds, [], []) + if os.get_blocking(master_fd): + # If we write more than tty/ndisc is willing to buffer, we may block + # indefinitely. So we set master_fd to non-blocking temporarily during + # the copy operation. + os.set_blocking(master_fd, False) + try: + _copy(master_fd, master_read=master_read, stdin_read=stdin_read) + finally: + # restore blocking mode for backwards compatibility + os.set_blocking(master_fd, True) + return + high_waterlevel = 4096 + stdin_avail = master_fd != STDIN_FILENO + stdout_avail = master_fd != STDOUT_FILENO + i_buf = b'' + o_buf = b'' + while 1: + rfds = [] + wfds = [] + if stdin_avail and len(i_buf) < high_waterlevel: + rfds.append(STDIN_FILENO) + if stdout_avail and len(o_buf) < high_waterlevel: + rfds.append(master_fd) + if stdout_avail and len(o_buf) > 0: + wfds.append(STDOUT_FILENO) + if len(i_buf) > 0: + wfds.append(master_fd) + + rfds, wfds, _xfds = select(rfds, wfds, []) + + if STDOUT_FILENO in wfds: + try: + n = os.write(STDOUT_FILENO, o_buf) + o_buf = o_buf[n:] + except OSError: + stdout_avail = False if master_fd in rfds: # Some OSes signal EOF by returning an empty byte string, @@ -144,15 +171,18 @@ def _copy(master_fd, master_read=_read, stdin_read=_read): if not data: # Reached EOF. return # Assume the child process has exited and is # unreachable, so we clean up. - else: - os.write(STDOUT_FILENO, data) + o_buf += data + + if master_fd in wfds: + n = os.write(master_fd, i_buf) + i_buf = i_buf[n:] - if STDIN_FILENO in rfds: + if stdin_avail and STDIN_FILENO in rfds: data = stdin_read(STDIN_FILENO) if not data: - fds.remove(STDIN_FILENO) + stdin_avail = False else: - _writen(master_fd, data) + i_buf += data def spawn(argv, master_read=_read, stdin_read=_read): """Create a spawned process.""" diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 3aaaee67fa35a6..cb742992a48e8f 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Tue Apr 4 17:52:21 2023 +# Autogenerated by Sphinx on Mon May 22 14:02:15 2023 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -2573,9 +2573,12 @@ '\n' 'Any remaining exceptions that were not handled by any "except*" ' 'clause\n' - 'are re-raised at the end, combined into an exception group along ' - 'with\n' - 'all exceptions that were raised from within "except*" clauses.\n' + 'are re-raised at the end, along with all exceptions that were ' + 'raised\n' + 'from within the "except*" clauses. If this list contains more ' + 'than one\n' + 'exception to reraise, they are combined into an exception ' + 'group.\n' '\n' 'If the raised exception is not an exception group and its type ' 'matches\n' @@ -4587,8 +4590,7 @@ 'case\n' ' performance of a dict insertion, O(n^2) complexity. ' 'See\n' - ' http://www.ocert.org/advisories/ocert-2011-003.html ' - 'for\n' + ' http://ocert.org/advisories/ocert-2011-003.html for\n' ' details.Changing hash values affects the iteration ' 'order of sets.\n' ' Python has never made guarantees about this ordering ' @@ -4651,20 +4653,41 @@ 'traces of\n' ' Python programs.\n' '\n' - 'The debugger’s prompt is "(Pdb)". Typical usage to run a program ' - 'under\n' - 'control of the debugger is:\n' + 'The typical usage to break into the debugger is to insert:\n' '\n' - ' >>> import pdb\n' - ' >>> import mymodule\n' - " >>> pdb.run('mymodule.test()')\n" - ' > (0)?()\n' - ' (Pdb) continue\n' - ' > (1)?()\n' + ' import pdb; pdb.set_trace()\n' + '\n' + 'Or:\n' + '\n' + ' breakpoint()\n' + '\n' + 'at the location you want to break into the debugger, and then ' + 'run the\n' + 'program. You can then step through the code following this ' + 'statement,\n' + 'and continue running without the debugger using the "continue"\n' + 'command.\n' + '\n' + 'New in version 3.7: The built-in "breakpoint()", when called ' + 'with\n' + 'defaults, can be used instead of "import pdb; pdb.set_trace()".\n' + '\n' + ' def double(x):\n' + ' breakpoint()\n' + ' return x * 2\n' + ' val = 3\n' + ' print(f"{val} * 2 is {double(val)}")\n' + '\n' + 'The debugger’s prompt is "(Pdb)", which is the indicator that ' + 'you are\n' + 'in debug mode:\n' + '\n' + ' > ...(3)double()\n' + ' -> return x * 2\n' + ' (Pdb) p x\n' + ' 3\n' ' (Pdb) continue\n' - " NameError: 'spam'\n" - ' > (1)?()\n' - ' (Pdb)\n' + ' 3 * 2 is 6\n' '\n' 'Changed in version 3.3: Tab-completion via the "readline" module ' 'is\n' @@ -4672,13 +4695,12 @@ 'global\n' 'and local names are offered as arguments of the "p" command.\n' '\n' - '"pdb.py" can also be invoked as a script to debug other ' - 'scripts. For\n' - 'example:\n' + 'You can also invoke "pdb" from the command line to debug other\n' + 'scripts. For example:\n' '\n' ' python -m pdb myscript.py\n' '\n' - 'When invoked as a script, pdb will automatically enter ' + 'When invoked as a module, pdb will automatically enter ' 'post-mortem\n' 'debugging if the program being debugged exits abnormally. After ' 'post-\n' @@ -4690,47 +4712,43 @@ 'the\n' 'debugger upon program’s exit.\n' '\n' - 'New in version 3.2: "pdb.py" now accepts a "-c" option that ' - 'executes\n' - 'commands as if given in a ".pdbrc" file, see Debugger Commands.\n' + 'New in version 3.2: "-c" option is introduced to execute ' + 'commands as\n' + 'if given in a ".pdbrc" file, see Debugger Commands.\n' '\n' - 'New in version 3.7: "pdb.py" now accepts a "-m" option that ' - 'execute\n' - 'modules similar to the way "python -m" does. As with a script, ' - 'the\n' - 'debugger will pause execution just before the first line of the\n' - 'module.\n' - '\n' - 'The typical usage to break into the debugger is to insert:\n' + 'New in version 3.7: "-m" option is introduced to execute ' + 'modules\n' + 'similar to the way "python -m" does. As with a script, the ' + 'debugger\n' + 'will pause execution just before the first line of the module.\n' '\n' - ' import pdb; pdb.set_trace()\n' + 'Typical usage to execute a statement under control of the ' + 'debugger is:\n' '\n' - 'at the location you want to break into the debugger, and then ' - 'run the\n' - 'program. You can then step through the code following this ' - 'statement,\n' - 'and continue running without the debugger using the "continue"\n' - 'command.\n' - '\n' - 'New in version 3.7: The built-in "breakpoint()", when called ' - 'with\n' - 'defaults, can be used instead of "import pdb; pdb.set_trace()".\n' + ' >>> import pdb\n' + ' >>> def f(x):\n' + ' ... print(1 / x)\n' + ' >>> pdb.run("f(2)")\n' + ' > (1)()\n' + ' (Pdb) continue\n' + ' 0.5\n' + ' >>>\n' '\n' 'The typical usage to inspect a crashed program is:\n' '\n' ' >>> import pdb\n' - ' >>> import mymodule\n' - ' >>> mymodule.test()\n' + ' >>> def f(x):\n' + ' ... print(1 / x)\n' + ' ...\n' + ' >>> f(0)\n' ' Traceback (most recent call last):\n' ' File "", line 1, in \n' - ' File "./mymodule.py", line 4, in test\n' - ' test2()\n' - ' File "./mymodule.py", line 3, in test2\n' - ' print(spam)\n' - ' NameError: spam\n' + ' File "", line 2, in f\n' + ' ZeroDivisionError: division by zero\n' ' >>> pdb.pm()\n' - ' > ./mymodule.py(3)test2()\n' - ' -> print(spam)\n' + ' > (2)f()\n' + ' (Pdb) p x\n' + ' 0\n' ' (Pdb)\n' '\n' 'The module defines the following functions; each enters the ' @@ -4914,6 +4932,29 @@ 'implicit\n' 'string concatenation "\';\'\';\'" or "";"";"".\n' '\n' + 'To set a temporary global variable, use a *convenience ' + 'variable*. A\n' + '*convenience variable* is a variable whose name starts with ' + '"$". For\n' + 'example, "$foo = 1" sets a global variable "$foo" which you can ' + 'use in\n' + 'the debugger session. The *convenience variables* are cleared ' + 'when\n' + 'the program resumes execution so it’s less likely to interfere ' + 'with\n' + 'your program compared to using normal variables like "foo = 1".\n' + '\n' + 'There are three preset *convenience variables*:\n' + '\n' + '* "$_frame": the current frame you are debugging\n' + '\n' + '* "$_retval": the return value if the frame is returning\n' + '\n' + '* "$_exception": the exception if the frame is raising an ' + 'exception\n' + '\n' + 'New in version 3.12.\n' + '\n' 'If a file ".pdbrc" exists in the user’s home directory or in ' 'the\n' 'current directory, it is read with "\'utf-8\'" encoding and ' @@ -4949,9 +4990,9 @@ '\n' ' Print a stack trace, with the most recent frame at the ' 'bottom. An\n' - ' arrow indicates the current frame, which determines the ' - 'context of\n' - ' most commands.\n' + ' arrow (">") indicates the current frame, which determines ' + 'the\n' + ' context of most commands.\n' '\n' 'd(own) [count]\n' '\n' @@ -5007,7 +5048,7 @@ 'first\n' ' ask confirmation).\n' '\n' - 'disable [bpnumber ...]\n' + 'disable bpnumber [bpnumber ...]\n' '\n' ' Disable the breakpoints given as a space separated list of\n' ' breakpoint numbers. Disabling a breakpoint means it cannot ' @@ -5016,7 +5057,7 @@ 'breakpoint, it\n' ' remains in the list of breakpoints and can be (re-)enabled.\n' '\n' - 'enable [bpnumber ...]\n' + 'enable bpnumber [bpnumber ...]\n' '\n' ' Enable the breakpoints specified.\n' '\n' @@ -5179,7 +5220,9 @@ '\n' 'a(rgs)\n' '\n' - ' Print the argument list of the current function.\n' + ' Print the arguments of the current function and their ' + 'current\n' + ' values.\n' '\n' 'p expression\n' '\n' @@ -5217,6 +5260,54 @@ 'current\n' ' frame.\n' '\n' + ' Note:\n' + '\n' + ' Display evaluates *expression* and compares to the result ' + 'of the\n' + ' previous evaluation of *expression*, so when the result is\n' + ' mutable, display may not be able to pick up the changes.\n' + '\n' + ' Example:\n' + '\n' + ' lst = []\n' + ' breakpoint()\n' + ' pass\n' + ' lst.append(1)\n' + ' print(lst)\n' + '\n' + ' Display won’t realize "lst" has been changed because the ' + 'result of\n' + ' evaluation is modified in place by "lst.append(1)" before ' + 'being\n' + ' compared:\n' + '\n' + ' > example.py(3)()\n' + ' -> pass\n' + ' (Pdb) display lst\n' + ' display lst: []\n' + ' (Pdb) n\n' + ' > example.py(4)()\n' + ' -> lst.append(1)\n' + ' (Pdb) n\n' + ' > example.py(5)()\n' + ' -> print(lst)\n' + ' (Pdb)\n' + '\n' + ' You can do some tricks with copy mechanism to make it work:\n' + '\n' + ' > example.py(3)()\n' + ' -> pass\n' + ' (Pdb) display lst[:]\n' + ' display lst[:]: []\n' + ' (Pdb) n\n' + ' > example.py(4)()\n' + ' -> lst.append(1)\n' + ' (Pdb) n\n' + ' > example.py(5)()\n' + ' -> print(lst)\n' + ' display lst[:]: [1] [old: []]\n' + ' (Pdb)\n' + '\n' ' New in version 3.2.\n' '\n' 'undisplay [expression]\n' @@ -5283,14 +5374,14 @@ 'current\n' ' stack frame. The exclamation point can be omitted unless the ' 'first\n' - ' word of the statement resembles a debugger command, e.g.:' + ' word of the statement resembles a debugger command, e.g.:\n' '\n' ' (Pdb) ! n=42\n' ' (Pdb)\n' '\n' - ' To set a global variable, you can prefix the assignment command ' - ' with \n' - ' a "global" statement on the same line, e.g.:\n' + ' To set a global variable, you can prefix the assignment ' + 'command\n' + ' with a "global" statement on the same line, e.g.:\n' '\n' " (Pdb) global list_options; list_options = ['-l']\n" ' (Pdb)\n' @@ -5321,7 +5412,8 @@ '\n' 'retval\n' '\n' - ' Print the return value for the last return of a function.\n' + ' Print the return value for the last return of the current ' + 'function.\n' '\n' '-[ Footnotes ]-\n' '\n' @@ -9509,8 +9601,7 @@ ' by carefully chosen inputs that exploit the worst case\n' ' performance of a dict insertion, O(n^2) complexity. ' 'See\n' - ' http://www.ocert.org/advisories/ocert-2011-003.html ' - 'for\n' + ' http://ocert.org/advisories/ocert-2011-003.html for\n' ' details.Changing hash values affects the iteration ' 'order of sets.\n' ' Python has never made guarantees about this ordering ' @@ -10164,20 +10255,37 @@ 'Resolving MRO entries\n' '---------------------\n' '\n' - 'If a base that appears in class definition is not an ' + 'object.__mro_entries__(self, bases)\n' + '\n' + ' If a base that appears in a class definition is not an ' 'instance of\n' - '"type", then an "__mro_entries__" method is searched on it. ' - 'If found,\n' - 'it is called with the original bases tuple. This method must ' - 'return a\n' - 'tuple of classes that will be used instead of this base. The ' - 'tuple may\n' - 'be empty, in such case the original base is ignored.\n' + ' "type", then an "__mro_entries__()" method is searched on ' + 'the base.\n' + ' If an "__mro_entries__()" method is found, the base is ' + 'substituted\n' + ' with the result of a call to "__mro_entries__()" when ' + 'creating the\n' + ' class. The method is called with the original bases tuple ' + 'passed to\n' + ' the *bases* parameter, and must return a tuple of classes ' + 'that will\n' + ' be used instead of the base. The returned tuple may be ' + 'empty: in\n' + ' these cases, the original base is ignored.\n' '\n' 'See also:\n' '\n' - ' **PEP 560** - Core support for typing module and generic ' - 'types\n' + ' "types.resolve_bases()"\n' + ' Dynamically resolve bases that are not instances of ' + '"type".\n' + '\n' + ' "types.get_original_bases()"\n' + ' Retrieve a class’s “original bases” prior to ' + 'modifications by\n' + ' "__mro_entries__()".\n' + '\n' + ' **PEP 560**\n' + ' Core support for typing module and generic types.\n' '\n' '\n' 'Determining the appropriate metaclass\n' @@ -11153,6 +11261,61 @@ ' The specification for the Python "match" statement.\n' '\n' '\n' + 'Emulating buffer types\n' + '======================\n' + '\n' + 'The buffer protocol provides a way for Python objects to ' + 'expose\n' + 'efficient access to a low-level memory array. This protocol ' + 'is\n' + 'implemented by builtin types such as "bytes" and ' + '"memoryview", and\n' + 'third-party libraries may define additional buffer types.\n' + '\n' + 'While buffer types are usually implemented in C, it is also ' + 'possible\n' + 'to implement the protocol in Python.\n' + '\n' + 'object.__buffer__(self, flags)\n' + '\n' + ' Called when a buffer is requested from *self* (for ' + 'example, by the\n' + ' "memoryview" constructor). The *flags* argument is an ' + 'integer\n' + ' representing the kind of buffer requested, affecting for ' + 'example\n' + ' whether the returned buffer is read-only or writable.\n' + ' "inspect.BufferFlags" provides a convenient way to ' + 'interpret the\n' + ' flags. The method must return a "memoryview" object.\n' + '\n' + 'object.__release_buffer__(self, buffer)\n' + '\n' + ' Called when a buffer is no longer needed. The *buffer* ' + 'argument is\n' + ' a "memoryview" object that was previously returned by\n' + ' "__buffer__()". The method must release any resources ' + 'associated\n' + ' with the buffer. This method should return "None". Buffer ' + 'objects\n' + ' that do not need to perform any cleanup are not required ' + 'to\n' + ' implement this method.\n' + '\n' + 'New in version 3.12.\n' + '\n' + 'See also:\n' + '\n' + ' **PEP 688** - Making the buffer protocol accessible in ' + 'Python\n' + ' Introduces the Python "__buffer__" and ' + '"__release_buffer__"\n' + ' methods.\n' + '\n' + ' "collections.abc.Buffer"\n' + ' ABC for buffer types.\n' + '\n' + '\n' 'Special method lookup\n' '=====================\n' '\n' @@ -11300,8 +11463,8 @@ ' "casefold()" converts it to ""ss"".\n' '\n' ' The casefolding algorithm is described in section 3.13 ' - 'of the\n' - ' Unicode Standard.\n' + '‘Default\n' + ' Case Folding’ of the Unicode Standard.\n' '\n' ' New in version 3.3.\n' '\n' @@ -11519,8 +11682,9 @@ ' being one of “Lm”, “Lt”, “Lu”, “Ll”, or “Lo”. Note ' 'that this is\n' ' different from the Alphabetic property defined in the ' - 'Unicode\n' - ' Standard.\n' + 'section 4.10\n' + ' ‘Letters, Alphabetic, and Ideographic’ of the Unicode ' + 'Standard.\n' '\n' 'str.isascii()\n' '\n' @@ -11692,8 +11856,8 @@ ' converted to lowercase.\n' '\n' ' The lowercasing algorithm used is described in section ' - '3.13 of the\n' - ' Unicode Standard.\n' + '3.13\n' + ' ‘Default Case Folding’ of the Unicode Standard.\n' '\n' 'str.lstrip([chars])\n' '\n' @@ -12159,8 +12323,8 @@ ' uppercase), but e.g. “Lt” (Letter, titlecase).\n' '\n' ' The uppercasing algorithm used is described in section ' - '3.13 of the\n' - ' Unicode Standard.\n' + '3.13\n' + ' ‘Default Case Folding’ of the Unicode Standard.\n' '\n' 'str.zfill(width)\n' '\n' @@ -12704,9 +12868,10 @@ '\n' 'Any remaining exceptions that were not handled by any "except*" ' 'clause\n' - 'are re-raised at the end, combined into an exception group along ' - 'with\n' - 'all exceptions that were raised from within "except*" clauses.\n' + 'are re-raised at the end, along with all exceptions that were raised\n' + 'from within the "except*" clauses. If this list contains more than ' + 'one\n' + 'exception to reraise, they are combined into an exception group.\n' '\n' 'If the raised exception is not an exception group and its type ' 'matches\n' diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 1f203bd00d3500..fbc76b8d0f14b2 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -872,37 +872,6 @@ def __init__(self, args, bufsize=-1, executable=None, 'and universal_newlines are supplied but ' 'different. Pass one or the other.') - # Input and output objects. The general principle is like - # this: - # - # Parent Child - # ------ ----- - # p2cwrite ---stdin---> p2cread - # c2pread <--stdout--- c2pwrite - # errread <--stderr--- errwrite - # - # On POSIX, the child objects are file descriptors. On - # Windows, these are Windows file handles. The parent objects - # are file descriptors on both platforms. The parent objects - # are -1 when not using PIPEs. The child objects are -1 - # when not redirecting. - - (p2cread, p2cwrite, - c2pread, c2pwrite, - errread, errwrite) = self._get_handles(stdin, stdout, stderr) - - # We wrap OS handles *before* launching the child, otherwise a - # quickly terminating child could make our fds unwrappable - # (see #8458). - - if _mswindows: - if p2cwrite != -1: - p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) - if c2pread != -1: - c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0) - if errread != -1: - errread = msvcrt.open_osfhandle(errread.Detach(), 0) - self.text_mode = encoding or errors or text or universal_newlines if self.text_mode and encoding is None: self.encoding = encoding = _text_encoding() @@ -1003,6 +972,39 @@ def __init__(self, args, bufsize=-1, executable=None, if uid < 0: raise ValueError(f"User ID cannot be negative, got {uid}") + # Input and output objects. The general principle is like + # this: + # + # Parent Child + # ------ ----- + # p2cwrite ---stdin---> p2cread + # c2pread <--stdout--- c2pwrite + # errread <--stderr--- errwrite + # + # On POSIX, the child objects are file descriptors. On + # Windows, these are Windows file handles. The parent objects + # are file descriptors on both platforms. The parent objects + # are -1 when not using PIPEs. The child objects are -1 + # when not redirecting. + + (p2cread, p2cwrite, + c2pread, c2pwrite, + errread, errwrite) = self._get_handles(stdin, stdout, stderr) + + # From here on, raising exceptions may cause file descriptor leakage + + # We wrap OS handles *before* launching the child, otherwise a + # quickly terminating child could make our fds unwrappable + # (see #8458). + + if _mswindows: + if p2cwrite != -1: + p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) + if c2pread != -1: + c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0) + if errread != -1: + errread = msvcrt.open_osfhandle(errread.Detach(), 0) + try: if p2cwrite != -1: self.stdin = io.open(p2cwrite, 'wb', bufsize) @@ -1306,6 +1308,26 @@ def _close_pipe_fds(self, # Prevent a double close of these handles/fds from __init__ on error. self._closed_child_pipe_fds = True + @contextlib.contextmanager + def _on_error_fd_closer(self): + """Helper to ensure file descriptors opened in _get_handles are closed""" + to_close = [] + try: + yield to_close + except: + if hasattr(self, '_devnull'): + to_close.append(self._devnull) + del self._devnull + for fd in to_close: + try: + if _mswindows and isinstance(fd, Handle): + fd.Close() + else: + os.close(fd) + except OSError: + pass + raise + if _mswindows: # # Windows methods @@ -1321,61 +1343,68 @@ def _get_handles(self, stdin, stdout, stderr): c2pread, c2pwrite = -1, -1 errread, errwrite = -1, -1 - if stdin is None: - p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE) - if p2cread is None: - p2cread, _ = _winapi.CreatePipe(None, 0) - p2cread = Handle(p2cread) - _winapi.CloseHandle(_) - elif stdin == PIPE: - p2cread, p2cwrite = _winapi.CreatePipe(None, 0) - p2cread, p2cwrite = Handle(p2cread), Handle(p2cwrite) - elif stdin == DEVNULL: - p2cread = msvcrt.get_osfhandle(self._get_devnull()) - elif isinstance(stdin, int): - p2cread = msvcrt.get_osfhandle(stdin) - else: - # Assuming file-like object - p2cread = msvcrt.get_osfhandle(stdin.fileno()) - p2cread = self._make_inheritable(p2cread) - - if stdout is None: - c2pwrite = _winapi.GetStdHandle(_winapi.STD_OUTPUT_HANDLE) - if c2pwrite is None: - _, c2pwrite = _winapi.CreatePipe(None, 0) - c2pwrite = Handle(c2pwrite) - _winapi.CloseHandle(_) - elif stdout == PIPE: - c2pread, c2pwrite = _winapi.CreatePipe(None, 0) - c2pread, c2pwrite = Handle(c2pread), Handle(c2pwrite) - elif stdout == DEVNULL: - c2pwrite = msvcrt.get_osfhandle(self._get_devnull()) - elif isinstance(stdout, int): - c2pwrite = msvcrt.get_osfhandle(stdout) - else: - # Assuming file-like object - c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) - c2pwrite = self._make_inheritable(c2pwrite) - - if stderr is None: - errwrite = _winapi.GetStdHandle(_winapi.STD_ERROR_HANDLE) - if errwrite is None: - _, errwrite = _winapi.CreatePipe(None, 0) - errwrite = Handle(errwrite) - _winapi.CloseHandle(_) - elif stderr == PIPE: - errread, errwrite = _winapi.CreatePipe(None, 0) - errread, errwrite = Handle(errread), Handle(errwrite) - elif stderr == STDOUT: - errwrite = c2pwrite - elif stderr == DEVNULL: - errwrite = msvcrt.get_osfhandle(self._get_devnull()) - elif isinstance(stderr, int): - errwrite = msvcrt.get_osfhandle(stderr) - else: - # Assuming file-like object - errwrite = msvcrt.get_osfhandle(stderr.fileno()) - errwrite = self._make_inheritable(errwrite) + with self._on_error_fd_closer() as err_close_fds: + if stdin is None: + p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE) + if p2cread is None: + p2cread, _ = _winapi.CreatePipe(None, 0) + p2cread = Handle(p2cread) + err_close_fds.append(p2cread) + _winapi.CloseHandle(_) + elif stdin == PIPE: + p2cread, p2cwrite = _winapi.CreatePipe(None, 0) + p2cread, p2cwrite = Handle(p2cread), Handle(p2cwrite) + err_close_fds.extend((p2cread, p2cwrite)) + elif stdin == DEVNULL: + p2cread = msvcrt.get_osfhandle(self._get_devnull()) + elif isinstance(stdin, int): + p2cread = msvcrt.get_osfhandle(stdin) + else: + # Assuming file-like object + p2cread = msvcrt.get_osfhandle(stdin.fileno()) + p2cread = self._make_inheritable(p2cread) + + if stdout is None: + c2pwrite = _winapi.GetStdHandle(_winapi.STD_OUTPUT_HANDLE) + if c2pwrite is None: + _, c2pwrite = _winapi.CreatePipe(None, 0) + c2pwrite = Handle(c2pwrite) + err_close_fds.append(c2pwrite) + _winapi.CloseHandle(_) + elif stdout == PIPE: + c2pread, c2pwrite = _winapi.CreatePipe(None, 0) + c2pread, c2pwrite = Handle(c2pread), Handle(c2pwrite) + err_close_fds.extend((c2pread, c2pwrite)) + elif stdout == DEVNULL: + c2pwrite = msvcrt.get_osfhandle(self._get_devnull()) + elif isinstance(stdout, int): + c2pwrite = msvcrt.get_osfhandle(stdout) + else: + # Assuming file-like object + c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) + c2pwrite = self._make_inheritable(c2pwrite) + + if stderr is None: + errwrite = _winapi.GetStdHandle(_winapi.STD_ERROR_HANDLE) + if errwrite is None: + _, errwrite = _winapi.CreatePipe(None, 0) + errwrite = Handle(errwrite) + err_close_fds.append(errwrite) + _winapi.CloseHandle(_) + elif stderr == PIPE: + errread, errwrite = _winapi.CreatePipe(None, 0) + errread, errwrite = Handle(errread), Handle(errwrite) + err_close_fds.extend((errread, errwrite)) + elif stderr == STDOUT: + errwrite = c2pwrite + elif stderr == DEVNULL: + errwrite = msvcrt.get_osfhandle(self._get_devnull()) + elif isinstance(stderr, int): + errwrite = msvcrt.get_osfhandle(stderr) + else: + # Assuming file-like object + errwrite = msvcrt.get_osfhandle(stderr.fileno()) + errwrite = self._make_inheritable(errwrite) return (p2cread, p2cwrite, c2pread, c2pwrite, @@ -1662,52 +1691,56 @@ def _get_handles(self, stdin, stdout, stderr): c2pread, c2pwrite = -1, -1 errread, errwrite = -1, -1 - if stdin is None: - pass - elif stdin == PIPE: - p2cread, p2cwrite = os.pipe() - if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"): - fcntl.fcntl(p2cwrite, fcntl.F_SETPIPE_SZ, self.pipesize) - elif stdin == DEVNULL: - p2cread = self._get_devnull() - elif isinstance(stdin, int): - p2cread = stdin - else: - # Assuming file-like object - p2cread = stdin.fileno() + with self._on_error_fd_closer() as err_close_fds: + if stdin is None: + pass + elif stdin == PIPE: + p2cread, p2cwrite = os.pipe() + err_close_fds.extend((p2cread, p2cwrite)) + if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"): + fcntl.fcntl(p2cwrite, fcntl.F_SETPIPE_SZ, self.pipesize) + elif stdin == DEVNULL: + p2cread = self._get_devnull() + elif isinstance(stdin, int): + p2cread = stdin + else: + # Assuming file-like object + p2cread = stdin.fileno() - if stdout is None: - pass - elif stdout == PIPE: - c2pread, c2pwrite = os.pipe() - if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"): - fcntl.fcntl(c2pwrite, fcntl.F_SETPIPE_SZ, self.pipesize) - elif stdout == DEVNULL: - c2pwrite = self._get_devnull() - elif isinstance(stdout, int): - c2pwrite = stdout - else: - # Assuming file-like object - c2pwrite = stdout.fileno() + if stdout is None: + pass + elif stdout == PIPE: + c2pread, c2pwrite = os.pipe() + err_close_fds.extend((c2pread, c2pwrite)) + if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"): + fcntl.fcntl(c2pwrite, fcntl.F_SETPIPE_SZ, self.pipesize) + elif stdout == DEVNULL: + c2pwrite = self._get_devnull() + elif isinstance(stdout, int): + c2pwrite = stdout + else: + # Assuming file-like object + c2pwrite = stdout.fileno() - if stderr is None: - pass - elif stderr == PIPE: - errread, errwrite = os.pipe() - if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"): - fcntl.fcntl(errwrite, fcntl.F_SETPIPE_SZ, self.pipesize) - elif stderr == STDOUT: - if c2pwrite != -1: - errwrite = c2pwrite - else: # child's stdout is not set, use parent's stdout - errwrite = sys.__stdout__.fileno() - elif stderr == DEVNULL: - errwrite = self._get_devnull() - elif isinstance(stderr, int): - errwrite = stderr - else: - # Assuming file-like object - errwrite = stderr.fileno() + if stderr is None: + pass + elif stderr == PIPE: + errread, errwrite = os.pipe() + err_close_fds.extend((errread, errwrite)) + if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"): + fcntl.fcntl(errwrite, fcntl.F_SETPIPE_SZ, self.pipesize) + elif stderr == STDOUT: + if c2pwrite != -1: + errwrite = c2pwrite + else: # child's stdout is not set, use parent's stdout + errwrite = sys.__stdout__.fileno() + elif stderr == DEVNULL: + errwrite = self._get_devnull() + elif isinstance(stderr, int): + errwrite = stderr + else: + # Assuming file-like object + errwrite = stderr.fileno() return (p2cread, p2cwrite, c2pread, c2pwrite, diff --git a/Lib/tabnanny.py b/Lib/tabnanny.py index 9d2df59d36ff47..e2ac6837f157d5 100755 --- a/Lib/tabnanny.py +++ b/Lib/tabnanny.py @@ -107,6 +107,10 @@ def check(file): errprint("%r: Token Error: %s" % (file, msg)) return + except SyntaxError as msg: + errprint("%r: Token Error: %s" % (file, msg)) + return + except IndentationError as msg: errprint("%r: Indentation Error: %s" % (file, msg)) return @@ -272,6 +276,12 @@ def format_witnesses(w): return prefix + " " + ', '.join(firsts) def process_tokens(tokens): + try: + _process_tokens(tokens) + except TabError as e: + raise NannyNag(e.lineno, e.msg, e.text) + +def _process_tokens(tokens): INDENT = tokenize.INDENT DEDENT = tokenize.DEDENT NEWLINE = tokenize.NEWLINE diff --git a/Lib/telnetlib.py b/Lib/telnetlib.py deleted file mode 100644 index 62d636129853ad..00000000000000 --- a/Lib/telnetlib.py +++ /dev/null @@ -1,679 +0,0 @@ -r"""TELNET client class. - -Based on RFC 854: TELNET Protocol Specification, by J. Postel and -J. Reynolds - -Example: - ->>> from telnetlib import Telnet ->>> tn = Telnet('www.python.org', 79) # connect to finger port ->>> tn.write(b'guido\r\n') ->>> print(tn.read_all()) -Login Name TTY Idle When Where -guido Guido van Rossum pts/2 snag.cnri.reston.. - ->>> - -Note that read_all() won't read until eof -- it just reads some data --- but it guarantees to read at least one byte unless EOF is hit. - -It is possible to pass a Telnet object to a selector in order to wait until -more data is available. Note that in this case, read_eager() may return b'' -even if there was data on the socket, because the protocol negotiation may have -eaten the data. This is why EOFError is needed in some cases to distinguish -between "no data" and "connection closed" (since the socket also appears ready -for reading when it is closed). - -To do: -- option negotiation -- timeout should be intrinsic to the connection object instead of an - option on one of the read calls only - -""" - - -# Imported modules -import sys -import socket -import selectors -from time import monotonic as _time -import warnings - -warnings._deprecated(__name__, remove=(3, 13)) - -__all__ = ["Telnet"] - -# Tunable parameters -DEBUGLEVEL = 0 - -# Telnet protocol defaults -TELNET_PORT = 23 - -# Telnet protocol characters (don't change) -IAC = bytes([255]) # "Interpret As Command" -DONT = bytes([254]) -DO = bytes([253]) -WONT = bytes([252]) -WILL = bytes([251]) -theNULL = bytes([0]) - -SE = bytes([240]) # Subnegotiation End -NOP = bytes([241]) # No Operation -DM = bytes([242]) # Data Mark -BRK = bytes([243]) # Break -IP = bytes([244]) # Interrupt process -AO = bytes([245]) # Abort output -AYT = bytes([246]) # Are You There -EC = bytes([247]) # Erase Character -EL = bytes([248]) # Erase Line -GA = bytes([249]) # Go Ahead -SB = bytes([250]) # Subnegotiation Begin - - -# Telnet protocol options code (don't change) -# These ones all come from arpa/telnet.h -BINARY = bytes([0]) # 8-bit data path -ECHO = bytes([1]) # echo -RCP = bytes([2]) # prepare to reconnect -SGA = bytes([3]) # suppress go ahead -NAMS = bytes([4]) # approximate message size -STATUS = bytes([5]) # give status -TM = bytes([6]) # timing mark -RCTE = bytes([7]) # remote controlled transmission and echo -NAOL = bytes([8]) # negotiate about output line width -NAOP = bytes([9]) # negotiate about output page size -NAOCRD = bytes([10]) # negotiate about CR disposition -NAOHTS = bytes([11]) # negotiate about horizontal tabstops -NAOHTD = bytes([12]) # negotiate about horizontal tab disposition -NAOFFD = bytes([13]) # negotiate about formfeed disposition -NAOVTS = bytes([14]) # negotiate about vertical tab stops -NAOVTD = bytes([15]) # negotiate about vertical tab disposition -NAOLFD = bytes([16]) # negotiate about output LF disposition -XASCII = bytes([17]) # extended ascii character set -LOGOUT = bytes([18]) # force logout -BM = bytes([19]) # byte macro -DET = bytes([20]) # data entry terminal -SUPDUP = bytes([21]) # supdup protocol -SUPDUPOUTPUT = bytes([22]) # supdup output -SNDLOC = bytes([23]) # send location -TTYPE = bytes([24]) # terminal type -EOR = bytes([25]) # end or record -TUID = bytes([26]) # TACACS user identification -OUTMRK = bytes([27]) # output marking -TTYLOC = bytes([28]) # terminal location number -VT3270REGIME = bytes([29]) # 3270 regime -X3PAD = bytes([30]) # X.3 PAD -NAWS = bytes([31]) # window size -TSPEED = bytes([32]) # terminal speed -LFLOW = bytes([33]) # remote flow control -LINEMODE = bytes([34]) # Linemode option -XDISPLOC = bytes([35]) # X Display Location -OLD_ENVIRON = bytes([36]) # Old - Environment variables -AUTHENTICATION = bytes([37]) # Authenticate -ENCRYPT = bytes([38]) # Encryption option -NEW_ENVIRON = bytes([39]) # New - Environment variables -# the following ones come from -# http://www.iana.org/assignments/telnet-options -# Unfortunately, that document does not assign identifiers -# to all of them, so we are making them up -TN3270E = bytes([40]) # TN3270E -XAUTH = bytes([41]) # XAUTH -CHARSET = bytes([42]) # CHARSET -RSP = bytes([43]) # Telnet Remote Serial Port -COM_PORT_OPTION = bytes([44]) # Com Port Control Option -SUPPRESS_LOCAL_ECHO = bytes([45]) # Telnet Suppress Local Echo -TLS = bytes([46]) # Telnet Start TLS -KERMIT = bytes([47]) # KERMIT -SEND_URL = bytes([48]) # SEND-URL -FORWARD_X = bytes([49]) # FORWARD_X -PRAGMA_LOGON = bytes([138]) # TELOPT PRAGMA LOGON -SSPI_LOGON = bytes([139]) # TELOPT SSPI LOGON -PRAGMA_HEARTBEAT = bytes([140]) # TELOPT PRAGMA HEARTBEAT -EXOPL = bytes([255]) # Extended-Options-List -NOOPT = bytes([0]) - - -# poll/select have the advantage of not requiring any extra file descriptor, -# contrarily to epoll/kqueue (also, they require a single syscall). -if hasattr(selectors, 'PollSelector'): - _TelnetSelector = selectors.PollSelector -else: - _TelnetSelector = selectors.SelectSelector - - -class Telnet: - - """Telnet interface class. - - An instance of this class represents a connection to a telnet - server. The instance is initially not connected; the open() - method must be used to establish a connection. Alternatively, the - host name and optional port number can be passed to the - constructor, too. - - Don't try to reopen an already connected instance. - - This class has many read_*() methods. Note that some of them - raise EOFError when the end of the connection is read, because - they can return an empty string for other reasons. See the - individual doc strings. - - read_until(expected, [timeout]) - Read until the expected string has been seen, or a timeout is - hit (default is no timeout); may block. - - read_all() - Read all data until EOF; may block. - - read_some() - Read at least one byte or EOF; may block. - - read_very_eager() - Read all data available already queued or on the socket, - without blocking. - - read_eager() - Read either data already queued or some data available on the - socket, without blocking. - - read_lazy() - Read all data in the raw queue (processing it first), without - doing any socket I/O. - - read_very_lazy() - Reads all data in the cooked queue, without doing any socket - I/O. - - read_sb_data() - Reads available data between SB ... SE sequence. Don't block. - - set_option_negotiation_callback(callback) - Each time a telnet option is read on the input flow, this callback - (if set) is called with the following parameters : - callback(telnet socket, command, option) - option will be chr(0) when there is no option. - No other action is done afterwards by telnetlib. - - """ - - def __init__(self, host=None, port=0, - timeout=socket._GLOBAL_DEFAULT_TIMEOUT): - """Constructor. - - When called without arguments, create an unconnected instance. - With a hostname argument, it connects the instance; port number - and timeout are optional. - """ - self.debuglevel = DEBUGLEVEL - self.host = host - self.port = port - self.timeout = timeout - self.sock = None - self.rawq = b'' - self.irawq = 0 - self.cookedq = b'' - self.eof = 0 - self.iacseq = b'' # Buffer for IAC sequence. - self.sb = 0 # flag for SB and SE sequence. - self.sbdataq = b'' - self.option_callback = None - if host is not None: - self.open(host, port, timeout) - - def open(self, host, port=0, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): - """Connect to a host. - - The optional second argument is the port number, which - defaults to the standard telnet port (23). - - Don't try to reopen an already connected instance. - """ - self.eof = 0 - if not port: - port = TELNET_PORT - self.host = host - self.port = port - self.timeout = timeout - sys.audit("telnetlib.Telnet.open", self, host, port) - self.sock = socket.create_connection((host, port), timeout) - - def __del__(self): - """Destructor -- close the connection.""" - self.close() - - def msg(self, msg, *args): - """Print a debug message, when the debug level is > 0. - - If extra arguments are present, they are substituted in the - message using the standard string formatting operator. - - """ - if self.debuglevel > 0: - print('Telnet(%s,%s):' % (self.host, self.port), end=' ') - if args: - print(msg % args) - else: - print(msg) - - def set_debuglevel(self, debuglevel): - """Set the debug level. - - The higher it is, the more debug output you get (on sys.stdout). - - """ - self.debuglevel = debuglevel - - def close(self): - """Close the connection.""" - sock = self.sock - self.sock = None - self.eof = True - self.iacseq = b'' - self.sb = 0 - if sock: - sock.close() - - def get_socket(self): - """Return the socket object used internally.""" - return self.sock - - def fileno(self): - """Return the fileno() of the socket object used internally.""" - return self.sock.fileno() - - def write(self, buffer): - """Write a string to the socket, doubling any IAC characters. - - Can block if the connection is blocked. May raise - OSError if the connection is closed. - - """ - if IAC in buffer: - buffer = buffer.replace(IAC, IAC+IAC) - sys.audit("telnetlib.Telnet.write", self, buffer) - self.msg("send %r", buffer) - self.sock.sendall(buffer) - - def read_until(self, match, timeout=None): - """Read until a given string is encountered or until timeout. - - When no match is found, return whatever is available instead, - possibly the empty string. Raise EOFError if the connection - is closed and no cooked data is available. - - """ - n = len(match) - self.process_rawq() - i = self.cookedq.find(match) - if i >= 0: - i = i+n - buf = self.cookedq[:i] - self.cookedq = self.cookedq[i:] - return buf - if timeout is not None: - deadline = _time() + timeout - with _TelnetSelector() as selector: - selector.register(self, selectors.EVENT_READ) - while not self.eof: - if selector.select(timeout): - i = max(0, len(self.cookedq)-n) - self.fill_rawq() - self.process_rawq() - i = self.cookedq.find(match, i) - if i >= 0: - i = i+n - buf = self.cookedq[:i] - self.cookedq = self.cookedq[i:] - return buf - if timeout is not None: - timeout = deadline - _time() - if timeout < 0: - break - return self.read_very_lazy() - - def read_all(self): - """Read all data until EOF; block until connection closed.""" - self.process_rawq() - while not self.eof: - self.fill_rawq() - self.process_rawq() - buf = self.cookedq - self.cookedq = b'' - return buf - - def read_some(self): - """Read at least one byte of cooked data unless EOF is hit. - - Return b'' if EOF is hit. Block if no data is immediately - available. - - """ - self.process_rawq() - while not self.cookedq and not self.eof: - self.fill_rawq() - self.process_rawq() - buf = self.cookedq - self.cookedq = b'' - return buf - - def read_very_eager(self): - """Read everything that's possible without blocking in I/O (eager). - - Raise EOFError if connection closed and no cooked data - available. Return b'' if no cooked data available otherwise. - Don't block unless in the midst of an IAC sequence. - - """ - self.process_rawq() - while not self.eof and self.sock_avail(): - self.fill_rawq() - self.process_rawq() - return self.read_very_lazy() - - def read_eager(self): - """Read readily available data. - - Raise EOFError if connection closed and no cooked data - available. Return b'' if no cooked data available otherwise. - Don't block unless in the midst of an IAC sequence. - - """ - self.process_rawq() - while not self.cookedq and not self.eof and self.sock_avail(): - self.fill_rawq() - self.process_rawq() - return self.read_very_lazy() - - def read_lazy(self): - """Process and return data that's already in the queues (lazy). - - Raise EOFError if connection closed and no data available. - Return b'' if no cooked data available otherwise. Don't block - unless in the midst of an IAC sequence. - - """ - self.process_rawq() - return self.read_very_lazy() - - def read_very_lazy(self): - """Return any data available in the cooked queue (very lazy). - - Raise EOFError if connection closed and no data available. - Return b'' if no cooked data available otherwise. Don't block. - - """ - buf = self.cookedq - self.cookedq = b'' - if not buf and self.eof and not self.rawq: - raise EOFError('telnet connection closed') - return buf - - def read_sb_data(self): - """Return any data available in the SB ... SE queue. - - Return b'' if no SB ... SE available. Should only be called - after seeing a SB or SE command. When a new SB command is - found, old unread SB data will be discarded. Don't block. - - """ - buf = self.sbdataq - self.sbdataq = b'' - return buf - - def set_option_negotiation_callback(self, callback): - """Provide a callback function called after each receipt of a telnet option.""" - self.option_callback = callback - - def process_rawq(self): - """Transfer from raw queue to cooked queue. - - Set self.eof when connection is closed. Don't block unless in - the midst of an IAC sequence. - - """ - buf = [b'', b''] - try: - while self.rawq: - c = self.rawq_getchar() - if not self.iacseq: - if c == theNULL: - continue - if c == b"\021": - continue - if c != IAC: - buf[self.sb] = buf[self.sb] + c - continue - else: - self.iacseq += c - elif len(self.iacseq) == 1: - # 'IAC: IAC CMD [OPTION only for WILL/WONT/DO/DONT]' - if c in (DO, DONT, WILL, WONT): - self.iacseq += c - continue - - self.iacseq = b'' - if c == IAC: - buf[self.sb] = buf[self.sb] + c - else: - if c == SB: # SB ... SE start. - self.sb = 1 - self.sbdataq = b'' - elif c == SE: - self.sb = 0 - self.sbdataq = self.sbdataq + buf[1] - buf[1] = b'' - if self.option_callback: - # Callback is supposed to look into - # the sbdataq - self.option_callback(self.sock, c, NOOPT) - else: - # We can't offer automatic processing of - # suboptions. Alas, we should not get any - # unless we did a WILL/DO before. - self.msg('IAC %d not recognized' % ord(c)) - elif len(self.iacseq) == 2: - cmd = self.iacseq[1:2] - self.iacseq = b'' - opt = c - if cmd in (DO, DONT): - self.msg('IAC %s %d', - cmd == DO and 'DO' or 'DONT', ord(opt)) - if self.option_callback: - self.option_callback(self.sock, cmd, opt) - else: - self.sock.sendall(IAC + WONT + opt) - elif cmd in (WILL, WONT): - self.msg('IAC %s %d', - cmd == WILL and 'WILL' or 'WONT', ord(opt)) - if self.option_callback: - self.option_callback(self.sock, cmd, opt) - else: - self.sock.sendall(IAC + DONT + opt) - except EOFError: # raised by self.rawq_getchar() - self.iacseq = b'' # Reset on EOF - self.sb = 0 - self.cookedq = self.cookedq + buf[0] - self.sbdataq = self.sbdataq + buf[1] - - def rawq_getchar(self): - """Get next char from raw queue. - - Block if no data is immediately available. Raise EOFError - when connection is closed. - - """ - if not self.rawq: - self.fill_rawq() - if self.eof: - raise EOFError - c = self.rawq[self.irawq:self.irawq+1] - self.irawq = self.irawq + 1 - if self.irawq >= len(self.rawq): - self.rawq = b'' - self.irawq = 0 - return c - - def fill_rawq(self): - """Fill raw queue from exactly one recv() system call. - - Block if no data is immediately available. Set self.eof when - connection is closed. - - """ - if self.irawq >= len(self.rawq): - self.rawq = b'' - self.irawq = 0 - # The buffer size should be fairly small so as to avoid quadratic - # behavior in process_rawq() above - buf = self.sock.recv(50) - self.msg("recv %r", buf) - self.eof = (not buf) - self.rawq = self.rawq + buf - - def sock_avail(self): - """Test whether data is available on the socket.""" - with _TelnetSelector() as selector: - selector.register(self, selectors.EVENT_READ) - return bool(selector.select(0)) - - def interact(self): - """Interaction function, emulates a very dumb telnet client.""" - if sys.platform == "win32": - self.mt_interact() - return - with _TelnetSelector() as selector: - selector.register(self, selectors.EVENT_READ) - selector.register(sys.stdin, selectors.EVENT_READ) - - while True: - for key, events in selector.select(): - if key.fileobj is self: - try: - text = self.read_eager() - except EOFError: - print('*** Connection closed by remote host ***') - return - if text: - sys.stdout.write(text.decode('ascii')) - sys.stdout.flush() - elif key.fileobj is sys.stdin: - line = sys.stdin.readline().encode('ascii') - if not line: - return - self.write(line) - - def mt_interact(self): - """Multithreaded version of interact().""" - import _thread - _thread.start_new_thread(self.listener, ()) - while 1: - line = sys.stdin.readline() - if not line: - break - self.write(line.encode('ascii')) - - def listener(self): - """Helper for mt_interact() -- this executes in the other thread.""" - while 1: - try: - data = self.read_eager() - except EOFError: - print('*** Connection closed by remote host ***') - return - if data: - sys.stdout.write(data.decode('ascii')) - else: - sys.stdout.flush() - - def expect(self, list, timeout=None): - """Read until one from a list of a regular expressions matches. - - The first argument is a list of regular expressions, either - compiled (re.Pattern instances) or uncompiled (strings). - The optional second argument is a timeout, in seconds; default - is no timeout. - - Return a tuple of three items: the index in the list of the - first regular expression that matches; the re.Match object - returned; and the text read up till and including the match. - - If EOF is read and no text was read, raise EOFError. - Otherwise, when nothing matches, return (-1, None, text) where - text is the text received so far (may be the empty string if a - timeout happened). - - If a regular expression ends with a greedy match (e.g. '.*') - or if more than one expression can match the same input, the - results are undeterministic, and may depend on the I/O timing. - - """ - re = None - list = list[:] - indices = range(len(list)) - for i in indices: - if not hasattr(list[i], "search"): - if not re: import re - list[i] = re.compile(list[i]) - if timeout is not None: - deadline = _time() + timeout - with _TelnetSelector() as selector: - selector.register(self, selectors.EVENT_READ) - while not self.eof: - self.process_rawq() - for i in indices: - m = list[i].search(self.cookedq) - if m: - e = m.end() - text = self.cookedq[:e] - self.cookedq = self.cookedq[e:] - return (i, m, text) - if timeout is not None: - ready = selector.select(timeout) - timeout = deadline - _time() - if not ready: - if timeout < 0: - break - else: - continue - self.fill_rawq() - text = self.read_very_lazy() - if not text and self.eof: - raise EOFError - return (-1, None, text) - - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - self.close() - - -def test(): - """Test program for telnetlib. - - Usage: python telnetlib.py [-d] ... [host [port]] - - Default host is localhost; default port is 23. - - """ - debuglevel = 0 - while sys.argv[1:] and sys.argv[1] == '-d': - debuglevel = debuglevel+1 - del sys.argv[1] - host = 'localhost' - if sys.argv[1:]: - host = sys.argv[1] - port = 0 - if sys.argv[2:]: - portstr = sys.argv[2] - try: - port = int(portstr) - except ValueError: - port = socket.getservbyname(portstr, 'tcp') - with Telnet() as tn: - tn.set_debuglevel(debuglevel) - tn.open(host, port, timeout=0.5) - tn.interact() - -if __name__ == '__main__': - test() diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 9a2db24b4bd597..767f049b0d717a 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -48,6 +48,7 @@ import multiprocessing.managers import multiprocessing.pool import multiprocessing.queues +from multiprocessing.connection import wait, AuthenticationError from multiprocessing import util @@ -131,8 +132,6 @@ def _resource_unlink(name, rtype): WIN32 = (sys.platform == "win32") -from multiprocessing.connection import wait - def wait_for_handle(handle, timeout): if timeout is not None and timeout < 0.0: timeout = None @@ -3042,7 +3041,7 @@ def test_remote(self): del queue -@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('sha256') class _TestManagerRestart(BaseTestCase): @classmethod @@ -3531,7 +3530,7 @@ def test_dont_merge(self): # @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction") -@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('sha256') class _TestPicklingConnections(BaseTestCase): ALLOWED_TYPES = ('processes',) @@ -3834,7 +3833,7 @@ def test_copy(self): @unittest.skipUnless(HAS_SHMEM, "requires multiprocessing.shared_memory") -@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('sha256') class _TestSharedMemory(BaseTestCase): ALLOWED_TYPES = ('processes',) @@ -4636,7 +4635,7 @@ def test_invalid_handles(self): -@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('sha256') class OtherTest(unittest.TestCase): # TODO: add more tests for deliver/answer challenge. def test_deliver_challenge_auth_failure(self): @@ -4656,7 +4655,7 @@ def __init__(self): def recv_bytes(self, size): self.count += 1 if self.count == 1: - return multiprocessing.connection.CHALLENGE + return multiprocessing.connection._CHALLENGE elif self.count == 2: return b'something bogus' return b'' @@ -4666,6 +4665,44 @@ def send_bytes(self, data): multiprocessing.connection.answer_challenge, _FakeConnection(), b'abc') + +@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('sha256') +class ChallengeResponseTest(unittest.TestCase): + authkey = b'supadupasecretkey' + + def create_response(self, message): + return multiprocessing.connection._create_response( + self.authkey, message + ) + + def verify_challenge(self, message, response): + return multiprocessing.connection._verify_challenge( + self.authkey, message, response + ) + + def test_challengeresponse(self): + for algo in [None, "md5", "sha256"]: + with self.subTest(f"{algo=}"): + msg = b'is-twenty-bytes-long' # The length of a legacy message. + if algo: + prefix = b'{%s}' % algo.encode("ascii") + else: + prefix = b'' + msg = prefix + msg + response = self.create_response(msg) + if not response.startswith(prefix): + self.fail(response) + self.verify_challenge(msg, response) + + # TODO(gpshead): We need integration tests for handshakes between modern + # deliver_challenge() and verify_response() code and connections running a + # test-local copy of the legacy Python <=3.11 implementations. + + # TODO(gpshead): properly annotate tests for requires_hashdigest rather than + # only running these on a platform supporting everything. otherwise logic + # issues preventing it from working on FIPS mode setups will be hidden. + # # Test Manager.start()/Pool.__init__() initializer feature - see issue 5585 # @@ -4673,7 +4710,7 @@ def send_bytes(self, data): def initializer(ns): ns.test += 1 -@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('sha256') class TestInitializers(unittest.TestCase): def setUp(self): self.mgr = multiprocessing.Manager() @@ -5537,7 +5574,7 @@ def is_alive(self): any(process.is_alive() for process in forked_processes)) -@hashlib_helper.requires_hashdigest('md5') +@hashlib_helper.requires_hashdigest('sha256') class TestSyncManagerTypes(unittest.TestCase): """Test all the types which can be shared between a parent and a child process by using a manager which acts as an intermediary @@ -5969,7 +6006,7 @@ def install_tests_in_module_dict(remote_globs, start_method): class Temp(base, Mixin, unittest.TestCase): pass if type_ == 'manager': - Temp = hashlib_helper.requires_hashdigest('md5')(Temp) + Temp = hashlib_helper.requires_hashdigest('sha256')(Temp) Temp.__name__ = Temp.__qualname__ = newname Temp.__module__ = __module__ remote_globs[newname] = Temp diff --git a/Lib/test/mod_generics_cache.py b/Lib/test/mod_generics_cache.py index 9d8b56cf03c364..6c1ee2fec8374d 100644 --- a/Lib/test/mod_generics_cache.py +++ b/Lib/test/mod_generics_cache.py @@ -1,6 +1,6 @@ """Module for testing the behavior of generics across different modules.""" -from typing import TypeVar, Generic, Optional +from typing import TypeVar, Generic, Optional, TypeAliasType default_a: Optional['A'] = None default_b: Optional['B'] = None @@ -19,3 +19,6 @@ class A(Generic[T]): my_inner_a1: 'B.A' my_inner_a2: A my_outer_a: 'A' # unless somebody calls get_type_hints with localns=B.__dict__ + +type Alias = int +OldStyle = TypeAliasType("OldStyle", int) diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py index 709cac7a27a449..a6ea2f378b37ac 100644 --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -8,18 +8,12 @@ from collections import UserList import random + class Sequence: def __init__(self, seq='wxyz'): self.seq = seq def __len__(self): return len(self.seq) def __getitem__(self, i): return self.seq[i] -class BadSeq1(Sequence): - def __init__(self): self.seq = [7, 'hello', 123] - def __str__(self): return '{0} {1} {2}'.format(*self.seq) - -class BadSeq2(Sequence): - def __init__(self): self.seq = ['a', 'b', 'c'] - def __len__(self): return 8 class BaseTest: # These tests are for buffers of values (bytes) and not @@ -27,7 +21,7 @@ class BaseTest: # and various string implementations # The type to be tested - # Change in subclasses to change the behaviour of fixtesttype() + # Change in subclasses to change the behaviour of fixtype() type2test = None # Whether the "contained items" of the container are integers in @@ -36,7 +30,7 @@ class BaseTest: contains_bytes = False # All tests pass their arguments to the testing methods - # as str objects. fixtesttype() can be used to propagate + # as str objects. fixtype() can be used to propagate # these arguments to the appropriate type def fixtype(self, obj): if isinstance(obj, str): @@ -1096,7 +1090,7 @@ def test_splitlines(self): self.checkraises(TypeError, 'abc', 'splitlines', 42, 42) -class CommonTest(BaseTest): +class StringLikeTest(BaseTest): # This testcase contains tests that can be used in all # stringlike classes. Currently this is str and UserString. @@ -1127,11 +1121,6 @@ def test_capitalize_nonascii(self): self.checkequal('\u019b\u1d00\u1d86\u0221\u1fb7', '\u019b\u1d00\u1d86\u0221\u1fb7', 'capitalize') - -class MixinStrUnicodeUserStringTest: - # additional tests that only work for - # stringlike objects, i.e. str, UserString - def test_startswith(self): self.checkequal(True, 'hello', 'startswith', 'he') self.checkequal(True, 'hello', 'startswith', 'hello') @@ -1313,8 +1302,11 @@ def test_join(self): self.checkequal(((('a' * i) + '-') * i)[:-1], '-', 'join', ('a' * i,) * i) - #self.checkequal(str(BadSeq1()), ' ', 'join', BadSeq1()) - self.checkequal('a b c', ' ', 'join', BadSeq2()) + class LiesAboutLengthSeq(Sequence): + def __init__(self): self.seq = ['a', 'b', 'c'] + def __len__(self): return 8 + + self.checkequal('a b c', ' ', 'join', LiesAboutLengthSeq()) self.checkraises(TypeError, ' ', 'join') self.checkraises(TypeError, ' ', 'join', None) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index d063837baee2de..d555c53fee50a2 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -12,6 +12,7 @@ import stat import sys import sysconfig +import textwrap import time import types import unittest @@ -619,6 +620,14 @@ def sortdict(dict): withcommas = ", ".join(reprpairs) return "{%s}" % withcommas + +def run_code(code: str) -> dict[str, object]: + """Run a piece of code after dedenting it, and return its global namespace.""" + ns = {} + exec(textwrap.dedent(code), ns) + return ns + + def check_syntax_error(testcase, statement, errtext='', *, lineno=None, offset=None): with testcase.assertRaisesRegex(SyntaxError, errtext) as cm: compile(statement, '', 'exec') diff --git a/Lib/test/support/bytecode_helper.py b/Lib/test/support/bytecode_helper.py index 7b577f54b8adc4..388d1266773c8a 100644 --- a/Lib/test/support/bytecode_helper.py +++ b/Lib/test/support/bytecode_helper.py @@ -130,10 +130,10 @@ def generate_code(self, ast): class CfgOptimizationTestCase(CompilationStepTestCase): - def get_optimized(self, insts, consts): + def get_optimized(self, insts, consts, nlocals=0): insts = self.normalize_insts(insts) insts = self.complete_insts_info(insts) - insts = optimize_cfg(insts, consts) + insts = optimize_cfg(insts, consts, nlocals) return insts, consts class AssemblerTestCase(CompilationStepTestCase): diff --git a/Lib/test/support/hypothesis_helper.py b/Lib/test/support/hypothesis_helper.py index 76bd2490fe6e3d..da16eb50c25958 100644 --- a/Lib/test/support/hypothesis_helper.py +++ b/Lib/test/support/hypothesis_helper.py @@ -1,4 +1,35 @@ +import os + try: import hypothesis except ImportError: from . import _hypothesis_stubs as hypothesis +else: + # When using the real Hypothesis, we'll configure it to ignore occasional + # slow tests (avoiding flakiness from random VM slowness in CI). + hypothesis.settings.register_profile( + "slow-is-ok", + deadline=None, + suppress_health_check=[hypothesis.HealthCheck.too_slow], + ) + hypothesis.settings.load_profile("slow-is-ok") + + # For local development, we'll write to the default on-local-disk database + # of failing examples, and also use a pull-through cache to automatically + # replay any failing examples discovered in CI. For details on how this + # works, see https://hypothesis.readthedocs.io/en/latest/database.html + if "CI" not in os.environ: + from hypothesis.database import ( + GitHubArtifactDatabase, + MultiplexedDatabase, + ReadOnlyDatabase, + ) + + hypothesis.settings.register_profile( + "cpython-local-dev", + database=MultiplexedDatabase( + hypothesis.settings.default.database, + ReadOnlyDatabase(GitHubArtifactDatabase("python", "cpython")), + ), + ) + hypothesis.settings.load_profile("cpython-local-dev") diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index 0659d244d35686..3a62a16cee3179 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -765,6 +765,49 @@ def test_const(self): self.assertIn("got an unexpected keyword argument 'const'", str(cm.exception)) + def test_deprecated_init_kw(self): + # See gh-92248 + parser = argparse.ArgumentParser() + + with self.assertWarns(DeprecationWarning): + parser.add_argument( + '-a', + action=argparse.BooleanOptionalAction, + type=None, + ) + with self.assertWarns(DeprecationWarning): + parser.add_argument( + '-b', + action=argparse.BooleanOptionalAction, + type=bool, + ) + + with self.assertWarns(DeprecationWarning): + parser.add_argument( + '-c', + action=argparse.BooleanOptionalAction, + metavar=None, + ) + with self.assertWarns(DeprecationWarning): + parser.add_argument( + '-d', + action=argparse.BooleanOptionalAction, + metavar='d', + ) + + with self.assertWarns(DeprecationWarning): + parser.add_argument( + '-e', + action=argparse.BooleanOptionalAction, + choices=None, + ) + with self.assertWarns(DeprecationWarning): + parser.add_argument( + '-f', + action=argparse.BooleanOptionalAction, + choices=(), + ) + class TestBooleanOptionalActionRequired(ParserTestCase): """Tests BooleanOptionalAction required""" diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index fdd21aca06ffdd..cf128e1e8cd04c 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -181,7 +181,22 @@ def to_tuple(t): "def f(a=1, /, b=2, *, c): pass", "def f(a=1, /, b=2, *, c=4, **kwargs): pass", "def f(a=1, /, b=2, *, c, **kwargs): pass", - + # Type aliases + "type X = int", + "type X[T] = int", + "type X[T, *Ts, **P] = (T, Ts, P)", + "type X[T: int, *Ts, **P] = (T, Ts, P)", + "type X[T: (int, str), *Ts, **P] = (T, Ts, P)", + # Generic classes + "class X[T]: pass", + "class X[T, *Ts, **P]: pass", + "class X[T: int, *Ts, **P]: pass", + "class X[T: (int, str), *Ts, **P]: pass", + # Generic functions + "def f[T](): pass", + "def f[T, *Ts, **P](): pass", + "def f[T: int, *Ts, **P](): pass", + "def f[T: (int, str), *Ts, **P](): pass", ] # These are compiled through "single" @@ -262,7 +277,6 @@ def to_tuple(t): "()", # Combination "a.b.c.d(a.b[1:2])", - ] # TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension @@ -1013,6 +1027,18 @@ def test_exception_groups_feature_version(self): with self.assertRaises(SyntaxError): ast.parse(code, feature_version=(3, 10)) + def test_type_params_feature_version(self): + samples = [ + "type X = int", + "class X[T]: pass", + "def f[T](): pass", + ] + for sample in samples: + with self.subTest(sample): + ast.parse(sample) + with self.assertRaises(SyntaxError): + ast.parse(sample, feature_version=(3, 11)) + def test_invalid_major_feature_version(self): with self.assertRaises(ValueError): ast.parse('pass', feature_version=(2, 7)) @@ -1557,16 +1583,16 @@ def arguments(args=None, posonlyargs=None, vararg=None, def test_funcdef(self): a = ast.arguments([], [], None, [], [], None, []) - f = ast.FunctionDef("x", a, [], [], None) + f = ast.FunctionDef("x", [], a, [], [], None) self.stmt(f, "empty body on FunctionDef") - f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())], + f = ast.FunctionDef("x", [], a, [ast.Pass()], [ast.Name("x", ast.Store())], None) self.stmt(f, "must have Load context") - f = ast.FunctionDef("x", a, [ast.Pass()], [], + f = ast.FunctionDef("x", [], a, [ast.Pass()], [], ast.Name("x", ast.Store())) self.stmt(f, "must have Load context") def fac(args): - return ast.FunctionDef("x", args, [ast.Pass()], [], None) + return ast.FunctionDef("x", [], args, [ast.Pass()], [], None) self._check_arguments(fac, self.stmt) def test_classdef(self): @@ -1579,7 +1605,7 @@ def cls(bases=None, keywords=None, body=None, decorator_list=None): body = [ast.Pass()] if decorator_list is None: decorator_list = [] - return ast.ClassDef("myclass", bases, keywords, + return ast.ClassDef("myclass", [], bases, keywords, body, decorator_list) self.stmt(cls(bases=[ast.Name("x", ast.Store())]), "must have Load context") @@ -2035,6 +2061,12 @@ def test_stdlib_validates(self): kwd_attrs=[], kwd_patterns=[ast.MatchStar()] ), + ast.MatchClass( + constant_true, # invalid name + patterns=[], + kwd_attrs=['True'], + kwd_patterns=[pattern_1] + ), ast.MatchSequence( [ ast.MatchStar("True") @@ -2863,23 +2895,23 @@ def main(): exec_results = [ ('Module', [('Expr', (1, 0, 1, 4), ('Constant', (1, 0, 1, 4), None, None))], []), ('Module', [('Expr', (1, 0, 1, 18), ('Constant', (1, 0, 1, 18), 'module docstring', None))], []), -('Module', [('FunctionDef', (1, 0, 1, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 14), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 23), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 36), 'f', ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 21), 'f', ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 71), 'f', ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 27), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []), -('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []), -('Module', [('FunctionDef', (1, 0, 1, 45), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []), -('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [('Pass', (1, 8, 1, 12))], [])], []), -('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []), -('Module', [('ClassDef', (1, 0, 1, 21), 'C', [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []), -('Module', [('FunctionDef', (1, 0, 1, 16), 'f', ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 9, 1, 13))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (1, 9, 1, 29), ('Constant', (1, 9, 1, 29), 'function docstring', None))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 14), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, []), [('Pass', (1, 10, 1, 14))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 0, None)]), [('Pass', (1, 12, 1, 16))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 11), 'args', None, None), [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 23), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 16), 'args', ('Starred', (1, 13, 1, 16), ('Name', (1, 14, 1, 16), 'Ts', ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 19, 1, 23))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Constant', (1, 25, 1, 28), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 36), 'f', [], ('arguments', [], [], ('arg', (1, 7, 1, 29), 'args', ('Starred', (1, 13, 1, 29), ('Subscript', (1, 14, 1, 29), ('Name', (1, 14, 1, 19), 'tuple', ('Load',)), ('Tuple', (1, 20, 1, 28), [('Name', (1, 20, 1, 23), 'int', ('Load',)), ('Starred', (1, 25, 1, 28), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), ('Load',)), None), [], [], None, []), [('Pass', (1, 32, 1, 36))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 21), 'f', [], ('arguments', [], [], None, [], [], ('arg', (1, 8, 1, 14), 'kwargs', None, None), []), [('Pass', (1, 17, 1, 21))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 71), 'f', [], ('arguments', [], [('arg', (1, 6, 1, 7), 'a', None, None), ('arg', (1, 9, 1, 10), 'b', None, None), ('arg', (1, 14, 1, 15), 'c', None, None), ('arg', (1, 22, 1, 23), 'd', None, None), ('arg', (1, 28, 1, 29), 'e', None, None)], ('arg', (1, 35, 1, 39), 'args', None, None), [('arg', (1, 41, 1, 42), 'f', None, None)], [('Constant', (1, 43, 1, 45), 42, None)], ('arg', (1, 49, 1, 55), 'kwargs', None, None), [('Constant', (1, 11, 1, 12), 1, None), ('Constant', (1, 16, 1, 20), None, None), ('List', (1, 24, 1, 26), [], ('Load',)), ('Dict', (1, 30, 1, 32), [], [])]), [('Expr', (1, 58, 1, 71), ('Constant', (1, 58, 1, 71), 'doc for f()', None))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 27), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 23, 1, 27))], [], ('Subscript', (1, 11, 1, 21), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 20), [('Starred', (1, 17, 1, 20), ('Name', (1, 18, 1, 20), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []), +('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 28, 1, 32))], [], ('Subscript', (1, 11, 1, 26), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 25), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 25), ('Name', (1, 23, 1, 25), 'Ts', ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []), +('Module', [('FunctionDef', (1, 0, 1, 45), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 41, 1, 45))], [], ('Subscript', (1, 11, 1, 39), ('Name', (1, 11, 1, 16), 'tuple', ('Load',)), ('Tuple', (1, 17, 1, 38), [('Name', (1, 17, 1, 20), 'int', ('Load',)), ('Starred', (1, 22, 1, 38), ('Subscript', (1, 23, 1, 38), ('Name', (1, 23, 1, 28), 'tuple', ('Load',)), ('Tuple', (1, 29, 1, 37), [('Name', (1, 29, 1, 32), 'int', ('Load',)), ('Constant', (1, 34, 1, 37), Ellipsis, None)], ('Load',)), ('Load',)), ('Load',))], ('Load',)), ('Load',)), None)], []), +('Module', [('ClassDef', (1, 0, 1, 12), 'C', [], [], [], [('Pass', (1, 8, 1, 12))], [])], []), +('Module', [('ClassDef', (1, 0, 1, 32), 'C', [], [], [], [('Expr', (1, 9, 1, 32), ('Constant', (1, 9, 1, 32), 'docstring for class C', None))], [])], []), +('Module', [('ClassDef', (1, 0, 1, 21), 'C', [], [('Name', (1, 8, 1, 14), 'object', ('Load',))], [], [('Pass', (1, 17, 1, 21))], [])], []), +('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Return', (1, 8, 1, 16), ('Constant', (1, 15, 1, 16), 1, None))], [], None, None)], []), ('Module', [('Delete', (1, 0, 1, 5), [('Name', (1, 4, 1, 5), 'v', ('Del',))])], []), ('Module', [('Assign', (1, 0, 1, 5), [('Name', (1, 0, 1, 1), 'v', ('Store',))], ('Constant', (1, 4, 1, 5), 1, None), None)], []), ('Module', [('Assign', (1, 0, 1, 7), [('Tuple', (1, 0, 1, 3), [('Name', (1, 0, 1, 1), 'a', ('Store',)), ('Name', (1, 2, 1, 3), 'b', ('Store',))], ('Store',))], ('Name', (1, 6, 1, 7), 'c', ('Load',)), None)], []), @@ -2916,28 +2948,41 @@ def main(): ('Module', [('Expr', (1, 0, 1, 20), ('DictComp', (1, 0, 1, 20), ('Name', (1, 1, 1, 2), 'a', ('Load',)), ('Name', (1, 5, 1, 6), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11, 1, 14), [('Name', (1, 11, 1, 12), 'v', ('Store',)), ('Name', (1, 13, 1, 14), 'w', ('Store',))], ('Store',)), ('Name', (1, 18, 1, 19), 'x', ('Load',)), [], 0)]))], []), ('Module', [('Expr', (1, 0, 1, 19), ('SetComp', (1, 0, 1, 19), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 12, 1, 13), 'x', ('Load',)), [('Name', (1, 17, 1, 18), 'g', ('Load',))], 0)]))], []), ('Module', [('Expr', (1, 0, 1, 16), ('SetComp', (1, 0, 1, 16), ('Name', (1, 1, 1, 2), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7, 1, 10), [('Name', (1, 7, 1, 8), 'l', ('Store',)), ('Name', (1, 9, 1, 10), 'm', ('Store',))], ('Store',)), ('Name', (1, 14, 1, 15), 'x', ('Load',)), [], 0)]))], []), -('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []), -('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []), -('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0, 3, 18), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 17), ('Constant', (2, 1, 2, 17), 'async function', None)), ('Expr', (3, 1, 3, 18), ('Await', (3, 1, 3, 18), ('Call', (3, 7, 3, 18), ('Name', (3, 7, 3, 16), 'something', ('Load',)), [], [])))], [], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0, 3, 8), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncFor', (2, 1, 3, 8), ('Name', (2, 11, 2, 12), 'e', ('Store',)), ('Name', (2, 16, 2, 17), 'i', ('Load',)), [('Expr', (2, 19, 2, 20), ('Constant', (2, 19, 2, 20), 1, None))], [('Expr', (3, 7, 3, 8), ('Constant', (3, 7, 3, 8), 2, None))], None)], [], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('AsyncWith', (2, 1, 2, 21), [('withitem', ('Name', (2, 12, 2, 13), 'a', ('Load',)), ('Name', (2, 17, 2, 18), 'b', ('Store',)))], [('Expr', (2, 20, 2, 21), ('Constant', (2, 20, 2, 21), 1, None))], None)], [], None, None)], []), ('Module', [('Expr', (1, 0, 1, 14), ('Dict', (1, 0, 1, 14), [None, ('Constant', (1, 10, 1, 11), 2, None)], [('Dict', (1, 3, 1, 8), [('Constant', (1, 4, 1, 5), 1, None)], [('Constant', (1, 6, 1, 7), 2, None)]), ('Constant', (1, 12, 1, 13), 3, None)]))], []), ('Module', [('Expr', (1, 0, 1, 12), ('Set', (1, 0, 1, 12), [('Starred', (1, 1, 1, 8), ('Set', (1, 2, 1, 8), [('Constant', (1, 3, 1, 4), 1, None), ('Constant', (1, 6, 1, 7), 2, None)]), ('Load',)), ('Constant', (1, 10, 1, 11), 3, None)]))], []), -('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []), -('Module', [('FunctionDef', (4, 0, 4, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []), -('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []), -('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []), -('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []), -('Module', [('FunctionDef', (2, 0, 2, 13), 'f', ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []), +('Module', [('AsyncFunctionDef', (1, 0, 2, 21), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Expr', (2, 1, 2, 21), ('ListComp', (2, 1, 2, 21), ('Name', (2, 2, 2, 3), 'i', ('Load',)), [('comprehension', ('Name', (2, 14, 2, 15), 'b', ('Store',)), ('Name', (2, 19, 2, 20), 'c', ('Load',)), [], 1)]))], [], None, None)], []), +('Module', [('FunctionDef', (4, 0, 4, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []), +('Module', [('AsyncFunctionDef', (4, 0, 4, 19), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (4, 15, 4, 19))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])], None, None)], []), +('Module', [('ClassDef', (4, 0, 4, 13), 'C', [], [], [], [('Pass', (4, 9, 4, 13))], [('Name', (1, 1, 1, 6), 'deco1', ('Load',)), ('Call', (2, 1, 2, 8), ('Name', (2, 1, 2, 6), 'deco2', ('Load',)), [], []), ('Call', (3, 1, 3, 9), ('Name', (3, 1, 3, 6), 'deco3', ('Load',)), [('Constant', (3, 7, 3, 8), 1, None)], [])])], []), +('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Call', (1, 1, 1, 19), ('Name', (1, 1, 1, 5), 'deco', ('Load',)), [('GeneratorExp', (1, 5, 1, 19), ('Name', (1, 6, 1, 7), 'a', ('Load',)), [('comprehension', ('Name', (1, 12, 1, 13), 'a', ('Store',)), ('Name', (1, 17, 1, 18), 'b', ('Load',)), [], 0)])], [])], None, None)], []), +('Module', [('FunctionDef', (2, 0, 2, 13), 'f', [], ('arguments', [], [], None, [], [], None, []), [('Pass', (2, 9, 2, 13))], [('Attribute', (1, 1, 1, 6), ('Attribute', (1, 1, 1, 4), ('Name', (1, 1, 1, 2), 'a', ('Load',)), 'b', ('Load',)), 'c', ('Load',))], None, None)], []), ('Module', [('Expr', (1, 0, 1, 8), ('NamedExpr', (1, 1, 1, 7), ('Name', (1, 1, 1, 2), 'a', ('Store',)), ('Constant', (1, 6, 1, 7), 1, None)))], []), -('Module', [('FunctionDef', (1, 0, 1, 18), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 26), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 39), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 20), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 29), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 32), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 30), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 42), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []), -('Module', [('FunctionDef', (1, 0, 1, 40), 'f', ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 18), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, []), [('Pass', (1, 14, 1, 18))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None), ('arg', (1, 15, 1, 16), 'd', None, None), ('arg', (1, 18, 1, 19), 'e', None, None)], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], None, []), [('Pass', (1, 25, 1, 29))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 39), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 12, 1, 13), 'c', None, None)], None, [('arg', (1, 18, 1, 19), 'd', None, None), ('arg', (1, 21, 1, 22), 'e', None, None)], [None, None], ('arg', (1, 26, 1, 32), 'kwargs', None, None), []), [('Pass', (1, 35, 1, 39))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 20), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None)]), [('Pass', (1, 16, 1, 20))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 29), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None), ('arg', (1, 19, 1, 20), 'c', None, None)], None, [], [], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None), ('Constant', (1, 21, 1, 22), 4, None)]), [('Pass', (1, 25, 1, 29))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 32), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 28, 1, 32))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 30), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], None, [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 26, 1, 30))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 42), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [('Constant', (1, 24, 1, 25), 4, None)], ('arg', (1, 29, 1, 35), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 38, 1, 42))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 40), 'f', [], ('arguments', [('arg', (1, 6, 1, 7), 'a', None, None)], [('arg', (1, 14, 1, 15), 'b', None, None)], None, [('arg', (1, 22, 1, 23), 'c', None, None)], [None], ('arg', (1, 27, 1, 33), 'kwargs', None, None), [('Constant', (1, 8, 1, 9), 1, None), ('Constant', (1, 16, 1, 17), 2, None)]), [('Pass', (1, 36, 1, 40))], [], None, None)], []), +('Module', [('TypeAlias', (1, 0, 1, 12), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [], ('Name', (1, 9, 1, 12), 'int', ('Load',)))], []), +('Module', [('TypeAlias', (1, 0, 1, 15), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None)], ('Name', (1, 12, 1, 15), 'int', ('Load',)))], []), +('Module', [('TypeAlias', (1, 0, 1, 32), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 8), 'T', None), ('TypeVarTuple', (1, 10, 1, 13), 'Ts'), ('ParamSpec', (1, 15, 1, 18), 'P')], ('Tuple', (1, 22, 1, 32), [('Name', (1, 23, 1, 24), 'T', ('Load',)), ('Name', (1, 26, 1, 28), 'Ts', ('Load',)), ('Name', (1, 30, 1, 31), 'P', ('Load',))], ('Load',)))], []), +('Module', [('TypeAlias', (1, 0, 1, 37), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 13), 'T', ('Name', (1, 10, 1, 13), 'int', ('Load',))), ('TypeVarTuple', (1, 15, 1, 18), 'Ts'), ('ParamSpec', (1, 20, 1, 23), 'P')], ('Tuple', (1, 27, 1, 37), [('Name', (1, 28, 1, 29), 'T', ('Load',)), ('Name', (1, 31, 1, 33), 'Ts', ('Load',)), ('Name', (1, 35, 1, 36), 'P', ('Load',))], ('Load',)))], []), +('Module', [('TypeAlias', (1, 0, 1, 44), ('Name', (1, 5, 1, 6), 'X', ('Store',)), [('TypeVar', (1, 7, 1, 20), 'T', ('Tuple', (1, 10, 1, 20), [('Name', (1, 11, 1, 14), 'int', ('Load',)), ('Name', (1, 16, 1, 19), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 22, 1, 25), 'Ts'), ('ParamSpec', (1, 27, 1, 30), 'P')], ('Tuple', (1, 34, 1, 44), [('Name', (1, 35, 1, 36), 'T', ('Load',)), ('Name', (1, 38, 1, 40), 'Ts', ('Load',)), ('Name', (1, 42, 1, 43), 'P', ('Load',))], ('Load',)))], []), +('Module', [('ClassDef', (1, 0, 1, 16), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None)], [], [], [('Pass', (1, 12, 1, 16))], [])], []), +('Module', [('ClassDef', (1, 0, 1, 26), 'X', [('TypeVar', (1, 8, 1, 9), 'T', None), ('TypeVarTuple', (1, 11, 1, 14), 'Ts'), ('ParamSpec', (1, 16, 1, 19), 'P')], [], [], [('Pass', (1, 22, 1, 26))], [])], []), +('Module', [('ClassDef', (1, 0, 1, 31), 'X', [('TypeVar', (1, 8, 1, 14), 'T', ('Name', (1, 11, 1, 14), 'int', ('Load',))), ('TypeVarTuple', (1, 16, 1, 19), 'Ts'), ('ParamSpec', (1, 21, 1, 24), 'P')], [], [], [('Pass', (1, 27, 1, 31))], [])], []), +('Module', [('ClassDef', (1, 0, 1, 38), 'X', [('TypeVar', (1, 8, 1, 21), 'T', ('Tuple', (1, 11, 1, 21), [('Name', (1, 12, 1, 15), 'int', ('Load',)), ('Name', (1, 17, 1, 20), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 23, 1, 26), 'Ts'), ('ParamSpec', (1, 28, 1, 31), 'P')], [], [], [('Pass', (1, 34, 1, 38))], [])], []), +('Module', [('FunctionDef', (1, 0, 1, 16), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None)], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 12, 1, 16))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 26), 'f', [('TypeVar', (1, 6, 1, 7), 'T', None), ('TypeVarTuple', (1, 9, 1, 12), 'Ts'), ('ParamSpec', (1, 14, 1, 17), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 22, 1, 26))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 31), 'f', [('TypeVar', (1, 6, 1, 12), 'T', ('Name', (1, 9, 1, 12), 'int', ('Load',))), ('TypeVarTuple', (1, 14, 1, 17), 'Ts'), ('ParamSpec', (1, 19, 1, 22), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 27, 1, 31))], [], None, None)], []), +('Module', [('FunctionDef', (1, 0, 1, 38), 'f', [('TypeVar', (1, 6, 1, 19), 'T', ('Tuple', (1, 9, 1, 19), [('Name', (1, 10, 1, 13), 'int', ('Load',)), ('Name', (1, 15, 1, 18), 'str', ('Load',))], ('Load',))), ('TypeVarTuple', (1, 21, 1, 24), 'Ts'), ('ParamSpec', (1, 26, 1, 29), 'P')], ('arguments', [], [], None, [], [], None, []), [('Pass', (1, 34, 1, 38))], [], None, None)], []), ] single_results = [ ('Interactive', [('Expr', (1, 0, 1, 3), ('BinOp', (1, 0, 1, 3), ('Constant', (1, 0, 1, 1), 1, None), ('Add',), ('Constant', (1, 2, 1, 3), 2, None)))]), diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 821710a7fa3286..f5a5c037f1bf1b 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -18,6 +18,7 @@ import sys import traceback import types +import typing import unittest import warnings from contextlib import ExitStack @@ -1613,7 +1614,7 @@ def test_setattr(self): msg = r"^attribute name must be string, not 'int'$" self.assertRaisesRegex(TypeError, msg, setattr, sys, 1, 'spam') - # test_str(): see test_unicode.py and test_bytes.py for str() tests. + # test_str(): see test_str.py and test_bytes.py for str() tests. def test_sum(self): self.assertEqual(sum([]), 0) @@ -2485,6 +2486,17 @@ def test_type_qualname(self): A.__qualname__ = b'B' self.assertEqual(A.__qualname__, 'D.E') + def test_type_typeparams(self): + class A[T]: + pass + T, = A.__type_params__ + self.assertIsInstance(T, typing.TypeVar) + A.__type_params__ = "whatever" + self.assertEqual(A.__type_params__, "whatever") + with self.assertRaises(TypeError): + del A.__type_params__ + self.assertEqual(A.__type_params__, "whatever") + def test_type_doc(self): for doc in 'x', '\xc4', '\U0001f40d', 'x\x00y', b'x', 42, None: A = type('A', (), {'__doc__': doc}) diff --git a/Lib/test/test_capi/test_exceptions.py b/Lib/test/test_capi/test_exceptions.py index b1c1a61e20685e..1081f40b6981af 100644 --- a/Lib/test/test_capi/test_exceptions.py +++ b/Lib/test/test_capi/test_exceptions.py @@ -66,7 +66,7 @@ def check_fatal_error(self, code, expected, not_expected=()): rc, out, err = assert_python_failure('-sSI', '-c', code) err = decode_stderr(err) - self.assertIn('Fatal Python error: test_fatal_error: MESSAGE\n', + self.assertIn('Fatal Python error: _testcapi_fatal_error_impl: MESSAGE\n', err) match = re.search(r'^Extension modules:(.*) \(total: ([0-9]+)\)$', diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py new file mode 100644 index 00000000000000..8928fd94a1d6a3 --- /dev/null +++ b/Lib/test/test_capi/test_long.py @@ -0,0 +1,39 @@ +import unittest +import sys + +from test.support import import_helper + +# Skip this test if the _testcapi module isn't available. +_testcapi = import_helper.import_module('_testcapi') + + +class LongTests(unittest.TestCase): + + def test_compact(self): + for n in { + # Edge cases + *(2**n for n in range(66)), + *(-2**n for n in range(66)), + *(2**n - 1 for n in range(66)), + *(-2**n + 1 for n in range(66)), + # Essentially random + *(37**n for n in range(14)), + *(-37**n for n in range(14)), + }: + with self.subTest(n=n): + is_compact, value = _testcapi.call_long_compact_api(n) + if is_compact: + self.assertEqual(n, value) + + def test_compact_known(self): + # Sanity-check some implementation details (we don't guarantee + # that these are/aren't compact) + self.assertEqual(_testcapi.call_long_compact_api(-1), (True, -1)) + self.assertEqual(_testcapi.call_long_compact_api(0), (True, 0)) + self.assertEqual(_testcapi.call_long_compact_api(256), (True, 256)) + self.assertEqual(_testcapi.call_long_compact_api(sys.maxsize), + (False, -1)) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 0ef0b5d8b65803..dc3441e4496a5d 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -1744,6 +1744,30 @@ class Subclass(BaseException, self.module.StateAccessType): self.assertIs(Subclass().get_defining_module(), self.module) +class TestInternalFrameApi(unittest.TestCase): + + @staticmethod + def func(): + return sys._getframe() + + def test_code(self): + frame = self.func() + code = _testinternalcapi.iframe_getcode(frame) + self.assertIs(code, self.func.__code__) + + def test_lasti(self): + frame = self.func() + lasti = _testinternalcapi.iframe_getlasti(frame) + self.assertGreater(lasti, 0) + self.assertLess(lasti, len(self.func.__code__.co_code)) + + def test_line(self): + frame = self.func() + line = _testinternalcapi.iframe_getline(frame) + firstline = self.func.__code__.co_firstlineno + self.assertEqual(line, firstline + 2) + + SUFFICIENT_TO_DEOPT_AND_SPECIALIZE = 100 class Test_Pep523API(unittest.TestCase): diff --git a/Lib/test/test_capi/test_unicode.py b/Lib/test/test_capi/test_unicode.py index 00807d968a7c43..9c7662065689ea 100644 --- a/Lib/test/test_capi/test_unicode.py +++ b/Lib/test/test_capi/test_unicode.py @@ -319,12 +319,17 @@ def test_fromobject(self): def test_from_format(self): """Test PyUnicode_FromFormat()""" + # Length modifiers "j" and "t" are not tested here because ctypes does + # not expose types for intmax_t and ptrdiff_t. + # _testcapi.test_string_from_format() has a wider coverage of all + # formats. import_helper.import_module('ctypes') from ctypes import ( c_char_p, pythonapi, py_object, sizeof, c_int, c_long, c_longlong, c_ssize_t, - c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p) + c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p, + sizeof, c_wchar, c_wchar_p) name = "PyUnicode_FromFormat" _PyUnicode_FromFormat = getattr(pythonapi, name) _PyUnicode_FromFormat.argtypes = (c_char_p,) @@ -449,37 +454,28 @@ def check_format(expected, format, *args): check_format("repr= 12", b'repr=%5.2V', None, b'123') - # test integer formats (%i, %d, %u) + # test integer formats (%i, %d, %u, %o, %x, %X) check_format('010', b'%03i', c_int(10)) check_format('0010', b'%0.4i', c_int(10)) - check_format('-123', - b'%i', c_int(-123)) - check_format('-123', - b'%li', c_long(-123)) - check_format('-123', - b'%lli', c_longlong(-123)) - check_format('-123', - b'%zi', c_ssize_t(-123)) - - check_format('-123', - b'%d', c_int(-123)) - check_format('-123', - b'%ld', c_long(-123)) - check_format('-123', - b'%lld', c_longlong(-123)) - check_format('-123', - b'%zd', c_ssize_t(-123)) - - check_format('123', - b'%u', c_uint(123)) - check_format('123', - b'%lu', c_ulong(123)) - check_format('123', - b'%llu', c_ulonglong(123)) - check_format('123', - b'%zu', c_size_t(123)) + for conv, signed, value, expected in [ + (b'i', True, -123, '-123'), + (b'd', True, -123, '-123'), + (b'u', False, 123, '123'), + (b'o', False, 0o123, '123'), + (b'x', False, 0xabc, 'abc'), + (b'X', False, 0xabc, 'ABC'), + ]: + for mod, ctype in [ + (b'', c_int if signed else c_uint), + (b'l', c_long if signed else c_ulong), + (b'll', c_longlong if signed else c_ulonglong), + (b'z', c_ssize_t if signed else c_size_t), + ]: + with self.subTest(format=b'%' + mod + conv): + check_format(expected, + b'%' + mod + conv, ctype(value)) # test long output min_longlong = -(2 ** (8 * sizeof(c_longlong) - 1)) @@ -494,40 +490,144 @@ def check_format(expected, format, *args): PyUnicode_FromFormat(b'%p', c_void_p(-1)) # test padding (width and/or precision) - check_format('123'.rjust(10, '0'), - b'%010i', c_int(123)) - check_format('123'.rjust(100), - b'%100i', c_int(123)) - check_format('123'.rjust(100, '0'), - b'%.100i', c_int(123)) - check_format('123'.rjust(80, '0').rjust(100), - b'%100.80i', c_int(123)) - - check_format('123'.rjust(10, '0'), - b'%010u', c_uint(123)) - check_format('123'.rjust(100), - b'%100u', c_uint(123)) - check_format('123'.rjust(100, '0'), - b'%.100u', c_uint(123)) - check_format('123'.rjust(80, '0').rjust(100), - b'%100.80u', c_uint(123)) - - check_format('123'.rjust(10, '0'), - b'%010x', c_int(0x123)) - check_format('123'.rjust(100), - b'%100x', c_int(0x123)) - check_format('123'.rjust(100, '0'), - b'%.100x', c_int(0x123)) - check_format('123'.rjust(80, '0').rjust(100), - b'%100.80x', c_int(0x123)) + check_format('123', b'%2i', c_int(123)) + check_format(' 123', b'%10i', c_int(123)) + check_format('0000000123', b'%010i', c_int(123)) + check_format('123 ', b'%-10i', c_int(123)) + check_format('123 ', b'%-010i', c_int(123)) + check_format('123', b'%.2i', c_int(123)) + check_format('0000123', b'%.7i', c_int(123)) + check_format(' 123', b'%10.2i', c_int(123)) + check_format(' 0000123', b'%10.7i', c_int(123)) + check_format('0000000123', b'%010.7i', c_int(123)) + check_format('0000123 ', b'%-10.7i', c_int(123)) + check_format('0000123 ', b'%-010.7i', c_int(123)) + + check_format('-123', b'%2i', c_int(-123)) + check_format(' -123', b'%10i', c_int(-123)) + check_format('-000000123', b'%010i', c_int(-123)) + check_format('-123 ', b'%-10i', c_int(-123)) + check_format('-123 ', b'%-010i', c_int(-123)) + check_format('-123', b'%.2i', c_int(-123)) + check_format('-0000123', b'%.7i', c_int(-123)) + check_format(' -123', b'%10.2i', c_int(-123)) + check_format(' -0000123', b'%10.7i', c_int(-123)) + check_format('-000000123', b'%010.7i', c_int(-123)) + check_format('-0000123 ', b'%-10.7i', c_int(-123)) + check_format('-0000123 ', b'%-010.7i', c_int(-123)) + + check_format('123', b'%2u', c_uint(123)) + check_format(' 123', b'%10u', c_uint(123)) + check_format('0000000123', b'%010u', c_uint(123)) + check_format('123 ', b'%-10u', c_uint(123)) + check_format('123 ', b'%-010u', c_uint(123)) + check_format('123', b'%.2u', c_uint(123)) + check_format('0000123', b'%.7u', c_uint(123)) + check_format(' 123', b'%10.2u', c_uint(123)) + check_format(' 0000123', b'%10.7u', c_uint(123)) + check_format('0000000123', b'%010.7u', c_uint(123)) + check_format('0000123 ', b'%-10.7u', c_uint(123)) + check_format('0000123 ', b'%-010.7u', c_uint(123)) + + check_format('123', b'%2o', c_uint(0o123)) + check_format(' 123', b'%10o', c_uint(0o123)) + check_format('0000000123', b'%010o', c_uint(0o123)) + check_format('123 ', b'%-10o', c_uint(0o123)) + check_format('123 ', b'%-010o', c_uint(0o123)) + check_format('123', b'%.2o', c_uint(0o123)) + check_format('0000123', b'%.7o', c_uint(0o123)) + check_format(' 123', b'%10.2o', c_uint(0o123)) + check_format(' 0000123', b'%10.7o', c_uint(0o123)) + check_format('0000000123', b'%010.7o', c_uint(0o123)) + check_format('0000123 ', b'%-10.7o', c_uint(0o123)) + check_format('0000123 ', b'%-010.7o', c_uint(0o123)) + + check_format('abc', b'%2x', c_uint(0xabc)) + check_format(' abc', b'%10x', c_uint(0xabc)) + check_format('0000000abc', b'%010x', c_uint(0xabc)) + check_format('abc ', b'%-10x', c_uint(0xabc)) + check_format('abc ', b'%-010x', c_uint(0xabc)) + check_format('abc', b'%.2x', c_uint(0xabc)) + check_format('0000abc', b'%.7x', c_uint(0xabc)) + check_format(' abc', b'%10.2x', c_uint(0xabc)) + check_format(' 0000abc', b'%10.7x', c_uint(0xabc)) + check_format('0000000abc', b'%010.7x', c_uint(0xabc)) + check_format('0000abc ', b'%-10.7x', c_uint(0xabc)) + check_format('0000abc ', b'%-010.7x', c_uint(0xabc)) + + check_format('ABC', b'%2X', c_uint(0xabc)) + check_format(' ABC', b'%10X', c_uint(0xabc)) + check_format('0000000ABC', b'%010X', c_uint(0xabc)) + check_format('ABC ', b'%-10X', c_uint(0xabc)) + check_format('ABC ', b'%-010X', c_uint(0xabc)) + check_format('ABC', b'%.2X', c_uint(0xabc)) + check_format('0000ABC', b'%.7X', c_uint(0xabc)) + check_format(' ABC', b'%10.2X', c_uint(0xabc)) + check_format(' 0000ABC', b'%10.7X', c_uint(0xabc)) + check_format('0000000ABC', b'%010.7X', c_uint(0xabc)) + check_format('0000ABC ', b'%-10.7X', c_uint(0xabc)) + check_format('0000ABC ', b'%-010.7X', c_uint(0xabc)) # test %A check_format(r"%A:'abc\xe9\uabcd\U0010ffff'", b'%%A:%A', 'abc\xe9\uabcd\U0010ffff') # test %V - check_format('repr=abc', - b'repr=%V', 'abc', b'xyz') + check_format('abc', + b'%V', 'abc', b'xyz') + check_format('xyz', + b'%V', None, b'xyz') + + # test %ls + check_format('abc', b'%ls', c_wchar_p('abc')) + check_format('\u4eba\u6c11', b'%ls', c_wchar_p('\u4eba\u6c11')) + check_format('\U0001f4bb+\U0001f40d', + b'%ls', c_wchar_p('\U0001f4bb+\U0001f40d')) + check_format(' ab', b'%5.2ls', c_wchar_p('abc')) + check_format(' \u4eba\u6c11', b'%5ls', c_wchar_p('\u4eba\u6c11')) + check_format(' \U0001f4bb+\U0001f40d', + b'%5ls', c_wchar_p('\U0001f4bb+\U0001f40d')) + check_format('\u4eba', b'%.1ls', c_wchar_p('\u4eba\u6c11')) + check_format('\U0001f4bb' if sizeof(c_wchar) > 2 else '\ud83d', + b'%.1ls', c_wchar_p('\U0001f4bb+\U0001f40d')) + check_format('\U0001f4bb+' if sizeof(c_wchar) > 2 else '\U0001f4bb', + b'%.2ls', c_wchar_p('\U0001f4bb+\U0001f40d')) + + # test %lV + check_format('abc', + b'%lV', 'abc', c_wchar_p('xyz')) + check_format('xyz', + b'%lV', None, c_wchar_p('xyz')) + check_format('\u4eba\u6c11', + b'%lV', None, c_wchar_p('\u4eba\u6c11')) + check_format('\U0001f4bb+\U0001f40d', + b'%lV', None, c_wchar_p('\U0001f4bb+\U0001f40d')) + check_format(' ab', + b'%5.2lV', None, c_wchar_p('abc')) + check_format(' \u4eba\u6c11', + b'%5lV', None, c_wchar_p('\u4eba\u6c11')) + check_format(' \U0001f4bb+\U0001f40d', + b'%5lV', None, c_wchar_p('\U0001f4bb+\U0001f40d')) + check_format('\u4eba', + b'%.1lV', None, c_wchar_p('\u4eba\u6c11')) + check_format('\U0001f4bb' if sizeof(c_wchar) > 2 else '\ud83d', + b'%.1lV', None, c_wchar_p('\U0001f4bb+\U0001f40d')) + check_format('\U0001f4bb+' if sizeof(c_wchar) > 2 else '\U0001f4bb', + b'%.2lV', None, c_wchar_p('\U0001f4bb+\U0001f40d')) + + # test variable width and precision + check_format(' abc', b'%*s', c_int(5), b'abc') + check_format('ab', b'%.*s', c_int(2), b'abc') + check_format(' ab', b'%*.*s', c_int(5), c_int(2), b'abc') + check_format(' abc', b'%*U', c_int(5), 'abc') + check_format('ab', b'%.*U', c_int(2), 'abc') + check_format(' ab', b'%*.*U', c_int(5), c_int(2), 'abc') + check_format(' ab', b'%*.*V', c_int(5), c_int(2), None, b'abc') + check_format(' ab', b'%*.*lV', c_int(5), c_int(2), + None, c_wchar_p('abc')) + check_format(' 123', b'%*i', c_int(8), c_int(123)) + check_format('00123', b'%.*i', c_int(5), c_int(123)) + check_format(' 00123', b'%*.*i', c_int(8), c_int(5), c_int(123)) # test %p # We cannot test the exact result, @@ -564,10 +664,11 @@ def check_format(expected, format, *args): check_format('', b'%s', b'') - # check for crashes + # test invalid format strings. these tests are just here + # to check for crashes and should not be considered as specifications for fmt in (b'%', b'%0', b'%01', b'%.', b'%.1', b'%0%s', b'%1%s', b'%.%s', b'%.1%s', b'%1abc', - b'%l', b'%ll', b'%z', b'%ls', b'%lls', b'%zs'): + b'%l', b'%ll', b'%z', b'%lls', b'%zs'): with self.subTest(fmt=fmt): self.assertRaisesRegex(SystemError, 'invalid format string', PyUnicode_FromFormat, fmt, b'abc') diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index 28d9f650926427..bea7303805567f 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -774,6 +774,45 @@ def test_legacy_converters(self): module, function = block.signatures self.assertIsInstance((function.parameters['path']).converter, clinic.str_converter) + def test_legacy_converters_non_string_constant_annotation(self): + expected_failure_message = """\ +Error on line 0: +Annotations must be either a name, a function call, or a string. +""" + + s = self.parse_function_should_fail('module os\nos.access\n path: 42') + self.assertEqual(s, expected_failure_message) + + s = self.parse_function_should_fail('module os\nos.access\n path: 42.42') + self.assertEqual(s, expected_failure_message) + + s = self.parse_function_should_fail('module os\nos.access\n path: 42j') + self.assertEqual(s, expected_failure_message) + + s = self.parse_function_should_fail('module os\nos.access\n path: b"42"') + self.assertEqual(s, expected_failure_message) + + def test_other_bizarre_things_in_annotations_fail(self): + expected_failure_message = """\ +Error on line 0: +Annotations must be either a name, a function call, or a string. +""" + + s = self.parse_function_should_fail( + 'module os\nos.access\n path: {"some": "dictionary"}' + ) + self.assertEqual(s, expected_failure_message) + + s = self.parse_function_should_fail( + 'module os\nos.access\n path: ["list", "of", "strings"]' + ) + self.assertEqual(s, expected_failure_message) + + s = self.parse_function_should_fail( + 'module os\nos.access\n path: (x for x in range(42))' + ) + self.assertEqual(s, expected_failure_message) + def test_unused_param(self): block = self.parse(""" module foo @@ -868,9 +907,12 @@ def test_external(self): self.assertEqual(new_mtime_ns, old_mtime_ns) -ac_tester = import_helper.import_module('_testclinic') - +try: + import _testclinic as ac_tester +except ImportError: + ac_tester = None +@unittest.skipIf(ac_tester is None, "_testclinic is missing") class ClinicFunctionalTest(unittest.TestCase): locals().update((name, getattr(ac_tester, name)) for name in dir(ac_tester) if name.startswith('test_')) diff --git a/Lib/test/test_compare.py b/Lib/test/test_compare.py index 2b3faed7965bc1..8166b0eea306e3 100644 --- a/Lib/test/test_compare.py +++ b/Lib/test/test_compare.py @@ -1,21 +1,27 @@ +"""Test equality and order comparisons.""" import unittest from test.support import ALWAYS_EQ +from fractions import Fraction +from decimal import Decimal -class Empty: - def __repr__(self): - return '' -class Cmp: - def __init__(self,arg): - self.arg = arg +class ComparisonSimpleTest(unittest.TestCase): + """Test equality and order comparisons for some simple cases.""" - def __repr__(self): - return '' % self.arg + class Empty: + def __repr__(self): + return '' - def __eq__(self, other): - return self.arg == other + class Cmp: + def __init__(self, arg): + self.arg = arg + + def __repr__(self): + return '' % self.arg + + def __eq__(self, other): + return self.arg == other -class ComparisonTest(unittest.TestCase): set1 = [2, 2.0, 2, 2+0j, Cmp(2.0)] set2 = [[1], (3,), None, Empty()] candidates = set1 + set2 @@ -32,16 +38,15 @@ def test_id_comparisons(self): # Ensure default comparison compares id() of args L = [] for i in range(10): - L.insert(len(L)//2, Empty()) + L.insert(len(L)//2, self.Empty()) for a in L: for b in L: - self.assertEqual(a == b, id(a) == id(b), - 'a=%r, b=%r' % (a, b)) + self.assertEqual(a == b, a is b, 'a=%r, b=%r' % (a, b)) def test_ne_defaults_to_not_eq(self): - a = Cmp(1) - b = Cmp(1) - c = Cmp(2) + a = self.Cmp(1) + b = self.Cmp(1) + c = self.Cmp(2) self.assertIs(a == b, True) self.assertIs(a != b, False) self.assertIs(a != c, True) @@ -114,5 +119,392 @@ def test_issue_1393(self): self.assertEqual(ALWAYS_EQ, y) +class ComparisonFullTest(unittest.TestCase): + """Test equality and ordering comparisons for built-in types and + user-defined classes that implement relevant combinations of rich + comparison methods. + """ + + class CompBase: + """Base class for classes with rich comparison methods. + + The "x" attribute should be set to an underlying value to compare. + + Derived classes have a "meth" tuple attribute listing names of + comparison methods implemented. See assert_total_order(). + """ + + # Class without any rich comparison methods. + class CompNone(CompBase): + meth = () + + # Classes with all combinations of value-based equality comparison methods. + class CompEq(CompBase): + meth = ("eq",) + def __eq__(self, other): + return self.x == other.x + + class CompNe(CompBase): + meth = ("ne",) + def __ne__(self, other): + return self.x != other.x + + class CompEqNe(CompBase): + meth = ("eq", "ne") + def __eq__(self, other): + return self.x == other.x + def __ne__(self, other): + return self.x != other.x + + # Classes with all combinations of value-based less/greater-than order + # comparison methods. + class CompLt(CompBase): + meth = ("lt",) + def __lt__(self, other): + return self.x < other.x + + class CompGt(CompBase): + meth = ("gt",) + def __gt__(self, other): + return self.x > other.x + + class CompLtGt(CompBase): + meth = ("lt", "gt") + def __lt__(self, other): + return self.x < other.x + def __gt__(self, other): + return self.x > other.x + + # Classes with all combinations of value-based less/greater-or-equal-than + # order comparison methods + class CompLe(CompBase): + meth = ("le",) + def __le__(self, other): + return self.x <= other.x + + class CompGe(CompBase): + meth = ("ge",) + def __ge__(self, other): + return self.x >= other.x + + class CompLeGe(CompBase): + meth = ("le", "ge") + def __le__(self, other): + return self.x <= other.x + def __ge__(self, other): + return self.x >= other.x + + # It should be sufficient to combine the comparison methods only within + # each group. + all_comp_classes = ( + CompNone, + CompEq, CompNe, CompEqNe, # equal group + CompLt, CompGt, CompLtGt, # less/greater-than group + CompLe, CompGe, CompLeGe) # less/greater-or-equal group + + def create_sorted_instances(self, class_, values): + """Create objects of type `class_` and return them in a list. + + `values` is a list of values that determines the value of data + attribute `x` of each object. + + Objects in the returned list are sorted by their identity. They + assigned values in `values` list order. By assign decreasing + values to objects with increasing identities, testcases can assert + that order comparison is performed by value and not by identity. + """ + + instances = [class_() for __ in range(len(values))] + instances.sort(key=id) + # Assign the provided values to the instances. + for inst, value in zip(instances, values): + inst.x = value + return instances + + def assert_equality_only(self, a, b, equal): + """Assert equality result and that ordering is not implemented. + + a, b: Instances to be tested (of same or different type). + equal: Boolean indicating the expected equality comparison results. + """ + self.assertEqual(a == b, equal) + self.assertEqual(b == a, equal) + self.assertEqual(a != b, not equal) + self.assertEqual(b != a, not equal) + with self.assertRaisesRegex(TypeError, "not supported"): + a < b + with self.assertRaisesRegex(TypeError, "not supported"): + a <= b + with self.assertRaisesRegex(TypeError, "not supported"): + a > b + with self.assertRaisesRegex(TypeError, "not supported"): + a >= b + with self.assertRaisesRegex(TypeError, "not supported"): + b < a + with self.assertRaisesRegex(TypeError, "not supported"): + b <= a + with self.assertRaisesRegex(TypeError, "not supported"): + b > a + with self.assertRaisesRegex(TypeError, "not supported"): + b >= a + + def assert_total_order(self, a, b, comp, a_meth=None, b_meth=None): + """Test total ordering comparison of two instances. + + a, b: Instances to be tested (of same or different type). + + comp: -1, 0, or 1 indicates that the expected order comparison + result for operations that are supported by the classes is + a <, ==, or > b. + + a_meth, b_meth: Either None, indicating that all rich comparison + methods are available, aa for builtins, or the tuple (subset) + of "eq", "ne", "lt", "le", "gt", and "ge" that are available + for the corresponding instance (of a user-defined class). + """ + self.assert_eq_subtest(a, b, comp, a_meth, b_meth) + self.assert_ne_subtest(a, b, comp, a_meth, b_meth) + self.assert_lt_subtest(a, b, comp, a_meth, b_meth) + self.assert_le_subtest(a, b, comp, a_meth, b_meth) + self.assert_gt_subtest(a, b, comp, a_meth, b_meth) + self.assert_ge_subtest(a, b, comp, a_meth, b_meth) + + # The body of each subtest has form: + # + # if value-based comparison methods: + # expect what the testcase defined for a op b and b rop a; + # else: no value-based comparison + # expect default behavior of object for a op b and b rop a. + + def assert_eq_subtest(self, a, b, comp, a_meth, b_meth): + if a_meth is None or "eq" in a_meth or "eq" in b_meth: + self.assertEqual(a == b, comp == 0) + self.assertEqual(b == a, comp == 0) + else: + self.assertEqual(a == b, a is b) + self.assertEqual(b == a, a is b) + + def assert_ne_subtest(self, a, b, comp, a_meth, b_meth): + if a_meth is None or not {"ne", "eq"}.isdisjoint(a_meth + b_meth): + self.assertEqual(a != b, comp != 0) + self.assertEqual(b != a, comp != 0) + else: + self.assertEqual(a != b, a is not b) + self.assertEqual(b != a, a is not b) + + def assert_lt_subtest(self, a, b, comp, a_meth, b_meth): + if a_meth is None or "lt" in a_meth or "gt" in b_meth: + self.assertEqual(a < b, comp < 0) + self.assertEqual(b > a, comp < 0) + else: + with self.assertRaisesRegex(TypeError, "not supported"): + a < b + with self.assertRaisesRegex(TypeError, "not supported"): + b > a + + def assert_le_subtest(self, a, b, comp, a_meth, b_meth): + if a_meth is None or "le" in a_meth or "ge" in b_meth: + self.assertEqual(a <= b, comp <= 0) + self.assertEqual(b >= a, comp <= 0) + else: + with self.assertRaisesRegex(TypeError, "not supported"): + a <= b + with self.assertRaisesRegex(TypeError, "not supported"): + b >= a + + def assert_gt_subtest(self, a, b, comp, a_meth, b_meth): + if a_meth is None or "gt" in a_meth or "lt" in b_meth: + self.assertEqual(a > b, comp > 0) + self.assertEqual(b < a, comp > 0) + else: + with self.assertRaisesRegex(TypeError, "not supported"): + a > b + with self.assertRaisesRegex(TypeError, "not supported"): + b < a + + def assert_ge_subtest(self, a, b, comp, a_meth, b_meth): + if a_meth is None or "ge" in a_meth or "le" in b_meth: + self.assertEqual(a >= b, comp >= 0) + self.assertEqual(b <= a, comp >= 0) + else: + with self.assertRaisesRegex(TypeError, "not supported"): + a >= b + with self.assertRaisesRegex(TypeError, "not supported"): + b <= a + + def test_objects(self): + """Compare instances of type 'object'.""" + a = object() + b = object() + self.assert_equality_only(a, a, True) + self.assert_equality_only(a, b, False) + + def test_comp_classes_same(self): + """Compare same-class instances with comparison methods.""" + + for cls in self.all_comp_classes: + with self.subTest(cls): + instances = self.create_sorted_instances(cls, (1, 2, 1)) + + # Same object. + self.assert_total_order(instances[0], instances[0], 0, + cls.meth, cls.meth) + + # Different objects, same value. + self.assert_total_order(instances[0], instances[2], 0, + cls.meth, cls.meth) + + # Different objects, value ascending for ascending identities. + self.assert_total_order(instances[0], instances[1], -1, + cls.meth, cls.meth) + + # different objects, value descending for ascending identities. + # This is the interesting case to assert that order comparison + # is performed based on the value and not based on the identity. + self.assert_total_order(instances[1], instances[2], +1, + cls.meth, cls.meth) + + def test_comp_classes_different(self): + """Compare different-class instances with comparison methods.""" + + for cls_a in self.all_comp_classes: + for cls_b in self.all_comp_classes: + with self.subTest(a=cls_a, b=cls_b): + a1 = cls_a() + a1.x = 1 + b1 = cls_b() + b1.x = 1 + b2 = cls_b() + b2.x = 2 + + self.assert_total_order( + a1, b1, 0, cls_a.meth, cls_b.meth) + self.assert_total_order( + a1, b2, -1, cls_a.meth, cls_b.meth) + + def test_str_subclass(self): + """Compare instances of str and a subclass.""" + class StrSubclass(str): + pass + + s1 = str("a") + s2 = str("b") + c1 = StrSubclass("a") + c2 = StrSubclass("b") + c3 = StrSubclass("b") + + self.assert_total_order(s1, s1, 0) + self.assert_total_order(s1, s2, -1) + self.assert_total_order(c1, c1, 0) + self.assert_total_order(c1, c2, -1) + self.assert_total_order(c2, c3, 0) + + self.assert_total_order(s1, c2, -1) + self.assert_total_order(s2, c3, 0) + self.assert_total_order(c1, s2, -1) + self.assert_total_order(c2, s2, 0) + + def test_numbers(self): + """Compare number types.""" + + # Same types. + i1 = 1001 + i2 = 1002 + self.assert_total_order(i1, i1, 0) + self.assert_total_order(i1, i2, -1) + + f1 = 1001.0 + f2 = 1001.1 + self.assert_total_order(f1, f1, 0) + self.assert_total_order(f1, f2, -1) + + q1 = Fraction(2002, 2) + q2 = Fraction(2003, 2) + self.assert_total_order(q1, q1, 0) + self.assert_total_order(q1, q2, -1) + + d1 = Decimal('1001.0') + d2 = Decimal('1001.1') + self.assert_total_order(d1, d1, 0) + self.assert_total_order(d1, d2, -1) + + c1 = 1001+0j + c2 = 1001+1j + self.assert_equality_only(c1, c1, True) + self.assert_equality_only(c1, c2, False) + + + # Mixing types. + for n1, n2 in ((i1,f1), (i1,q1), (i1,d1), (f1,q1), (f1,d1), (q1,d1)): + self.assert_total_order(n1, n2, 0) + for n1 in (i1, f1, q1, d1): + self.assert_equality_only(n1, c1, True) + + def test_sequences(self): + """Compare list, tuple, and range.""" + l1 = [1, 2] + l2 = [2, 3] + self.assert_total_order(l1, l1, 0) + self.assert_total_order(l1, l2, -1) + + t1 = (1, 2) + t2 = (2, 3) + self.assert_total_order(t1, t1, 0) + self.assert_total_order(t1, t2, -1) + + r1 = range(1, 2) + r2 = range(2, 2) + self.assert_equality_only(r1, r1, True) + self.assert_equality_only(r1, r2, False) + + self.assert_equality_only(t1, l1, False) + self.assert_equality_only(l1, r1, False) + self.assert_equality_only(r1, t1, False) + + def test_bytes(self): + """Compare bytes and bytearray.""" + bs1 = b'a1' + bs2 = b'b2' + self.assert_total_order(bs1, bs1, 0) + self.assert_total_order(bs1, bs2, -1) + + ba1 = bytearray(b'a1') + ba2 = bytearray(b'b2') + self.assert_total_order(ba1, ba1, 0) + self.assert_total_order(ba1, ba2, -1) + + self.assert_total_order(bs1, ba1, 0) + self.assert_total_order(bs1, ba2, -1) + self.assert_total_order(ba1, bs1, 0) + self.assert_total_order(ba1, bs2, -1) + + def test_sets(self): + """Compare set and frozenset.""" + s1 = {1, 2} + s2 = {1, 2, 3} + self.assert_total_order(s1, s1, 0) + self.assert_total_order(s1, s2, -1) + + f1 = frozenset(s1) + f2 = frozenset(s2) + self.assert_total_order(f1, f1, 0) + self.assert_total_order(f1, f2, -1) + + self.assert_total_order(s1, f1, 0) + self.assert_total_order(s1, f2, -1) + self.assert_total_order(f1, s1, 0) + self.assert_total_order(f1, s2, -1) + + def test_mappings(self): + """ Compare dict. + """ + d1 = {1: "a", 2: "b"} + d2 = {2: "b", 3: "c"} + d3 = {3: "c", 2: "b"} + self.assert_equality_only(d1, d1, True) + self.assert_equality_only(d1, d2, False) + self.assert_equality_only(d2, d3, True) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index c68b9ce388466e..784c0550cc09b1 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1168,6 +1168,24 @@ def foo(param, lambda_exp): """) compile(code, "", "exec") + def test_apply_static_swaps(self): + def f(x, y): + a, a = x, y + return a + self.assertEqual(f("x", "y"), "y") + + def test_apply_static_swaps_2(self): + def f(x, y, z): + a, b, a = x, y, z + return a + self.assertEqual(f("x", "y", "z"), "z") + + def test_apply_static_swaps_3(self): + def f(x, y, z): + a, a, b = x, y, z + return a + self.assertEqual(f("x", "y", "z"), "y") + @requires_debug_ranges() class TestSourcePositions(unittest.TestCase): diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index fb7a016c9007f8..fe701025b70f48 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -4265,7 +4265,7 @@ class Color(Enum): 'mixed types with auto() will raise in 3.13', ) def test_auto_garbage_fail(self): - with self.assertRaisesRegex(TypeError, 'will require all values to be sortable'): + with self.assertRaisesRegex(TypeError, "unable to increment 'red'"): class Color(Enum): red = 'red' blue = auto() @@ -4275,7 +4275,7 @@ class Color(Enum): 'mixed types with auto() will raise in 3.13', ) def test_auto_garbage_corrected_fail(self): - with self.assertRaisesRegex(TypeError, 'will require all values to be sortable'): + with self.assertRaisesRegex(TypeError, 'unable to sort non-numeric values'): class Color(Enum): red = 'red' blue = 2 diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 8d106daaf6520a..2e97de592712c0 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -270,7 +270,7 @@ def check_fatal_error_func(self, release_gil): """, 2, 'xyz', - func='test_fatal_error', + func='_testcapi_fatal_error_impl', py_fatal_error=True) def test_fatal_error(self): diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 58e2550715cecf..3ba2f943e6e968 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -661,15 +661,50 @@ def test_comments(self): self.assertEqual(f'{"#"}', '#') self.assertEqual(f'{d["#"]}', 'hash') - self.assertAllRaise(SyntaxError, "f-string expression part cannot include '#'", - ["f'{1#}'", # error because the expression becomes "(1#)" - "f'{3(#)}'", + self.assertAllRaise(SyntaxError, "'{' was never closed", + ["f'{1#}'", # error because everything after '#' is a comment "f'{#}'", + "f'one: {1#}'", + "f'{1# one} {2 this is a comment still#}'", ]) self.assertAllRaise(SyntaxError, r"f-string: unmatched '\)'", ["f'{)#}'", # When wrapped in parens, this becomes # '()#)'. Make sure that doesn't compile. ]) + self.assertEqual(f'''A complex trick: { +2 # two +}''', 'A complex trick: 2') + self.assertEqual(f''' +{ +40 # fourty ++ # plus +2 # two +}''', '\n42') + self.assertEqual(f''' +{ +40 # fourty ++ # plus +2 # two +}''', '\n42') + + self.assertEqual(f''' +# this is not a comment +{ # the following operation it's +3 # this is a number +* 2}''', '\n# this is not a comment\n6') + self.assertEqual(f''' +{# f'a {comment}' +86 # constant +# nothing more +}''', '\n86') + + self.assertAllRaise(SyntaxError, r"f-string: valid expression required before '}'", + ["""f''' +{ +# only a comment +}''' +""", # this is equivalent to f'{}' + ]) def test_many_expressions(self): # Create a string with many expressions in it. Note that @@ -1558,7 +1593,21 @@ def test_not_closing_quotes(self): self.assertAllRaise(SyntaxError, "unterminated f-string literal", ['f"', "f'"]) self.assertAllRaise(SyntaxError, "unterminated triple-quoted f-string literal", ['f"""', "f'''"]) - + # Ensure that the errors are reported at the correct line number. + data = '''\ +x = 1 + 1 +y = 2 + 2 +z = f""" +sdfjnsdfjsdf +sdfsdfs{1+ +2} dfigdf {3+ +4}sdufsd"" +''' + try: + compile(data, "?", "exec") + except SyntaxError as e: + self.assertEqual(e.text, 'z = f"""') + self.assertEqual(e.lineno, 3) def test_syntax_error_after_debug(self): self.assertAllRaise(SyntaxError, "f-string: expecting a valid expression after '{'", [ diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py index 77977d0ae966f8..e08d72877d8aef 100644 --- a/Lib/test/test_funcattrs.py +++ b/Lib/test/test_funcattrs.py @@ -1,5 +1,6 @@ import textwrap import types +import typing import unittest @@ -190,6 +191,20 @@ def test___qualname__(self): # __qualname__ must be a string self.cannot_set_attr(self.b, '__qualname__', 7, TypeError) + def test___type_params__(self): + def generic[T](): pass + def not_generic(): pass + T, = generic.__type_params__ + self.assertIsInstance(T, typing.TypeVar) + self.assertEqual(generic.__type_params__, (T,)) + self.assertEqual(not_generic.__type_params__, ()) + with self.assertRaises(TypeError): + del not_generic.__type_params__ + with self.assertRaises(TypeError): + not_generic.__type_params__ = 42 + not_generic.__type_params__ = (T,) + self.assertEqual(not_generic.__type_params__, (T,)) + def test___code__(self): num_one, num_two = 7, 8 def a(): pass diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index af286052a7d560..d668fa4c3adf5c 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -617,7 +617,7 @@ def check_wrapper(self, wrapper, wrapped, def _default_update(self): - def f(a:'This is a new annotation'): + def f[T](a:'This is a new annotation'): """This is a test""" pass f.attr = 'This is also a test' @@ -630,12 +630,14 @@ def wrapper(b:'This is the prior annotation'): def test_default_update(self): wrapper, f = self._default_update() self.check_wrapper(wrapper, f) + T, = f.__type_params__ self.assertIs(wrapper.__wrapped__, f) self.assertEqual(wrapper.__name__, 'f') self.assertEqual(wrapper.__qualname__, f.__qualname__) self.assertEqual(wrapper.attr, 'This is also a test') self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation') self.assertNotIn('b', wrapper.__annotations__) + self.assertEqual(wrapper.__type_params__, (T,)) @unittest.skipIf(sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above") diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 4b1d355f550b49..8955d45fa93dd4 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -2401,7 +2401,7 @@ def test_proxy_response_headers(self): self.conn.set_tunnel('destination.com') self.conn.request('PUT', '/', '') - headers = self.conn._proxy_response_headers + headers = self.conn.get_proxy_response_headers() self.assertIn(expected_header, headers.items()) def test_tunnel_leak(self): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 364f75db908b05..0590e49d0e1a43 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2052,6 +2052,9 @@ class Foo(object): descriptor.__set__ = lambda s, i, v: None self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) + del descriptor.__set__ + descriptor.__delete__ = lambda s, i, o: None + self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) def test_metaclass_with_descriptor(self): class descriptor(object): diff --git a/Lib/test/test_keyword.py b/Lib/test/test_keyword.py index f329f88fa01d51..858e5de3b92e6a 100644 --- a/Lib/test/test_keyword.py +++ b/Lib/test/test_keyword.py @@ -39,7 +39,8 @@ def test_async_and_await_are_keywords(self): self.assertIn("async", keyword.kwlist) self.assertIn("await", keyword.kwlist) - def test_match_and_case_are_soft_keywords(self): + def test_soft_keywords(self): + self.assertIn("type", keyword.softkwlist) self.assertIn("match", keyword.softkwlist) self.assertIn("case", keyword.softkwlist) self.assertIn("_", keyword.softkwlist) diff --git a/Lib/test/test_lib2to3/__init__.py b/Lib/test/test_lib2to3/__init__.py deleted file mode 100644 index f323c2355b2287..00000000000000 --- a/Lib/test/test_lib2to3/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# Author: Collin Winter - -import os -import warnings - -from test.support import load_package_tests - -def load_tests(*args): - with warnings.catch_warnings(): - warnings.filterwarnings('ignore', category=DeprecationWarning, message='lib2to3') - return load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/test/test_lib2to3/__main__.py b/Lib/test/test_lib2to3/__main__.py deleted file mode 100644 index 40a23a297ec2b4..00000000000000 --- a/Lib/test/test_lib2to3/__main__.py +++ /dev/null @@ -1,4 +0,0 @@ -from . import load_tests -import unittest - -unittest.main() diff --git a/Lib/test/test_lib2to3/data/README b/Lib/test/test_lib2to3/data/README deleted file mode 100644 index 7aa47e40aa97f5..00000000000000 --- a/Lib/test/test_lib2to3/data/README +++ /dev/null @@ -1,6 +0,0 @@ -In this directory: -- py2_test_grammar.py -- test file that exercises most/all of Python 2.x's grammar. -- py3_test_grammar.py -- test file that exercises most/all of Python 3.x's grammar. -- infinite_recursion.py -- test file that causes lib2to3's faster recursive pattern matching - scheme to fail, but passes when lib2to3 falls back to iterative pattern matching. -- fixes/ -- for use by test_refactor.py diff --git a/Lib/test/test_lib2to3/data/bom.py b/Lib/test/test_lib2to3/data/bom.py deleted file mode 100644 index 9bc3975a42f601..00000000000000 --- a/Lib/test/test_lib2to3/data/bom.py +++ /dev/null @@ -1,2 +0,0 @@ -# coding: utf-8 -print "BOM BOOM!" diff --git a/Lib/test/test_lib2to3/data/crlf.py b/Lib/test/test_lib2to3/data/crlf.py deleted file mode 100644 index a83ca8f0a2068f..00000000000000 --- a/Lib/test/test_lib2to3/data/crlf.py +++ /dev/null @@ -1,3 +0,0 @@ -print "hi" - -print "Like bad Windows newlines?" diff --git a/Lib/test/test_lib2to3/data/different_encoding.py b/Lib/test/test_lib2to3/data/different_encoding.py deleted file mode 100755 index 9f32bd04dc28db..00000000000000 --- a/Lib/test/test_lib2to3/data/different_encoding.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -print u'ßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞ' - -def f(x): - print '%s\t-> α(%2i):%s β(%s)' diff --git a/Lib/test/test_lib2to3/data/false_encoding.py b/Lib/test/test_lib2to3/data/false_encoding.py deleted file mode 100755 index f4e59e787da1e5..00000000000000 --- a/Lib/test/test_lib2to3/data/false_encoding.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python -print '#coding=0' diff --git a/Lib/test/test_lib2to3/data/fixers/bad_order.py b/Lib/test/test_lib2to3/data/fixers/bad_order.py deleted file mode 100644 index 061bbf209a0dee..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/bad_order.py +++ /dev/null @@ -1,5 +0,0 @@ -from lib2to3.fixer_base import BaseFix - -class FixBadOrder(BaseFix): - - order = "crazy" diff --git a/Lib/test/test_lib2to3/data/fixers/myfixes/__init__.py b/Lib/test/test_lib2to3/data/fixers/myfixes/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_explicit.py b/Lib/test/test_lib2to3/data/fixers/myfixes/fix_explicit.py deleted file mode 100644 index cbe16f6f1f0dfc..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_explicit.py +++ /dev/null @@ -1,6 +0,0 @@ -from lib2to3.fixer_base import BaseFix - -class FixExplicit(BaseFix): - explicit = True - - def match(self): return False diff --git a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_first.py b/Lib/test/test_lib2to3/data/fixers/myfixes/fix_first.py deleted file mode 100644 index a88821f06b2d14..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_first.py +++ /dev/null @@ -1,6 +0,0 @@ -from lib2to3.fixer_base import BaseFix - -class FixFirst(BaseFix): - run_order = 1 - - def match(self, node): return False diff --git a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_last.py b/Lib/test/test_lib2to3/data/fixers/myfixes/fix_last.py deleted file mode 100644 index 9a077d41594da6..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_last.py +++ /dev/null @@ -1,7 +0,0 @@ -from lib2to3.fixer_base import BaseFix - -class FixLast(BaseFix): - - run_order = 10 - - def match(self, node): return False diff --git a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_parrot.py b/Lib/test/test_lib2to3/data/fixers/myfixes/fix_parrot.py deleted file mode 100644 index 6db79adf8d80c1..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_parrot.py +++ /dev/null @@ -1,13 +0,0 @@ -from lib2to3.fixer_base import BaseFix -from lib2to3.fixer_util import Name - -class FixParrot(BaseFix): - """ - Change functions named 'parrot' to 'cheese'. - """ - - PATTERN = """funcdef < 'def' name='parrot' any* >""" - - def transform(self, node, results): - name = results["name"] - name.replace(Name("cheese", name.prefix)) diff --git a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_preorder.py b/Lib/test/test_lib2to3/data/fixers/myfixes/fix_preorder.py deleted file mode 100644 index b9bfbba9d5e900..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/myfixes/fix_preorder.py +++ /dev/null @@ -1,6 +0,0 @@ -from lib2to3.fixer_base import BaseFix - -class FixPreorder(BaseFix): - order = "pre" - - def match(self, node): return False diff --git a/Lib/test/test_lib2to3/data/fixers/no_fixer_cls.py b/Lib/test/test_lib2to3/data/fixers/no_fixer_cls.py deleted file mode 100644 index 506f7949517058..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/no_fixer_cls.py +++ /dev/null @@ -1 +0,0 @@ -# This is empty so trying to fetch the fixer class gives an AttributeError diff --git a/Lib/test/test_lib2to3/data/fixers/parrot_example.py b/Lib/test/test_lib2to3/data/fixers/parrot_example.py deleted file mode 100644 index 08529280cdb4a1..00000000000000 --- a/Lib/test/test_lib2to3/data/fixers/parrot_example.py +++ /dev/null @@ -1,2 +0,0 @@ -def parrot(): - pass diff --git a/Lib/test/test_lib2to3/data/infinite_recursion.py b/Lib/test/test_lib2to3/data/infinite_recursion.py deleted file mode 100644 index acc62ed4f1a44c..00000000000000 --- a/Lib/test/test_lib2to3/data/infinite_recursion.py +++ /dev/null @@ -1,2669 +0,0 @@ -# Verify that 2to3 falls back from the recursive pattern matching scheme to a -# slower, iterative scheme in the event of a RecursionError. -from ctypes import * -STRING = c_char_p - - -OSUnknownByteOrder = 0 -UIT_PROMPT = 1 -P_PGID = 2 -P_PID = 1 -UIT_ERROR = 5 -UIT_INFO = 4 -UIT_NONE = 0 -P_ALL = 0 -UIT_VERIFY = 2 -OSBigEndian = 2 -UIT_BOOLEAN = 3 -OSLittleEndian = 1 -__darwin_nl_item = c_int -__darwin_wctrans_t = c_int -__darwin_wctype_t = c_ulong -__int8_t = c_byte -__uint8_t = c_ubyte -__int16_t = c_short -__uint16_t = c_ushort -__int32_t = c_int -__uint32_t = c_uint -__int64_t = c_longlong -__uint64_t = c_ulonglong -__darwin_intptr_t = c_long -__darwin_natural_t = c_uint -__darwin_ct_rune_t = c_int -class __mbstate_t(Union): - pass -__mbstate_t._pack_ = 4 -__mbstate_t._fields_ = [ - ('__mbstate8', c_char * 128), - ('_mbstateL', c_longlong), -] -assert sizeof(__mbstate_t) == 128, sizeof(__mbstate_t) -assert alignment(__mbstate_t) == 4, alignment(__mbstate_t) -__darwin_mbstate_t = __mbstate_t -__darwin_ptrdiff_t = c_int -__darwin_size_t = c_ulong -__darwin_va_list = STRING -__darwin_wchar_t = c_int -__darwin_rune_t = __darwin_wchar_t -__darwin_wint_t = c_int -__darwin_clock_t = c_ulong -__darwin_socklen_t = __uint32_t -__darwin_ssize_t = c_long -__darwin_time_t = c_long -sig_atomic_t = c_int -class sigcontext(Structure): - pass -sigcontext._fields_ = [ - ('sc_onstack', c_int), - ('sc_mask', c_int), - ('sc_eax', c_uint), - ('sc_ebx', c_uint), - ('sc_ecx', c_uint), - ('sc_edx', c_uint), - ('sc_edi', c_uint), - ('sc_esi', c_uint), - ('sc_ebp', c_uint), - ('sc_esp', c_uint), - ('sc_ss', c_uint), - ('sc_eflags', c_uint), - ('sc_eip', c_uint), - ('sc_cs', c_uint), - ('sc_ds', c_uint), - ('sc_es', c_uint), - ('sc_fs', c_uint), - ('sc_gs', c_uint), -] -assert sizeof(sigcontext) == 72, sizeof(sigcontext) -assert alignment(sigcontext) == 4, alignment(sigcontext) -u_int8_t = c_ubyte -u_int16_t = c_ushort -u_int32_t = c_uint -u_int64_t = c_ulonglong -int32_t = c_int -register_t = int32_t -user_addr_t = u_int64_t -user_size_t = u_int64_t -int64_t = c_longlong -user_ssize_t = int64_t -user_long_t = int64_t -user_ulong_t = u_int64_t -user_time_t = int64_t -syscall_arg_t = u_int64_t - -# values for unnamed enumeration -class aes_key_st(Structure): - pass -aes_key_st._fields_ = [ - ('rd_key', c_ulong * 60), - ('rounds', c_int), -] -assert sizeof(aes_key_st) == 244, sizeof(aes_key_st) -assert alignment(aes_key_st) == 4, alignment(aes_key_st) -AES_KEY = aes_key_st -class asn1_ctx_st(Structure): - pass -asn1_ctx_st._fields_ = [ - ('p', POINTER(c_ubyte)), - ('eos', c_int), - ('error', c_int), - ('inf', c_int), - ('tag', c_int), - ('xclass', c_int), - ('slen', c_long), - ('max', POINTER(c_ubyte)), - ('q', POINTER(c_ubyte)), - ('pp', POINTER(POINTER(c_ubyte))), - ('line', c_int), -] -assert sizeof(asn1_ctx_st) == 44, sizeof(asn1_ctx_st) -assert alignment(asn1_ctx_st) == 4, alignment(asn1_ctx_st) -ASN1_CTX = asn1_ctx_st -class asn1_object_st(Structure): - pass -asn1_object_st._fields_ = [ - ('sn', STRING), - ('ln', STRING), - ('nid', c_int), - ('length', c_int), - ('data', POINTER(c_ubyte)), - ('flags', c_int), -] -assert sizeof(asn1_object_st) == 24, sizeof(asn1_object_st) -assert alignment(asn1_object_st) == 4, alignment(asn1_object_st) -ASN1_OBJECT = asn1_object_st -class asn1_string_st(Structure): - pass -asn1_string_st._fields_ = [ - ('length', c_int), - ('type', c_int), - ('data', POINTER(c_ubyte)), - ('flags', c_long), -] -assert sizeof(asn1_string_st) == 16, sizeof(asn1_string_st) -assert alignment(asn1_string_st) == 4, alignment(asn1_string_st) -ASN1_STRING = asn1_string_st -class ASN1_ENCODING_st(Structure): - pass -ASN1_ENCODING_st._fields_ = [ - ('enc', POINTER(c_ubyte)), - ('len', c_long), - ('modified', c_int), -] -assert sizeof(ASN1_ENCODING_st) == 12, sizeof(ASN1_ENCODING_st) -assert alignment(ASN1_ENCODING_st) == 4, alignment(ASN1_ENCODING_st) -ASN1_ENCODING = ASN1_ENCODING_st -class asn1_string_table_st(Structure): - pass -asn1_string_table_st._fields_ = [ - ('nid', c_int), - ('minsize', c_long), - ('maxsize', c_long), - ('mask', c_ulong), - ('flags', c_ulong), -] -assert sizeof(asn1_string_table_st) == 20, sizeof(asn1_string_table_st) -assert alignment(asn1_string_table_st) == 4, alignment(asn1_string_table_st) -ASN1_STRING_TABLE = asn1_string_table_st -class ASN1_TEMPLATE_st(Structure): - pass -ASN1_TEMPLATE_st._fields_ = [ -] -ASN1_TEMPLATE = ASN1_TEMPLATE_st -class ASN1_ITEM_st(Structure): - pass -ASN1_ITEM = ASN1_ITEM_st -ASN1_ITEM_st._fields_ = [ -] -class ASN1_TLC_st(Structure): - pass -ASN1_TLC = ASN1_TLC_st -ASN1_TLC_st._fields_ = [ -] -class ASN1_VALUE_st(Structure): - pass -ASN1_VALUE_st._fields_ = [ -] -ASN1_VALUE = ASN1_VALUE_st -ASN1_ITEM_EXP = ASN1_ITEM -class asn1_type_st(Structure): - pass -class N12asn1_type_st4DOLLAR_11E(Union): - pass -ASN1_BOOLEAN = c_int -ASN1_INTEGER = asn1_string_st -ASN1_ENUMERATED = asn1_string_st -ASN1_BIT_STRING = asn1_string_st -ASN1_OCTET_STRING = asn1_string_st -ASN1_PRINTABLESTRING = asn1_string_st -ASN1_T61STRING = asn1_string_st -ASN1_IA5STRING = asn1_string_st -ASN1_GENERALSTRING = asn1_string_st -ASN1_BMPSTRING = asn1_string_st -ASN1_UNIVERSALSTRING = asn1_string_st -ASN1_UTCTIME = asn1_string_st -ASN1_GENERALIZEDTIME = asn1_string_st -ASN1_VISIBLESTRING = asn1_string_st -ASN1_UTF8STRING = asn1_string_st -N12asn1_type_st4DOLLAR_11E._fields_ = [ - ('ptr', STRING), - ('boolean', ASN1_BOOLEAN), - ('asn1_string', POINTER(ASN1_STRING)), - ('object', POINTER(ASN1_OBJECT)), - ('integer', POINTER(ASN1_INTEGER)), - ('enumerated', POINTER(ASN1_ENUMERATED)), - ('bit_string', POINTER(ASN1_BIT_STRING)), - ('octet_string', POINTER(ASN1_OCTET_STRING)), - ('printablestring', POINTER(ASN1_PRINTABLESTRING)), - ('t61string', POINTER(ASN1_T61STRING)), - ('ia5string', POINTER(ASN1_IA5STRING)), - ('generalstring', POINTER(ASN1_GENERALSTRING)), - ('bmpstring', POINTER(ASN1_BMPSTRING)), - ('universalstring', POINTER(ASN1_UNIVERSALSTRING)), - ('utctime', POINTER(ASN1_UTCTIME)), - ('generalizedtime', POINTER(ASN1_GENERALIZEDTIME)), - ('visiblestring', POINTER(ASN1_VISIBLESTRING)), - ('utf8string', POINTER(ASN1_UTF8STRING)), - ('set', POINTER(ASN1_STRING)), - ('sequence', POINTER(ASN1_STRING)), -] -assert sizeof(N12asn1_type_st4DOLLAR_11E) == 4, sizeof(N12asn1_type_st4DOLLAR_11E) -assert alignment(N12asn1_type_st4DOLLAR_11E) == 4, alignment(N12asn1_type_st4DOLLAR_11E) -asn1_type_st._fields_ = [ - ('type', c_int), - ('value', N12asn1_type_st4DOLLAR_11E), -] -assert sizeof(asn1_type_st) == 8, sizeof(asn1_type_st) -assert alignment(asn1_type_st) == 4, alignment(asn1_type_st) -ASN1_TYPE = asn1_type_st -class asn1_method_st(Structure): - pass -asn1_method_st._fields_ = [ - ('i2d', CFUNCTYPE(c_int)), - ('d2i', CFUNCTYPE(STRING)), - ('create', CFUNCTYPE(STRING)), - ('destroy', CFUNCTYPE(None)), -] -assert sizeof(asn1_method_st) == 16, sizeof(asn1_method_st) -assert alignment(asn1_method_st) == 4, alignment(asn1_method_st) -ASN1_METHOD = asn1_method_st -class asn1_header_st(Structure): - pass -asn1_header_st._fields_ = [ - ('header', POINTER(ASN1_OCTET_STRING)), - ('data', STRING), - ('meth', POINTER(ASN1_METHOD)), -] -assert sizeof(asn1_header_st) == 12, sizeof(asn1_header_st) -assert alignment(asn1_header_st) == 4, alignment(asn1_header_st) -ASN1_HEADER = asn1_header_st -class BIT_STRING_BITNAME_st(Structure): - pass -BIT_STRING_BITNAME_st._fields_ = [ - ('bitnum', c_int), - ('lname', STRING), - ('sname', STRING), -] -assert sizeof(BIT_STRING_BITNAME_st) == 12, sizeof(BIT_STRING_BITNAME_st) -assert alignment(BIT_STRING_BITNAME_st) == 4, alignment(BIT_STRING_BITNAME_st) -BIT_STRING_BITNAME = BIT_STRING_BITNAME_st -class bio_st(Structure): - pass -BIO = bio_st -bio_info_cb = CFUNCTYPE(None, POINTER(bio_st), c_int, STRING, c_int, c_long, c_long) -class bio_method_st(Structure): - pass -bio_method_st._fields_ = [ - ('type', c_int), - ('name', STRING), - ('bwrite', CFUNCTYPE(c_int, POINTER(BIO), STRING, c_int)), - ('bread', CFUNCTYPE(c_int, POINTER(BIO), STRING, c_int)), - ('bputs', CFUNCTYPE(c_int, POINTER(BIO), STRING)), - ('bgets', CFUNCTYPE(c_int, POINTER(BIO), STRING, c_int)), - ('ctrl', CFUNCTYPE(c_long, POINTER(BIO), c_int, c_long, c_void_p)), - ('create', CFUNCTYPE(c_int, POINTER(BIO))), - ('destroy', CFUNCTYPE(c_int, POINTER(BIO))), - ('callback_ctrl', CFUNCTYPE(c_long, POINTER(BIO), c_int, POINTER(bio_info_cb))), -] -assert sizeof(bio_method_st) == 40, sizeof(bio_method_st) -assert alignment(bio_method_st) == 4, alignment(bio_method_st) -BIO_METHOD = bio_method_st -class crypto_ex_data_st(Structure): - pass -class stack_st(Structure): - pass -STACK = stack_st -crypto_ex_data_st._fields_ = [ - ('sk', POINTER(STACK)), - ('dummy', c_int), -] -assert sizeof(crypto_ex_data_st) == 8, sizeof(crypto_ex_data_st) -assert alignment(crypto_ex_data_st) == 4, alignment(crypto_ex_data_st) -CRYPTO_EX_DATA = crypto_ex_data_st -bio_st._fields_ = [ - ('method', POINTER(BIO_METHOD)), - ('callback', CFUNCTYPE(c_long, POINTER(bio_st), c_int, STRING, c_int, c_long, c_long)), - ('cb_arg', STRING), - ('init', c_int), - ('shutdown', c_int), - ('flags', c_int), - ('retry_reason', c_int), - ('num', c_int), - ('ptr', c_void_p), - ('next_bio', POINTER(bio_st)), - ('prev_bio', POINTER(bio_st)), - ('references', c_int), - ('num_read', c_ulong), - ('num_write', c_ulong), - ('ex_data', CRYPTO_EX_DATA), -] -assert sizeof(bio_st) == 64, sizeof(bio_st) -assert alignment(bio_st) == 4, alignment(bio_st) -class bio_f_buffer_ctx_struct(Structure): - pass -bio_f_buffer_ctx_struct._fields_ = [ - ('ibuf_size', c_int), - ('obuf_size', c_int), - ('ibuf', STRING), - ('ibuf_len', c_int), - ('ibuf_off', c_int), - ('obuf', STRING), - ('obuf_len', c_int), - ('obuf_off', c_int), -] -assert sizeof(bio_f_buffer_ctx_struct) == 32, sizeof(bio_f_buffer_ctx_struct) -assert alignment(bio_f_buffer_ctx_struct) == 4, alignment(bio_f_buffer_ctx_struct) -BIO_F_BUFFER_CTX = bio_f_buffer_ctx_struct -class hostent(Structure): - pass -hostent._fields_ = [ -] -class bf_key_st(Structure): - pass -bf_key_st._fields_ = [ - ('P', c_uint * 18), - ('S', c_uint * 1024), -] -assert sizeof(bf_key_st) == 4168, sizeof(bf_key_st) -assert alignment(bf_key_st) == 4, alignment(bf_key_st) -BF_KEY = bf_key_st -class bignum_st(Structure): - pass -bignum_st._fields_ = [ - ('d', POINTER(c_ulong)), - ('top', c_int), - ('dmax', c_int), - ('neg', c_int), - ('flags', c_int), -] -assert sizeof(bignum_st) == 20, sizeof(bignum_st) -assert alignment(bignum_st) == 4, alignment(bignum_st) -BIGNUM = bignum_st -class bignum_ctx(Structure): - pass -bignum_ctx._fields_ = [ -] -BN_CTX = bignum_ctx -class bn_blinding_st(Structure): - pass -bn_blinding_st._fields_ = [ - ('init', c_int), - ('A', POINTER(BIGNUM)), - ('Ai', POINTER(BIGNUM)), - ('mod', POINTER(BIGNUM)), - ('thread_id', c_ulong), -] -assert sizeof(bn_blinding_st) == 20, sizeof(bn_blinding_st) -assert alignment(bn_blinding_st) == 4, alignment(bn_blinding_st) -BN_BLINDING = bn_blinding_st -class bn_mont_ctx_st(Structure): - pass -bn_mont_ctx_st._fields_ = [ - ('ri', c_int), - ('RR', BIGNUM), - ('N', BIGNUM), - ('Ni', BIGNUM), - ('n0', c_ulong), - ('flags', c_int), -] -assert sizeof(bn_mont_ctx_st) == 72, sizeof(bn_mont_ctx_st) -assert alignment(bn_mont_ctx_st) == 4, alignment(bn_mont_ctx_st) -BN_MONT_CTX = bn_mont_ctx_st -class bn_recp_ctx_st(Structure): - pass -bn_recp_ctx_st._fields_ = [ - ('N', BIGNUM), - ('Nr', BIGNUM), - ('num_bits', c_int), - ('shift', c_int), - ('flags', c_int), -] -assert sizeof(bn_recp_ctx_st) == 52, sizeof(bn_recp_ctx_st) -assert alignment(bn_recp_ctx_st) == 4, alignment(bn_recp_ctx_st) -BN_RECP_CTX = bn_recp_ctx_st -class buf_mem_st(Structure): - pass -buf_mem_st._fields_ = [ - ('length', c_int), - ('data', STRING), - ('max', c_int), -] -assert sizeof(buf_mem_st) == 12, sizeof(buf_mem_st) -assert alignment(buf_mem_st) == 4, alignment(buf_mem_st) -BUF_MEM = buf_mem_st -class cast_key_st(Structure): - pass -cast_key_st._fields_ = [ - ('data', c_ulong * 32), - ('short_key', c_int), -] -assert sizeof(cast_key_st) == 132, sizeof(cast_key_st) -assert alignment(cast_key_st) == 4, alignment(cast_key_st) -CAST_KEY = cast_key_st -class comp_method_st(Structure): - pass -comp_method_st._fields_ = [ - ('type', c_int), - ('name', STRING), - ('init', CFUNCTYPE(c_int)), - ('finish', CFUNCTYPE(None)), - ('compress', CFUNCTYPE(c_int)), - ('expand', CFUNCTYPE(c_int)), - ('ctrl', CFUNCTYPE(c_long)), - ('callback_ctrl', CFUNCTYPE(c_long)), -] -assert sizeof(comp_method_st) == 32, sizeof(comp_method_st) -assert alignment(comp_method_st) == 4, alignment(comp_method_st) -COMP_METHOD = comp_method_st -class comp_ctx_st(Structure): - pass -comp_ctx_st._fields_ = [ - ('meth', POINTER(COMP_METHOD)), - ('compress_in', c_ulong), - ('compress_out', c_ulong), - ('expand_in', c_ulong), - ('expand_out', c_ulong), - ('ex_data', CRYPTO_EX_DATA), -] -assert sizeof(comp_ctx_st) == 28, sizeof(comp_ctx_st) -assert alignment(comp_ctx_st) == 4, alignment(comp_ctx_st) -COMP_CTX = comp_ctx_st -class CRYPTO_dynlock_value(Structure): - pass -CRYPTO_dynlock_value._fields_ = [ -] -class CRYPTO_dynlock(Structure): - pass -CRYPTO_dynlock._fields_ = [ - ('references', c_int), - ('data', POINTER(CRYPTO_dynlock_value)), -] -assert sizeof(CRYPTO_dynlock) == 8, sizeof(CRYPTO_dynlock) -assert alignment(CRYPTO_dynlock) == 4, alignment(CRYPTO_dynlock) -BIO_dummy = bio_st -CRYPTO_EX_new = CFUNCTYPE(c_int, c_void_p, c_void_p, POINTER(CRYPTO_EX_DATA), c_int, c_long, c_void_p) -CRYPTO_EX_free = CFUNCTYPE(None, c_void_p, c_void_p, POINTER(CRYPTO_EX_DATA), c_int, c_long, c_void_p) -CRYPTO_EX_dup = CFUNCTYPE(c_int, POINTER(CRYPTO_EX_DATA), POINTER(CRYPTO_EX_DATA), c_void_p, c_int, c_long, c_void_p) -class crypto_ex_data_func_st(Structure): - pass -crypto_ex_data_func_st._fields_ = [ - ('argl', c_long), - ('argp', c_void_p), - ('new_func', POINTER(CRYPTO_EX_new)), - ('free_func', POINTER(CRYPTO_EX_free)), - ('dup_func', POINTER(CRYPTO_EX_dup)), -] -assert sizeof(crypto_ex_data_func_st) == 20, sizeof(crypto_ex_data_func_st) -assert alignment(crypto_ex_data_func_st) == 4, alignment(crypto_ex_data_func_st) -CRYPTO_EX_DATA_FUNCS = crypto_ex_data_func_st -class st_CRYPTO_EX_DATA_IMPL(Structure): - pass -CRYPTO_EX_DATA_IMPL = st_CRYPTO_EX_DATA_IMPL -st_CRYPTO_EX_DATA_IMPL._fields_ = [ -] -CRYPTO_MEM_LEAK_CB = CFUNCTYPE(c_void_p, c_ulong, STRING, c_int, c_int, c_void_p) -DES_cblock = c_ubyte * 8 -const_DES_cblock = c_ubyte * 8 -class DES_ks(Structure): - pass -class N6DES_ks3DOLLAR_9E(Union): - pass -N6DES_ks3DOLLAR_9E._fields_ = [ - ('cblock', DES_cblock), - ('deslong', c_ulong * 2), -] -assert sizeof(N6DES_ks3DOLLAR_9E) == 8, sizeof(N6DES_ks3DOLLAR_9E) -assert alignment(N6DES_ks3DOLLAR_9E) == 4, alignment(N6DES_ks3DOLLAR_9E) -DES_ks._fields_ = [ - ('ks', N6DES_ks3DOLLAR_9E * 16), -] -assert sizeof(DES_ks) == 128, sizeof(DES_ks) -assert alignment(DES_ks) == 4, alignment(DES_ks) -DES_key_schedule = DES_ks -_ossl_old_des_cblock = c_ubyte * 8 -class _ossl_old_des_ks_struct(Structure): - pass -class N23_ossl_old_des_ks_struct4DOLLAR_10E(Union): - pass -N23_ossl_old_des_ks_struct4DOLLAR_10E._fields_ = [ - ('_', _ossl_old_des_cblock), - ('pad', c_ulong * 2), -] -assert sizeof(N23_ossl_old_des_ks_struct4DOLLAR_10E) == 8, sizeof(N23_ossl_old_des_ks_struct4DOLLAR_10E) -assert alignment(N23_ossl_old_des_ks_struct4DOLLAR_10E) == 4, alignment(N23_ossl_old_des_ks_struct4DOLLAR_10E) -_ossl_old_des_ks_struct._fields_ = [ - ('ks', N23_ossl_old_des_ks_struct4DOLLAR_10E), -] -assert sizeof(_ossl_old_des_ks_struct) == 8, sizeof(_ossl_old_des_ks_struct) -assert alignment(_ossl_old_des_ks_struct) == 4, alignment(_ossl_old_des_ks_struct) -_ossl_old_des_key_schedule = _ossl_old_des_ks_struct * 16 -class dh_st(Structure): - pass -DH = dh_st -class dh_method(Structure): - pass -dh_method._fields_ = [ - ('name', STRING), - ('generate_key', CFUNCTYPE(c_int, POINTER(DH))), - ('compute_key', CFUNCTYPE(c_int, POINTER(c_ubyte), POINTER(BIGNUM), POINTER(DH))), - ('bn_mod_exp', CFUNCTYPE(c_int, POINTER(DH), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BN_CTX), POINTER(BN_MONT_CTX))), - ('init', CFUNCTYPE(c_int, POINTER(DH))), - ('finish', CFUNCTYPE(c_int, POINTER(DH))), - ('flags', c_int), - ('app_data', STRING), -] -assert sizeof(dh_method) == 32, sizeof(dh_method) -assert alignment(dh_method) == 4, alignment(dh_method) -DH_METHOD = dh_method -class engine_st(Structure): - pass -ENGINE = engine_st -dh_st._fields_ = [ - ('pad', c_int), - ('version', c_int), - ('p', POINTER(BIGNUM)), - ('g', POINTER(BIGNUM)), - ('length', c_long), - ('pub_key', POINTER(BIGNUM)), - ('priv_key', POINTER(BIGNUM)), - ('flags', c_int), - ('method_mont_p', STRING), - ('q', POINTER(BIGNUM)), - ('j', POINTER(BIGNUM)), - ('seed', POINTER(c_ubyte)), - ('seedlen', c_int), - ('counter', POINTER(BIGNUM)), - ('references', c_int), - ('ex_data', CRYPTO_EX_DATA), - ('meth', POINTER(DH_METHOD)), - ('engine', POINTER(ENGINE)), -] -assert sizeof(dh_st) == 76, sizeof(dh_st) -assert alignment(dh_st) == 4, alignment(dh_st) -class dsa_st(Structure): - pass -DSA = dsa_st -class DSA_SIG_st(Structure): - pass -DSA_SIG_st._fields_ = [ - ('r', POINTER(BIGNUM)), - ('s', POINTER(BIGNUM)), -] -assert sizeof(DSA_SIG_st) == 8, sizeof(DSA_SIG_st) -assert alignment(DSA_SIG_st) == 4, alignment(DSA_SIG_st) -DSA_SIG = DSA_SIG_st -class dsa_method(Structure): - pass -dsa_method._fields_ = [ - ('name', STRING), - ('dsa_do_sign', CFUNCTYPE(POINTER(DSA_SIG), POINTER(c_ubyte), c_int, POINTER(DSA))), - ('dsa_sign_setup', CFUNCTYPE(c_int, POINTER(DSA), POINTER(BN_CTX), POINTER(POINTER(BIGNUM)), POINTER(POINTER(BIGNUM)))), - ('dsa_do_verify', CFUNCTYPE(c_int, POINTER(c_ubyte), c_int, POINTER(DSA_SIG), POINTER(DSA))), - ('dsa_mod_exp', CFUNCTYPE(c_int, POINTER(DSA), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BN_CTX), POINTER(BN_MONT_CTX))), - ('bn_mod_exp', CFUNCTYPE(c_int, POINTER(DSA), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BN_CTX), POINTER(BN_MONT_CTX))), - ('init', CFUNCTYPE(c_int, POINTER(DSA))), - ('finish', CFUNCTYPE(c_int, POINTER(DSA))), - ('flags', c_int), - ('app_data', STRING), -] -assert sizeof(dsa_method) == 40, sizeof(dsa_method) -assert alignment(dsa_method) == 4, alignment(dsa_method) -DSA_METHOD = dsa_method -dsa_st._fields_ = [ - ('pad', c_int), - ('version', c_long), - ('write_params', c_int), - ('p', POINTER(BIGNUM)), - ('q', POINTER(BIGNUM)), - ('g', POINTER(BIGNUM)), - ('pub_key', POINTER(BIGNUM)), - ('priv_key', POINTER(BIGNUM)), - ('kinv', POINTER(BIGNUM)), - ('r', POINTER(BIGNUM)), - ('flags', c_int), - ('method_mont_p', STRING), - ('references', c_int), - ('ex_data', CRYPTO_EX_DATA), - ('meth', POINTER(DSA_METHOD)), - ('engine', POINTER(ENGINE)), -] -assert sizeof(dsa_st) == 68, sizeof(dsa_st) -assert alignment(dsa_st) == 4, alignment(dsa_st) -class evp_pkey_st(Structure): - pass -class N11evp_pkey_st4DOLLAR_12E(Union): - pass -class rsa_st(Structure): - pass -N11evp_pkey_st4DOLLAR_12E._fields_ = [ - ('ptr', STRING), - ('rsa', POINTER(rsa_st)), - ('dsa', POINTER(dsa_st)), - ('dh', POINTER(dh_st)), -] -assert sizeof(N11evp_pkey_st4DOLLAR_12E) == 4, sizeof(N11evp_pkey_st4DOLLAR_12E) -assert alignment(N11evp_pkey_st4DOLLAR_12E) == 4, alignment(N11evp_pkey_st4DOLLAR_12E) -evp_pkey_st._fields_ = [ - ('type', c_int), - ('save_type', c_int), - ('references', c_int), - ('pkey', N11evp_pkey_st4DOLLAR_12E), - ('save_parameters', c_int), - ('attributes', POINTER(STACK)), -] -assert sizeof(evp_pkey_st) == 24, sizeof(evp_pkey_st) -assert alignment(evp_pkey_st) == 4, alignment(evp_pkey_st) -class env_md_st(Structure): - pass -class env_md_ctx_st(Structure): - pass -EVP_MD_CTX = env_md_ctx_st -env_md_st._fields_ = [ - ('type', c_int), - ('pkey_type', c_int), - ('md_size', c_int), - ('flags', c_ulong), - ('init', CFUNCTYPE(c_int, POINTER(EVP_MD_CTX))), - ('update', CFUNCTYPE(c_int, POINTER(EVP_MD_CTX), c_void_p, c_ulong)), - ('final', CFUNCTYPE(c_int, POINTER(EVP_MD_CTX), POINTER(c_ubyte))), - ('copy', CFUNCTYPE(c_int, POINTER(EVP_MD_CTX), POINTER(EVP_MD_CTX))), - ('cleanup', CFUNCTYPE(c_int, POINTER(EVP_MD_CTX))), - ('sign', CFUNCTYPE(c_int)), - ('verify', CFUNCTYPE(c_int)), - ('required_pkey_type', c_int * 5), - ('block_size', c_int), - ('ctx_size', c_int), -] -assert sizeof(env_md_st) == 72, sizeof(env_md_st) -assert alignment(env_md_st) == 4, alignment(env_md_st) -EVP_MD = env_md_st -env_md_ctx_st._fields_ = [ - ('digest', POINTER(EVP_MD)), - ('engine', POINTER(ENGINE)), - ('flags', c_ulong), - ('md_data', c_void_p), -] -assert sizeof(env_md_ctx_st) == 16, sizeof(env_md_ctx_st) -assert alignment(env_md_ctx_st) == 4, alignment(env_md_ctx_st) -class evp_cipher_st(Structure): - pass -class evp_cipher_ctx_st(Structure): - pass -EVP_CIPHER_CTX = evp_cipher_ctx_st -evp_cipher_st._fields_ = [ - ('nid', c_int), - ('block_size', c_int), - ('key_len', c_int), - ('iv_len', c_int), - ('flags', c_ulong), - ('init', CFUNCTYPE(c_int, POINTER(EVP_CIPHER_CTX), POINTER(c_ubyte), POINTER(c_ubyte), c_int)), - ('do_cipher', CFUNCTYPE(c_int, POINTER(EVP_CIPHER_CTX), POINTER(c_ubyte), POINTER(c_ubyte), c_uint)), - ('cleanup', CFUNCTYPE(c_int, POINTER(EVP_CIPHER_CTX))), - ('ctx_size', c_int), - ('set_asn1_parameters', CFUNCTYPE(c_int, POINTER(EVP_CIPHER_CTX), POINTER(ASN1_TYPE))), - ('get_asn1_parameters', CFUNCTYPE(c_int, POINTER(EVP_CIPHER_CTX), POINTER(ASN1_TYPE))), - ('ctrl', CFUNCTYPE(c_int, POINTER(EVP_CIPHER_CTX), c_int, c_int, c_void_p)), - ('app_data', c_void_p), -] -assert sizeof(evp_cipher_st) == 52, sizeof(evp_cipher_st) -assert alignment(evp_cipher_st) == 4, alignment(evp_cipher_st) -class evp_cipher_info_st(Structure): - pass -EVP_CIPHER = evp_cipher_st -evp_cipher_info_st._fields_ = [ - ('cipher', POINTER(EVP_CIPHER)), - ('iv', c_ubyte * 16), -] -assert sizeof(evp_cipher_info_st) == 20, sizeof(evp_cipher_info_st) -assert alignment(evp_cipher_info_st) == 4, alignment(evp_cipher_info_st) -EVP_CIPHER_INFO = evp_cipher_info_st -evp_cipher_ctx_st._fields_ = [ - ('cipher', POINTER(EVP_CIPHER)), - ('engine', POINTER(ENGINE)), - ('encrypt', c_int), - ('buf_len', c_int), - ('oiv', c_ubyte * 16), - ('iv', c_ubyte * 16), - ('buf', c_ubyte * 32), - ('num', c_int), - ('app_data', c_void_p), - ('key_len', c_int), - ('flags', c_ulong), - ('cipher_data', c_void_p), - ('final_used', c_int), - ('block_mask', c_int), - ('final', c_ubyte * 32), -] -assert sizeof(evp_cipher_ctx_st) == 140, sizeof(evp_cipher_ctx_st) -assert alignment(evp_cipher_ctx_st) == 4, alignment(evp_cipher_ctx_st) -class evp_Encode_Ctx_st(Structure): - pass -evp_Encode_Ctx_st._fields_ = [ - ('num', c_int), - ('length', c_int), - ('enc_data', c_ubyte * 80), - ('line_num', c_int), - ('expect_nl', c_int), -] -assert sizeof(evp_Encode_Ctx_st) == 96, sizeof(evp_Encode_Ctx_st) -assert alignment(evp_Encode_Ctx_st) == 4, alignment(evp_Encode_Ctx_st) -EVP_ENCODE_CTX = evp_Encode_Ctx_st -EVP_PBE_KEYGEN = CFUNCTYPE(c_int, POINTER(EVP_CIPHER_CTX), STRING, c_int, POINTER(ASN1_TYPE), POINTER(EVP_CIPHER), POINTER(EVP_MD), c_int) -class lhash_node_st(Structure): - pass -lhash_node_st._fields_ = [ - ('data', c_void_p), - ('next', POINTER(lhash_node_st)), - ('hash', c_ulong), -] -assert sizeof(lhash_node_st) == 12, sizeof(lhash_node_st) -assert alignment(lhash_node_st) == 4, alignment(lhash_node_st) -LHASH_NODE = lhash_node_st -LHASH_COMP_FN_TYPE = CFUNCTYPE(c_int, c_void_p, c_void_p) -LHASH_HASH_FN_TYPE = CFUNCTYPE(c_ulong, c_void_p) -LHASH_DOALL_FN_TYPE = CFUNCTYPE(None, c_void_p) -LHASH_DOALL_ARG_FN_TYPE = CFUNCTYPE(None, c_void_p, c_void_p) -class lhash_st(Structure): - pass -lhash_st._fields_ = [ - ('b', POINTER(POINTER(LHASH_NODE))), - ('comp', LHASH_COMP_FN_TYPE), - ('hash', LHASH_HASH_FN_TYPE), - ('num_nodes', c_uint), - ('num_alloc_nodes', c_uint), - ('p', c_uint), - ('pmax', c_uint), - ('up_load', c_ulong), - ('down_load', c_ulong), - ('num_items', c_ulong), - ('num_expands', c_ulong), - ('num_expand_reallocs', c_ulong), - ('num_contracts', c_ulong), - ('num_contract_reallocs', c_ulong), - ('num_hash_calls', c_ulong), - ('num_comp_calls', c_ulong), - ('num_insert', c_ulong), - ('num_replace', c_ulong), - ('num_delete', c_ulong), - ('num_no_delete', c_ulong), - ('num_retrieve', c_ulong), - ('num_retrieve_miss', c_ulong), - ('num_hash_comps', c_ulong), - ('error', c_int), -] -assert sizeof(lhash_st) == 96, sizeof(lhash_st) -assert alignment(lhash_st) == 4, alignment(lhash_st) -LHASH = lhash_st -class MD2state_st(Structure): - pass -MD2state_st._fields_ = [ - ('num', c_int), - ('data', c_ubyte * 16), - ('cksm', c_uint * 16), - ('state', c_uint * 16), -] -assert sizeof(MD2state_st) == 148, sizeof(MD2state_st) -assert alignment(MD2state_st) == 4, alignment(MD2state_st) -MD2_CTX = MD2state_st -class MD4state_st(Structure): - pass -MD4state_st._fields_ = [ - ('A', c_uint), - ('B', c_uint), - ('C', c_uint), - ('D', c_uint), - ('Nl', c_uint), - ('Nh', c_uint), - ('data', c_uint * 16), - ('num', c_int), -] -assert sizeof(MD4state_st) == 92, sizeof(MD4state_st) -assert alignment(MD4state_st) == 4, alignment(MD4state_st) -MD4_CTX = MD4state_st -class MD5state_st(Structure): - pass -MD5state_st._fields_ = [ - ('A', c_uint), - ('B', c_uint), - ('C', c_uint), - ('D', c_uint), - ('Nl', c_uint), - ('Nh', c_uint), - ('data', c_uint * 16), - ('num', c_int), -] -assert sizeof(MD5state_st) == 92, sizeof(MD5state_st) -assert alignment(MD5state_st) == 4, alignment(MD5state_st) -MD5_CTX = MD5state_st -class mdc2_ctx_st(Structure): - pass -mdc2_ctx_st._fields_ = [ - ('num', c_int), - ('data', c_ubyte * 8), - ('h', DES_cblock), - ('hh', DES_cblock), - ('pad_type', c_int), -] -assert sizeof(mdc2_ctx_st) == 32, sizeof(mdc2_ctx_st) -assert alignment(mdc2_ctx_st) == 4, alignment(mdc2_ctx_st) -MDC2_CTX = mdc2_ctx_st -class obj_name_st(Structure): - pass -obj_name_st._fields_ = [ - ('type', c_int), - ('alias', c_int), - ('name', STRING), - ('data', STRING), -] -assert sizeof(obj_name_st) == 16, sizeof(obj_name_st) -assert alignment(obj_name_st) == 4, alignment(obj_name_st) -OBJ_NAME = obj_name_st -ASN1_TIME = asn1_string_st -ASN1_NULL = c_int -EVP_PKEY = evp_pkey_st -class x509_st(Structure): - pass -X509 = x509_st -class X509_algor_st(Structure): - pass -X509_ALGOR = X509_algor_st -class X509_crl_st(Structure): - pass -X509_CRL = X509_crl_st -class X509_name_st(Structure): - pass -X509_NAME = X509_name_st -class x509_store_st(Structure): - pass -X509_STORE = x509_store_st -class x509_store_ctx_st(Structure): - pass -X509_STORE_CTX = x509_store_ctx_st -engine_st._fields_ = [ -] -class PEM_Encode_Seal_st(Structure): - pass -PEM_Encode_Seal_st._fields_ = [ - ('encode', EVP_ENCODE_CTX), - ('md', EVP_MD_CTX), - ('cipher', EVP_CIPHER_CTX), -] -assert sizeof(PEM_Encode_Seal_st) == 252, sizeof(PEM_Encode_Seal_st) -assert alignment(PEM_Encode_Seal_st) == 4, alignment(PEM_Encode_Seal_st) -PEM_ENCODE_SEAL_CTX = PEM_Encode_Seal_st -class pem_recip_st(Structure): - pass -pem_recip_st._fields_ = [ - ('name', STRING), - ('dn', POINTER(X509_NAME)), - ('cipher', c_int), - ('key_enc', c_int), -] -assert sizeof(pem_recip_st) == 16, sizeof(pem_recip_st) -assert alignment(pem_recip_st) == 4, alignment(pem_recip_st) -PEM_USER = pem_recip_st -class pem_ctx_st(Structure): - pass -class N10pem_ctx_st4DOLLAR_16E(Structure): - pass -N10pem_ctx_st4DOLLAR_16E._fields_ = [ - ('version', c_int), - ('mode', c_int), -] -assert sizeof(N10pem_ctx_st4DOLLAR_16E) == 8, sizeof(N10pem_ctx_st4DOLLAR_16E) -assert alignment(N10pem_ctx_st4DOLLAR_16E) == 4, alignment(N10pem_ctx_st4DOLLAR_16E) -class N10pem_ctx_st4DOLLAR_17E(Structure): - pass -N10pem_ctx_st4DOLLAR_17E._fields_ = [ - ('cipher', c_int), -] -assert sizeof(N10pem_ctx_st4DOLLAR_17E) == 4, sizeof(N10pem_ctx_st4DOLLAR_17E) -assert alignment(N10pem_ctx_st4DOLLAR_17E) == 4, alignment(N10pem_ctx_st4DOLLAR_17E) -pem_ctx_st._fields_ = [ - ('type', c_int), - ('proc_type', N10pem_ctx_st4DOLLAR_16E), - ('domain', STRING), - ('DEK_info', N10pem_ctx_st4DOLLAR_17E), - ('originator', POINTER(PEM_USER)), - ('num_recipient', c_int), - ('recipient', POINTER(POINTER(PEM_USER))), - ('x509_chain', POINTER(STACK)), - ('md', POINTER(EVP_MD)), - ('md_enc', c_int), - ('md_len', c_int), - ('md_data', STRING), - ('dec', POINTER(EVP_CIPHER)), - ('key_len', c_int), - ('key', POINTER(c_ubyte)), - ('data_enc', c_int), - ('data_len', c_int), - ('data', POINTER(c_ubyte)), -] -assert sizeof(pem_ctx_st) == 76, sizeof(pem_ctx_st) -assert alignment(pem_ctx_st) == 4, alignment(pem_ctx_st) -PEM_CTX = pem_ctx_st -pem_password_cb = CFUNCTYPE(c_int, STRING, c_int, c_int, c_void_p) -class pkcs7_issuer_and_serial_st(Structure): - pass -pkcs7_issuer_and_serial_st._fields_ = [ - ('issuer', POINTER(X509_NAME)), - ('serial', POINTER(ASN1_INTEGER)), -] -assert sizeof(pkcs7_issuer_and_serial_st) == 8, sizeof(pkcs7_issuer_and_serial_st) -assert alignment(pkcs7_issuer_and_serial_st) == 4, alignment(pkcs7_issuer_and_serial_st) -PKCS7_ISSUER_AND_SERIAL = pkcs7_issuer_and_serial_st -class pkcs7_signer_info_st(Structure): - pass -pkcs7_signer_info_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('issuer_and_serial', POINTER(PKCS7_ISSUER_AND_SERIAL)), - ('digest_alg', POINTER(X509_ALGOR)), - ('auth_attr', POINTER(STACK)), - ('digest_enc_alg', POINTER(X509_ALGOR)), - ('enc_digest', POINTER(ASN1_OCTET_STRING)), - ('unauth_attr', POINTER(STACK)), - ('pkey', POINTER(EVP_PKEY)), -] -assert sizeof(pkcs7_signer_info_st) == 32, sizeof(pkcs7_signer_info_st) -assert alignment(pkcs7_signer_info_st) == 4, alignment(pkcs7_signer_info_st) -PKCS7_SIGNER_INFO = pkcs7_signer_info_st -class pkcs7_recip_info_st(Structure): - pass -pkcs7_recip_info_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('issuer_and_serial', POINTER(PKCS7_ISSUER_AND_SERIAL)), - ('key_enc_algor', POINTER(X509_ALGOR)), - ('enc_key', POINTER(ASN1_OCTET_STRING)), - ('cert', POINTER(X509)), -] -assert sizeof(pkcs7_recip_info_st) == 20, sizeof(pkcs7_recip_info_st) -assert alignment(pkcs7_recip_info_st) == 4, alignment(pkcs7_recip_info_st) -PKCS7_RECIP_INFO = pkcs7_recip_info_st -class pkcs7_signed_st(Structure): - pass -class pkcs7_st(Structure): - pass -pkcs7_signed_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('md_algs', POINTER(STACK)), - ('cert', POINTER(STACK)), - ('crl', POINTER(STACK)), - ('signer_info', POINTER(STACK)), - ('contents', POINTER(pkcs7_st)), -] -assert sizeof(pkcs7_signed_st) == 24, sizeof(pkcs7_signed_st) -assert alignment(pkcs7_signed_st) == 4, alignment(pkcs7_signed_st) -PKCS7_SIGNED = pkcs7_signed_st -class pkcs7_enc_content_st(Structure): - pass -pkcs7_enc_content_st._fields_ = [ - ('content_type', POINTER(ASN1_OBJECT)), - ('algorithm', POINTER(X509_ALGOR)), - ('enc_data', POINTER(ASN1_OCTET_STRING)), - ('cipher', POINTER(EVP_CIPHER)), -] -assert sizeof(pkcs7_enc_content_st) == 16, sizeof(pkcs7_enc_content_st) -assert alignment(pkcs7_enc_content_st) == 4, alignment(pkcs7_enc_content_st) -PKCS7_ENC_CONTENT = pkcs7_enc_content_st -class pkcs7_enveloped_st(Structure): - pass -pkcs7_enveloped_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('recipientinfo', POINTER(STACK)), - ('enc_data', POINTER(PKCS7_ENC_CONTENT)), -] -assert sizeof(pkcs7_enveloped_st) == 12, sizeof(pkcs7_enveloped_st) -assert alignment(pkcs7_enveloped_st) == 4, alignment(pkcs7_enveloped_st) -PKCS7_ENVELOPE = pkcs7_enveloped_st -class pkcs7_signedandenveloped_st(Structure): - pass -pkcs7_signedandenveloped_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('md_algs', POINTER(STACK)), - ('cert', POINTER(STACK)), - ('crl', POINTER(STACK)), - ('signer_info', POINTER(STACK)), - ('enc_data', POINTER(PKCS7_ENC_CONTENT)), - ('recipientinfo', POINTER(STACK)), -] -assert sizeof(pkcs7_signedandenveloped_st) == 28, sizeof(pkcs7_signedandenveloped_st) -assert alignment(pkcs7_signedandenveloped_st) == 4, alignment(pkcs7_signedandenveloped_st) -PKCS7_SIGN_ENVELOPE = pkcs7_signedandenveloped_st -class pkcs7_digest_st(Structure): - pass -pkcs7_digest_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('md', POINTER(X509_ALGOR)), - ('contents', POINTER(pkcs7_st)), - ('digest', POINTER(ASN1_OCTET_STRING)), -] -assert sizeof(pkcs7_digest_st) == 16, sizeof(pkcs7_digest_st) -assert alignment(pkcs7_digest_st) == 4, alignment(pkcs7_digest_st) -PKCS7_DIGEST = pkcs7_digest_st -class pkcs7_encrypted_st(Structure): - pass -pkcs7_encrypted_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('enc_data', POINTER(PKCS7_ENC_CONTENT)), -] -assert sizeof(pkcs7_encrypted_st) == 8, sizeof(pkcs7_encrypted_st) -assert alignment(pkcs7_encrypted_st) == 4, alignment(pkcs7_encrypted_st) -PKCS7_ENCRYPT = pkcs7_encrypted_st -class N8pkcs7_st4DOLLAR_15E(Union): - pass -N8pkcs7_st4DOLLAR_15E._fields_ = [ - ('ptr', STRING), - ('data', POINTER(ASN1_OCTET_STRING)), - ('sign', POINTER(PKCS7_SIGNED)), - ('enveloped', POINTER(PKCS7_ENVELOPE)), - ('signed_and_enveloped', POINTER(PKCS7_SIGN_ENVELOPE)), - ('digest', POINTER(PKCS7_DIGEST)), - ('encrypted', POINTER(PKCS7_ENCRYPT)), - ('other', POINTER(ASN1_TYPE)), -] -assert sizeof(N8pkcs7_st4DOLLAR_15E) == 4, sizeof(N8pkcs7_st4DOLLAR_15E) -assert alignment(N8pkcs7_st4DOLLAR_15E) == 4, alignment(N8pkcs7_st4DOLLAR_15E) -pkcs7_st._fields_ = [ - ('asn1', POINTER(c_ubyte)), - ('length', c_long), - ('state', c_int), - ('detached', c_int), - ('type', POINTER(ASN1_OBJECT)), - ('d', N8pkcs7_st4DOLLAR_15E), -] -assert sizeof(pkcs7_st) == 24, sizeof(pkcs7_st) -assert alignment(pkcs7_st) == 4, alignment(pkcs7_st) -PKCS7 = pkcs7_st -class rc2_key_st(Structure): - pass -rc2_key_st._fields_ = [ - ('data', c_uint * 64), -] -assert sizeof(rc2_key_st) == 256, sizeof(rc2_key_st) -assert alignment(rc2_key_st) == 4, alignment(rc2_key_st) -RC2_KEY = rc2_key_st -class rc4_key_st(Structure): - pass -rc4_key_st._fields_ = [ - ('x', c_ubyte), - ('y', c_ubyte), - ('data', c_ubyte * 256), -] -assert sizeof(rc4_key_st) == 258, sizeof(rc4_key_st) -assert alignment(rc4_key_st) == 1, alignment(rc4_key_st) -RC4_KEY = rc4_key_st -class rc5_key_st(Structure): - pass -rc5_key_st._fields_ = [ - ('rounds', c_int), - ('data', c_ulong * 34), -] -assert sizeof(rc5_key_st) == 140, sizeof(rc5_key_st) -assert alignment(rc5_key_st) == 4, alignment(rc5_key_st) -RC5_32_KEY = rc5_key_st -class RIPEMD160state_st(Structure): - pass -RIPEMD160state_st._fields_ = [ - ('A', c_uint), - ('B', c_uint), - ('C', c_uint), - ('D', c_uint), - ('E', c_uint), - ('Nl', c_uint), - ('Nh', c_uint), - ('data', c_uint * 16), - ('num', c_int), -] -assert sizeof(RIPEMD160state_st) == 96, sizeof(RIPEMD160state_st) -assert alignment(RIPEMD160state_st) == 4, alignment(RIPEMD160state_st) -RIPEMD160_CTX = RIPEMD160state_st -RSA = rsa_st -class rsa_meth_st(Structure): - pass -rsa_meth_st._fields_ = [ - ('name', STRING), - ('rsa_pub_enc', CFUNCTYPE(c_int, c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)), - ('rsa_pub_dec', CFUNCTYPE(c_int, c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)), - ('rsa_priv_enc', CFUNCTYPE(c_int, c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)), - ('rsa_priv_dec', CFUNCTYPE(c_int, c_int, POINTER(c_ubyte), POINTER(c_ubyte), POINTER(RSA), c_int)), - ('rsa_mod_exp', CFUNCTYPE(c_int, POINTER(BIGNUM), POINTER(BIGNUM), POINTER(RSA))), - ('bn_mod_exp', CFUNCTYPE(c_int, POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BIGNUM), POINTER(BN_CTX), POINTER(BN_MONT_CTX))), - ('init', CFUNCTYPE(c_int, POINTER(RSA))), - ('finish', CFUNCTYPE(c_int, POINTER(RSA))), - ('flags', c_int), - ('app_data', STRING), - ('rsa_sign', CFUNCTYPE(c_int, c_int, POINTER(c_ubyte), c_uint, POINTER(c_ubyte), POINTER(c_uint), POINTER(RSA))), - ('rsa_verify', CFUNCTYPE(c_int, c_int, POINTER(c_ubyte), c_uint, POINTER(c_ubyte), c_uint, POINTER(RSA))), -] -assert sizeof(rsa_meth_st) == 52, sizeof(rsa_meth_st) -assert alignment(rsa_meth_st) == 4, alignment(rsa_meth_st) -RSA_METHOD = rsa_meth_st -rsa_st._fields_ = [ - ('pad', c_int), - ('version', c_long), - ('meth', POINTER(RSA_METHOD)), - ('engine', POINTER(ENGINE)), - ('n', POINTER(BIGNUM)), - ('e', POINTER(BIGNUM)), - ('d', POINTER(BIGNUM)), - ('p', POINTER(BIGNUM)), - ('q', POINTER(BIGNUM)), - ('dmp1', POINTER(BIGNUM)), - ('dmq1', POINTER(BIGNUM)), - ('iqmp', POINTER(BIGNUM)), - ('ex_data', CRYPTO_EX_DATA), - ('references', c_int), - ('flags', c_int), - ('_method_mod_n', POINTER(BN_MONT_CTX)), - ('_method_mod_p', POINTER(BN_MONT_CTX)), - ('_method_mod_q', POINTER(BN_MONT_CTX)), - ('bignum_data', STRING), - ('blinding', POINTER(BN_BLINDING)), -] -assert sizeof(rsa_st) == 84, sizeof(rsa_st) -assert alignment(rsa_st) == 4, alignment(rsa_st) -openssl_fptr = CFUNCTYPE(None) -class SHAstate_st(Structure): - pass -SHAstate_st._fields_ = [ - ('h0', c_uint), - ('h1', c_uint), - ('h2', c_uint), - ('h3', c_uint), - ('h4', c_uint), - ('Nl', c_uint), - ('Nh', c_uint), - ('data', c_uint * 16), - ('num', c_int), -] -assert sizeof(SHAstate_st) == 96, sizeof(SHAstate_st) -assert alignment(SHAstate_st) == 4, alignment(SHAstate_st) -SHA_CTX = SHAstate_st -class ssl_st(Structure): - pass -ssl_crock_st = POINTER(ssl_st) -class ssl_cipher_st(Structure): - pass -ssl_cipher_st._fields_ = [ - ('valid', c_int), - ('name', STRING), - ('id', c_ulong), - ('algorithms', c_ulong), - ('algo_strength', c_ulong), - ('algorithm2', c_ulong), - ('strength_bits', c_int), - ('alg_bits', c_int), - ('mask', c_ulong), - ('mask_strength', c_ulong), -] -assert sizeof(ssl_cipher_st) == 40, sizeof(ssl_cipher_st) -assert alignment(ssl_cipher_st) == 4, alignment(ssl_cipher_st) -SSL_CIPHER = ssl_cipher_st -SSL = ssl_st -class ssl_ctx_st(Structure): - pass -SSL_CTX = ssl_ctx_st -class ssl_method_st(Structure): - pass -class ssl3_enc_method(Structure): - pass -ssl_method_st._fields_ = [ - ('version', c_int), - ('ssl_new', CFUNCTYPE(c_int, POINTER(SSL))), - ('ssl_clear', CFUNCTYPE(None, POINTER(SSL))), - ('ssl_free', CFUNCTYPE(None, POINTER(SSL))), - ('ssl_accept', CFUNCTYPE(c_int, POINTER(SSL))), - ('ssl_connect', CFUNCTYPE(c_int, POINTER(SSL))), - ('ssl_read', CFUNCTYPE(c_int, POINTER(SSL), c_void_p, c_int)), - ('ssl_peek', CFUNCTYPE(c_int, POINTER(SSL), c_void_p, c_int)), - ('ssl_write', CFUNCTYPE(c_int, POINTER(SSL), c_void_p, c_int)), - ('ssl_shutdown', CFUNCTYPE(c_int, POINTER(SSL))), - ('ssl_renegotiate', CFUNCTYPE(c_int, POINTER(SSL))), - ('ssl_renegotiate_check', CFUNCTYPE(c_int, POINTER(SSL))), - ('ssl_ctrl', CFUNCTYPE(c_long, POINTER(SSL), c_int, c_long, c_void_p)), - ('ssl_ctx_ctrl', CFUNCTYPE(c_long, POINTER(SSL_CTX), c_int, c_long, c_void_p)), - ('get_cipher_by_char', CFUNCTYPE(POINTER(SSL_CIPHER), POINTER(c_ubyte))), - ('put_cipher_by_char', CFUNCTYPE(c_int, POINTER(SSL_CIPHER), POINTER(c_ubyte))), - ('ssl_pending', CFUNCTYPE(c_int, POINTER(SSL))), - ('num_ciphers', CFUNCTYPE(c_int)), - ('get_cipher', CFUNCTYPE(POINTER(SSL_CIPHER), c_uint)), - ('get_ssl_method', CFUNCTYPE(POINTER(ssl_method_st), c_int)), - ('get_timeout', CFUNCTYPE(c_long)), - ('ssl3_enc', POINTER(ssl3_enc_method)), - ('ssl_version', CFUNCTYPE(c_int)), - ('ssl_callback_ctrl', CFUNCTYPE(c_long, POINTER(SSL), c_int, CFUNCTYPE(None))), - ('ssl_ctx_callback_ctrl', CFUNCTYPE(c_long, POINTER(SSL_CTX), c_int, CFUNCTYPE(None))), -] -assert sizeof(ssl_method_st) == 100, sizeof(ssl_method_st) -assert alignment(ssl_method_st) == 4, alignment(ssl_method_st) -ssl3_enc_method._fields_ = [ -] -SSL_METHOD = ssl_method_st -class ssl_session_st(Structure): - pass -class sess_cert_st(Structure): - pass -ssl_session_st._fields_ = [ - ('ssl_version', c_int), - ('key_arg_length', c_uint), - ('key_arg', c_ubyte * 8), - ('master_key_length', c_int), - ('master_key', c_ubyte * 48), - ('session_id_length', c_uint), - ('session_id', c_ubyte * 32), - ('sid_ctx_length', c_uint), - ('sid_ctx', c_ubyte * 32), - ('not_resumable', c_int), - ('sess_cert', POINTER(sess_cert_st)), - ('peer', POINTER(X509)), - ('verify_result', c_long), - ('references', c_int), - ('timeout', c_long), - ('time', c_long), - ('compress_meth', c_int), - ('cipher', POINTER(SSL_CIPHER)), - ('cipher_id', c_ulong), - ('ciphers', POINTER(STACK)), - ('ex_data', CRYPTO_EX_DATA), - ('prev', POINTER(ssl_session_st)), - ('next', POINTER(ssl_session_st)), -] -assert sizeof(ssl_session_st) == 200, sizeof(ssl_session_st) -assert alignment(ssl_session_st) == 4, alignment(ssl_session_st) -sess_cert_st._fields_ = [ -] -SSL_SESSION = ssl_session_st -GEN_SESSION_CB = CFUNCTYPE(c_int, POINTER(SSL), POINTER(c_ubyte), POINTER(c_uint)) -class ssl_comp_st(Structure): - pass -ssl_comp_st._fields_ = [ - ('id', c_int), - ('name', STRING), - ('method', POINTER(COMP_METHOD)), -] -assert sizeof(ssl_comp_st) == 12, sizeof(ssl_comp_st) -assert alignment(ssl_comp_st) == 4, alignment(ssl_comp_st) -SSL_COMP = ssl_comp_st -class N10ssl_ctx_st4DOLLAR_18E(Structure): - pass -N10ssl_ctx_st4DOLLAR_18E._fields_ = [ - ('sess_connect', c_int), - ('sess_connect_renegotiate', c_int), - ('sess_connect_good', c_int), - ('sess_accept', c_int), - ('sess_accept_renegotiate', c_int), - ('sess_accept_good', c_int), - ('sess_miss', c_int), - ('sess_timeout', c_int), - ('sess_cache_full', c_int), - ('sess_hit', c_int), - ('sess_cb_hit', c_int), -] -assert sizeof(N10ssl_ctx_st4DOLLAR_18E) == 44, sizeof(N10ssl_ctx_st4DOLLAR_18E) -assert alignment(N10ssl_ctx_st4DOLLAR_18E) == 4, alignment(N10ssl_ctx_st4DOLLAR_18E) -class cert_st(Structure): - pass -ssl_ctx_st._fields_ = [ - ('method', POINTER(SSL_METHOD)), - ('cipher_list', POINTER(STACK)), - ('cipher_list_by_id', POINTER(STACK)), - ('cert_store', POINTER(x509_store_st)), - ('sessions', POINTER(lhash_st)), - ('session_cache_size', c_ulong), - ('session_cache_head', POINTER(ssl_session_st)), - ('session_cache_tail', POINTER(ssl_session_st)), - ('session_cache_mode', c_int), - ('session_timeout', c_long), - ('new_session_cb', CFUNCTYPE(c_int, POINTER(ssl_st), POINTER(SSL_SESSION))), - ('remove_session_cb', CFUNCTYPE(None, POINTER(ssl_ctx_st), POINTER(SSL_SESSION))), - ('get_session_cb', CFUNCTYPE(POINTER(SSL_SESSION), POINTER(ssl_st), POINTER(c_ubyte), c_int, POINTER(c_int))), - ('stats', N10ssl_ctx_st4DOLLAR_18E), - ('references', c_int), - ('app_verify_callback', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), c_void_p)), - ('app_verify_arg', c_void_p), - ('default_passwd_callback', POINTER(pem_password_cb)), - ('default_passwd_callback_userdata', c_void_p), - ('client_cert_cb', CFUNCTYPE(c_int, POINTER(SSL), POINTER(POINTER(X509)), POINTER(POINTER(EVP_PKEY)))), - ('ex_data', CRYPTO_EX_DATA), - ('rsa_md5', POINTER(EVP_MD)), - ('md5', POINTER(EVP_MD)), - ('sha1', POINTER(EVP_MD)), - ('extra_certs', POINTER(STACK)), - ('comp_methods', POINTER(STACK)), - ('info_callback', CFUNCTYPE(None, POINTER(SSL), c_int, c_int)), - ('client_CA', POINTER(STACK)), - ('options', c_ulong), - ('mode', c_ulong), - ('max_cert_list', c_long), - ('cert', POINTER(cert_st)), - ('read_ahead', c_int), - ('msg_callback', CFUNCTYPE(None, c_int, c_int, c_int, c_void_p, c_ulong, POINTER(SSL), c_void_p)), - ('msg_callback_arg', c_void_p), - ('verify_mode', c_int), - ('verify_depth', c_int), - ('sid_ctx_length', c_uint), - ('sid_ctx', c_ubyte * 32), - ('default_verify_callback', CFUNCTYPE(c_int, c_int, POINTER(X509_STORE_CTX))), - ('generate_session_id', GEN_SESSION_CB), - ('purpose', c_int), - ('trust', c_int), - ('quiet_shutdown', c_int), -] -assert sizeof(ssl_ctx_st) == 248, sizeof(ssl_ctx_st) -assert alignment(ssl_ctx_st) == 4, alignment(ssl_ctx_st) -cert_st._fields_ = [ -] -class ssl2_state_st(Structure): - pass -class ssl3_state_st(Structure): - pass -ssl_st._fields_ = [ - ('version', c_int), - ('type', c_int), - ('method', POINTER(SSL_METHOD)), - ('rbio', POINTER(BIO)), - ('wbio', POINTER(BIO)), - ('bbio', POINTER(BIO)), - ('rwstate', c_int), - ('in_handshake', c_int), - ('handshake_func', CFUNCTYPE(c_int)), - ('server', c_int), - ('new_session', c_int), - ('quiet_shutdown', c_int), - ('shutdown', c_int), - ('state', c_int), - ('rstate', c_int), - ('init_buf', POINTER(BUF_MEM)), - ('init_msg', c_void_p), - ('init_num', c_int), - ('init_off', c_int), - ('packet', POINTER(c_ubyte)), - ('packet_length', c_uint), - ('s2', POINTER(ssl2_state_st)), - ('s3', POINTER(ssl3_state_st)), - ('read_ahead', c_int), - ('msg_callback', CFUNCTYPE(None, c_int, c_int, c_int, c_void_p, c_ulong, POINTER(SSL), c_void_p)), - ('msg_callback_arg', c_void_p), - ('hit', c_int), - ('purpose', c_int), - ('trust', c_int), - ('cipher_list', POINTER(STACK)), - ('cipher_list_by_id', POINTER(STACK)), - ('enc_read_ctx', POINTER(EVP_CIPHER_CTX)), - ('read_hash', POINTER(EVP_MD)), - ('expand', POINTER(COMP_CTX)), - ('enc_write_ctx', POINTER(EVP_CIPHER_CTX)), - ('write_hash', POINTER(EVP_MD)), - ('compress', POINTER(COMP_CTX)), - ('cert', POINTER(cert_st)), - ('sid_ctx_length', c_uint), - ('sid_ctx', c_ubyte * 32), - ('session', POINTER(SSL_SESSION)), - ('generate_session_id', GEN_SESSION_CB), - ('verify_mode', c_int), - ('verify_depth', c_int), - ('verify_callback', CFUNCTYPE(c_int, c_int, POINTER(X509_STORE_CTX))), - ('info_callback', CFUNCTYPE(None, POINTER(SSL), c_int, c_int)), - ('error', c_int), - ('error_code', c_int), - ('ctx', POINTER(SSL_CTX)), - ('debug', c_int), - ('verify_result', c_long), - ('ex_data', CRYPTO_EX_DATA), - ('client_CA', POINTER(STACK)), - ('references', c_int), - ('options', c_ulong), - ('mode', c_ulong), - ('max_cert_list', c_long), - ('first_packet', c_int), - ('client_version', c_int), -] -assert sizeof(ssl_st) == 268, sizeof(ssl_st) -assert alignment(ssl_st) == 4, alignment(ssl_st) -class N13ssl2_state_st4DOLLAR_19E(Structure): - pass -N13ssl2_state_st4DOLLAR_19E._fields_ = [ - ('conn_id_length', c_uint), - ('cert_type', c_uint), - ('cert_length', c_uint), - ('csl', c_uint), - ('clear', c_uint), - ('enc', c_uint), - ('ccl', c_ubyte * 32), - ('cipher_spec_length', c_uint), - ('session_id_length', c_uint), - ('clen', c_uint), - ('rlen', c_uint), -] -assert sizeof(N13ssl2_state_st4DOLLAR_19E) == 72, sizeof(N13ssl2_state_st4DOLLAR_19E) -assert alignment(N13ssl2_state_st4DOLLAR_19E) == 4, alignment(N13ssl2_state_st4DOLLAR_19E) -ssl2_state_st._fields_ = [ - ('three_byte_header', c_int), - ('clear_text', c_int), - ('escape', c_int), - ('ssl2_rollback', c_int), - ('wnum', c_uint), - ('wpend_tot', c_int), - ('wpend_buf', POINTER(c_ubyte)), - ('wpend_off', c_int), - ('wpend_len', c_int), - ('wpend_ret', c_int), - ('rbuf_left', c_int), - ('rbuf_offs', c_int), - ('rbuf', POINTER(c_ubyte)), - ('wbuf', POINTER(c_ubyte)), - ('write_ptr', POINTER(c_ubyte)), - ('padding', c_uint), - ('rlength', c_uint), - ('ract_data_length', c_int), - ('wlength', c_uint), - ('wact_data_length', c_int), - ('ract_data', POINTER(c_ubyte)), - ('wact_data', POINTER(c_ubyte)), - ('mac_data', POINTER(c_ubyte)), - ('read_key', POINTER(c_ubyte)), - ('write_key', POINTER(c_ubyte)), - ('challenge_length', c_uint), - ('challenge', c_ubyte * 32), - ('conn_id_length', c_uint), - ('conn_id', c_ubyte * 16), - ('key_material_length', c_uint), - ('key_material', c_ubyte * 48), - ('read_sequence', c_ulong), - ('write_sequence', c_ulong), - ('tmp', N13ssl2_state_st4DOLLAR_19E), -] -assert sizeof(ssl2_state_st) == 288, sizeof(ssl2_state_st) -assert alignment(ssl2_state_st) == 4, alignment(ssl2_state_st) -SSL2_STATE = ssl2_state_st -class ssl3_record_st(Structure): - pass -ssl3_record_st._fields_ = [ - ('type', c_int), - ('length', c_uint), - ('off', c_uint), - ('data', POINTER(c_ubyte)), - ('input', POINTER(c_ubyte)), - ('comp', POINTER(c_ubyte)), -] -assert sizeof(ssl3_record_st) == 24, sizeof(ssl3_record_st) -assert alignment(ssl3_record_st) == 4, alignment(ssl3_record_st) -SSL3_RECORD = ssl3_record_st -class ssl3_buffer_st(Structure): - pass -size_t = __darwin_size_t -ssl3_buffer_st._fields_ = [ - ('buf', POINTER(c_ubyte)), - ('len', size_t), - ('offset', c_int), - ('left', c_int), -] -assert sizeof(ssl3_buffer_st) == 16, sizeof(ssl3_buffer_st) -assert alignment(ssl3_buffer_st) == 4, alignment(ssl3_buffer_st) -SSL3_BUFFER = ssl3_buffer_st -class N13ssl3_state_st4DOLLAR_20E(Structure): - pass -N13ssl3_state_st4DOLLAR_20E._fields_ = [ - ('cert_verify_md', c_ubyte * 72), - ('finish_md', c_ubyte * 72), - ('finish_md_len', c_int), - ('peer_finish_md', c_ubyte * 72), - ('peer_finish_md_len', c_int), - ('message_size', c_ulong), - ('message_type', c_int), - ('new_cipher', POINTER(SSL_CIPHER)), - ('dh', POINTER(DH)), - ('next_state', c_int), - ('reuse_message', c_int), - ('cert_req', c_int), - ('ctype_num', c_int), - ('ctype', c_char * 7), - ('ca_names', POINTER(STACK)), - ('use_rsa_tmp', c_int), - ('key_block_length', c_int), - ('key_block', POINTER(c_ubyte)), - ('new_sym_enc', POINTER(EVP_CIPHER)), - ('new_hash', POINTER(EVP_MD)), - ('new_compression', POINTER(SSL_COMP)), - ('cert_request', c_int), -] -assert sizeof(N13ssl3_state_st4DOLLAR_20E) == 296, sizeof(N13ssl3_state_st4DOLLAR_20E) -assert alignment(N13ssl3_state_st4DOLLAR_20E) == 4, alignment(N13ssl3_state_st4DOLLAR_20E) -ssl3_state_st._fields_ = [ - ('flags', c_long), - ('delay_buf_pop_ret', c_int), - ('read_sequence', c_ubyte * 8), - ('read_mac_secret', c_ubyte * 36), - ('write_sequence', c_ubyte * 8), - ('write_mac_secret', c_ubyte * 36), - ('server_random', c_ubyte * 32), - ('client_random', c_ubyte * 32), - ('need_empty_fragments', c_int), - ('empty_fragment_done', c_int), - ('rbuf', SSL3_BUFFER), - ('wbuf', SSL3_BUFFER), - ('rrec', SSL3_RECORD), - ('wrec', SSL3_RECORD), - ('alert_fragment', c_ubyte * 2), - ('alert_fragment_len', c_uint), - ('handshake_fragment', c_ubyte * 4), - ('handshake_fragment_len', c_uint), - ('wnum', c_uint), - ('wpend_tot', c_int), - ('wpend_type', c_int), - ('wpend_ret', c_int), - ('wpend_buf', POINTER(c_ubyte)), - ('finish_dgst1', EVP_MD_CTX), - ('finish_dgst2', EVP_MD_CTX), - ('change_cipher_spec', c_int), - ('warn_alert', c_int), - ('fatal_alert', c_int), - ('alert_dispatch', c_int), - ('send_alert', c_ubyte * 2), - ('renegotiate', c_int), - ('total_renegotiations', c_int), - ('num_renegotiations', c_int), - ('in_read_app_data', c_int), - ('tmp', N13ssl3_state_st4DOLLAR_20E), -] -assert sizeof(ssl3_state_st) == 648, sizeof(ssl3_state_st) -assert alignment(ssl3_state_st) == 4, alignment(ssl3_state_st) -SSL3_STATE = ssl3_state_st -stack_st._fields_ = [ - ('num', c_int), - ('data', POINTER(STRING)), - ('sorted', c_int), - ('num_alloc', c_int), - ('comp', CFUNCTYPE(c_int, POINTER(STRING), POINTER(STRING))), -] -assert sizeof(stack_st) == 20, sizeof(stack_st) -assert alignment(stack_st) == 4, alignment(stack_st) -class ui_st(Structure): - pass -ui_st._fields_ = [ -] -UI = ui_st -class ui_method_st(Structure): - pass -ui_method_st._fields_ = [ -] -UI_METHOD = ui_method_st -class ui_string_st(Structure): - pass -ui_string_st._fields_ = [ -] -UI_STRING = ui_string_st - -# values for enumeration 'UI_string_types' -UI_string_types = c_int # enum -class X509_objects_st(Structure): - pass -X509_objects_st._fields_ = [ - ('nid', c_int), - ('a2i', CFUNCTYPE(c_int)), - ('i2a', CFUNCTYPE(c_int)), -] -assert sizeof(X509_objects_st) == 12, sizeof(X509_objects_st) -assert alignment(X509_objects_st) == 4, alignment(X509_objects_st) -X509_OBJECTS = X509_objects_st -X509_algor_st._fields_ = [ - ('algorithm', POINTER(ASN1_OBJECT)), - ('parameter', POINTER(ASN1_TYPE)), -] -assert sizeof(X509_algor_st) == 8, sizeof(X509_algor_st) -assert alignment(X509_algor_st) == 4, alignment(X509_algor_st) -class X509_val_st(Structure): - pass -X509_val_st._fields_ = [ - ('notBefore', POINTER(ASN1_TIME)), - ('notAfter', POINTER(ASN1_TIME)), -] -assert sizeof(X509_val_st) == 8, sizeof(X509_val_st) -assert alignment(X509_val_st) == 4, alignment(X509_val_st) -X509_VAL = X509_val_st -class X509_pubkey_st(Structure): - pass -X509_pubkey_st._fields_ = [ - ('algor', POINTER(X509_ALGOR)), - ('public_key', POINTER(ASN1_BIT_STRING)), - ('pkey', POINTER(EVP_PKEY)), -] -assert sizeof(X509_pubkey_st) == 12, sizeof(X509_pubkey_st) -assert alignment(X509_pubkey_st) == 4, alignment(X509_pubkey_st) -X509_PUBKEY = X509_pubkey_st -class X509_sig_st(Structure): - pass -X509_sig_st._fields_ = [ - ('algor', POINTER(X509_ALGOR)), - ('digest', POINTER(ASN1_OCTET_STRING)), -] -assert sizeof(X509_sig_st) == 8, sizeof(X509_sig_st) -assert alignment(X509_sig_st) == 4, alignment(X509_sig_st) -X509_SIG = X509_sig_st -class X509_name_entry_st(Structure): - pass -X509_name_entry_st._fields_ = [ - ('object', POINTER(ASN1_OBJECT)), - ('value', POINTER(ASN1_STRING)), - ('set', c_int), - ('size', c_int), -] -assert sizeof(X509_name_entry_st) == 16, sizeof(X509_name_entry_st) -assert alignment(X509_name_entry_st) == 4, alignment(X509_name_entry_st) -X509_NAME_ENTRY = X509_name_entry_st -X509_name_st._fields_ = [ - ('entries', POINTER(STACK)), - ('modified', c_int), - ('bytes', POINTER(BUF_MEM)), - ('hash', c_ulong), -] -assert sizeof(X509_name_st) == 16, sizeof(X509_name_st) -assert alignment(X509_name_st) == 4, alignment(X509_name_st) -class X509_extension_st(Structure): - pass -X509_extension_st._fields_ = [ - ('object', POINTER(ASN1_OBJECT)), - ('critical', ASN1_BOOLEAN), - ('value', POINTER(ASN1_OCTET_STRING)), -] -assert sizeof(X509_extension_st) == 12, sizeof(X509_extension_st) -assert alignment(X509_extension_st) == 4, alignment(X509_extension_st) -X509_EXTENSION = X509_extension_st -class x509_attributes_st(Structure): - pass -class N18x509_attributes_st4DOLLAR_13E(Union): - pass -N18x509_attributes_st4DOLLAR_13E._fields_ = [ - ('ptr', STRING), - ('set', POINTER(STACK)), - ('single', POINTER(ASN1_TYPE)), -] -assert sizeof(N18x509_attributes_st4DOLLAR_13E) == 4, sizeof(N18x509_attributes_st4DOLLAR_13E) -assert alignment(N18x509_attributes_st4DOLLAR_13E) == 4, alignment(N18x509_attributes_st4DOLLAR_13E) -x509_attributes_st._fields_ = [ - ('object', POINTER(ASN1_OBJECT)), - ('single', c_int), - ('value', N18x509_attributes_st4DOLLAR_13E), -] -assert sizeof(x509_attributes_st) == 12, sizeof(x509_attributes_st) -assert alignment(x509_attributes_st) == 4, alignment(x509_attributes_st) -X509_ATTRIBUTE = x509_attributes_st -class X509_req_info_st(Structure): - pass -X509_req_info_st._fields_ = [ - ('enc', ASN1_ENCODING), - ('version', POINTER(ASN1_INTEGER)), - ('subject', POINTER(X509_NAME)), - ('pubkey', POINTER(X509_PUBKEY)), - ('attributes', POINTER(STACK)), -] -assert sizeof(X509_req_info_st) == 28, sizeof(X509_req_info_st) -assert alignment(X509_req_info_st) == 4, alignment(X509_req_info_st) -X509_REQ_INFO = X509_req_info_st -class X509_req_st(Structure): - pass -X509_req_st._fields_ = [ - ('req_info', POINTER(X509_REQ_INFO)), - ('sig_alg', POINTER(X509_ALGOR)), - ('signature', POINTER(ASN1_BIT_STRING)), - ('references', c_int), -] -assert sizeof(X509_req_st) == 16, sizeof(X509_req_st) -assert alignment(X509_req_st) == 4, alignment(X509_req_st) -X509_REQ = X509_req_st -class x509_cinf_st(Structure): - pass -x509_cinf_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('serialNumber', POINTER(ASN1_INTEGER)), - ('signature', POINTER(X509_ALGOR)), - ('issuer', POINTER(X509_NAME)), - ('validity', POINTER(X509_VAL)), - ('subject', POINTER(X509_NAME)), - ('key', POINTER(X509_PUBKEY)), - ('issuerUID', POINTER(ASN1_BIT_STRING)), - ('subjectUID', POINTER(ASN1_BIT_STRING)), - ('extensions', POINTER(STACK)), -] -assert sizeof(x509_cinf_st) == 40, sizeof(x509_cinf_st) -assert alignment(x509_cinf_st) == 4, alignment(x509_cinf_st) -X509_CINF = x509_cinf_st -class x509_cert_aux_st(Structure): - pass -x509_cert_aux_st._fields_ = [ - ('trust', POINTER(STACK)), - ('reject', POINTER(STACK)), - ('alias', POINTER(ASN1_UTF8STRING)), - ('keyid', POINTER(ASN1_OCTET_STRING)), - ('other', POINTER(STACK)), -] -assert sizeof(x509_cert_aux_st) == 20, sizeof(x509_cert_aux_st) -assert alignment(x509_cert_aux_st) == 4, alignment(x509_cert_aux_st) -X509_CERT_AUX = x509_cert_aux_st -class AUTHORITY_KEYID_st(Structure): - pass -x509_st._fields_ = [ - ('cert_info', POINTER(X509_CINF)), - ('sig_alg', POINTER(X509_ALGOR)), - ('signature', POINTER(ASN1_BIT_STRING)), - ('valid', c_int), - ('references', c_int), - ('name', STRING), - ('ex_data', CRYPTO_EX_DATA), - ('ex_pathlen', c_long), - ('ex_flags', c_ulong), - ('ex_kusage', c_ulong), - ('ex_xkusage', c_ulong), - ('ex_nscert', c_ulong), - ('skid', POINTER(ASN1_OCTET_STRING)), - ('akid', POINTER(AUTHORITY_KEYID_st)), - ('sha1_hash', c_ubyte * 20), - ('aux', POINTER(X509_CERT_AUX)), -] -assert sizeof(x509_st) == 84, sizeof(x509_st) -assert alignment(x509_st) == 4, alignment(x509_st) -AUTHORITY_KEYID_st._fields_ = [ -] -class x509_trust_st(Structure): - pass -x509_trust_st._fields_ = [ - ('trust', c_int), - ('flags', c_int), - ('check_trust', CFUNCTYPE(c_int, POINTER(x509_trust_st), POINTER(X509), c_int)), - ('name', STRING), - ('arg1', c_int), - ('arg2', c_void_p), -] -assert sizeof(x509_trust_st) == 24, sizeof(x509_trust_st) -assert alignment(x509_trust_st) == 4, alignment(x509_trust_st) -X509_TRUST = x509_trust_st -class X509_revoked_st(Structure): - pass -X509_revoked_st._fields_ = [ - ('serialNumber', POINTER(ASN1_INTEGER)), - ('revocationDate', POINTER(ASN1_TIME)), - ('extensions', POINTER(STACK)), - ('sequence', c_int), -] -assert sizeof(X509_revoked_st) == 16, sizeof(X509_revoked_st) -assert alignment(X509_revoked_st) == 4, alignment(X509_revoked_st) -X509_REVOKED = X509_revoked_st -class X509_crl_info_st(Structure): - pass -X509_crl_info_st._fields_ = [ - ('version', POINTER(ASN1_INTEGER)), - ('sig_alg', POINTER(X509_ALGOR)), - ('issuer', POINTER(X509_NAME)), - ('lastUpdate', POINTER(ASN1_TIME)), - ('nextUpdate', POINTER(ASN1_TIME)), - ('revoked', POINTER(STACK)), - ('extensions', POINTER(STACK)), - ('enc', ASN1_ENCODING), -] -assert sizeof(X509_crl_info_st) == 40, sizeof(X509_crl_info_st) -assert alignment(X509_crl_info_st) == 4, alignment(X509_crl_info_st) -X509_CRL_INFO = X509_crl_info_st -X509_crl_st._fields_ = [ - ('crl', POINTER(X509_CRL_INFO)), - ('sig_alg', POINTER(X509_ALGOR)), - ('signature', POINTER(ASN1_BIT_STRING)), - ('references', c_int), -] -assert sizeof(X509_crl_st) == 16, sizeof(X509_crl_st) -assert alignment(X509_crl_st) == 4, alignment(X509_crl_st) -class private_key_st(Structure): - pass -private_key_st._fields_ = [ - ('version', c_int), - ('enc_algor', POINTER(X509_ALGOR)), - ('enc_pkey', POINTER(ASN1_OCTET_STRING)), - ('dec_pkey', POINTER(EVP_PKEY)), - ('key_length', c_int), - ('key_data', STRING), - ('key_free', c_int), - ('cipher', EVP_CIPHER_INFO), - ('references', c_int), -] -assert sizeof(private_key_st) == 52, sizeof(private_key_st) -assert alignment(private_key_st) == 4, alignment(private_key_st) -X509_PKEY = private_key_st -class X509_info_st(Structure): - pass -X509_info_st._fields_ = [ - ('x509', POINTER(X509)), - ('crl', POINTER(X509_CRL)), - ('x_pkey', POINTER(X509_PKEY)), - ('enc_cipher', EVP_CIPHER_INFO), - ('enc_len', c_int), - ('enc_data', STRING), - ('references', c_int), -] -assert sizeof(X509_info_st) == 44, sizeof(X509_info_st) -assert alignment(X509_info_st) == 4, alignment(X509_info_st) -X509_INFO = X509_info_st -class Netscape_spkac_st(Structure): - pass -Netscape_spkac_st._fields_ = [ - ('pubkey', POINTER(X509_PUBKEY)), - ('challenge', POINTER(ASN1_IA5STRING)), -] -assert sizeof(Netscape_spkac_st) == 8, sizeof(Netscape_spkac_st) -assert alignment(Netscape_spkac_st) == 4, alignment(Netscape_spkac_st) -NETSCAPE_SPKAC = Netscape_spkac_st -class Netscape_spki_st(Structure): - pass -Netscape_spki_st._fields_ = [ - ('spkac', POINTER(NETSCAPE_SPKAC)), - ('sig_algor', POINTER(X509_ALGOR)), - ('signature', POINTER(ASN1_BIT_STRING)), -] -assert sizeof(Netscape_spki_st) == 12, sizeof(Netscape_spki_st) -assert alignment(Netscape_spki_st) == 4, alignment(Netscape_spki_st) -NETSCAPE_SPKI = Netscape_spki_st -class Netscape_certificate_sequence(Structure): - pass -Netscape_certificate_sequence._fields_ = [ - ('type', POINTER(ASN1_OBJECT)), - ('certs', POINTER(STACK)), -] -assert sizeof(Netscape_certificate_sequence) == 8, sizeof(Netscape_certificate_sequence) -assert alignment(Netscape_certificate_sequence) == 4, alignment(Netscape_certificate_sequence) -NETSCAPE_CERT_SEQUENCE = Netscape_certificate_sequence -class PBEPARAM_st(Structure): - pass -PBEPARAM_st._fields_ = [ - ('salt', POINTER(ASN1_OCTET_STRING)), - ('iter', POINTER(ASN1_INTEGER)), -] -assert sizeof(PBEPARAM_st) == 8, sizeof(PBEPARAM_st) -assert alignment(PBEPARAM_st) == 4, alignment(PBEPARAM_st) -PBEPARAM = PBEPARAM_st -class PBE2PARAM_st(Structure): - pass -PBE2PARAM_st._fields_ = [ - ('keyfunc', POINTER(X509_ALGOR)), - ('encryption', POINTER(X509_ALGOR)), -] -assert sizeof(PBE2PARAM_st) == 8, sizeof(PBE2PARAM_st) -assert alignment(PBE2PARAM_st) == 4, alignment(PBE2PARAM_st) -PBE2PARAM = PBE2PARAM_st -class PBKDF2PARAM_st(Structure): - pass -PBKDF2PARAM_st._fields_ = [ - ('salt', POINTER(ASN1_TYPE)), - ('iter', POINTER(ASN1_INTEGER)), - ('keylength', POINTER(ASN1_INTEGER)), - ('prf', POINTER(X509_ALGOR)), -] -assert sizeof(PBKDF2PARAM_st) == 16, sizeof(PBKDF2PARAM_st) -assert alignment(PBKDF2PARAM_st) == 4, alignment(PBKDF2PARAM_st) -PBKDF2PARAM = PBKDF2PARAM_st -class pkcs8_priv_key_info_st(Structure): - pass -pkcs8_priv_key_info_st._fields_ = [ - ('broken', c_int), - ('version', POINTER(ASN1_INTEGER)), - ('pkeyalg', POINTER(X509_ALGOR)), - ('pkey', POINTER(ASN1_TYPE)), - ('attributes', POINTER(STACK)), -] -assert sizeof(pkcs8_priv_key_info_st) == 20, sizeof(pkcs8_priv_key_info_st) -assert alignment(pkcs8_priv_key_info_st) == 4, alignment(pkcs8_priv_key_info_st) -PKCS8_PRIV_KEY_INFO = pkcs8_priv_key_info_st -class x509_hash_dir_st(Structure): - pass -x509_hash_dir_st._fields_ = [ - ('num_dirs', c_int), - ('dirs', POINTER(STRING)), - ('dirs_type', POINTER(c_int)), - ('num_dirs_alloced', c_int), -] -assert sizeof(x509_hash_dir_st) == 16, sizeof(x509_hash_dir_st) -assert alignment(x509_hash_dir_st) == 4, alignment(x509_hash_dir_st) -X509_HASH_DIR_CTX = x509_hash_dir_st -class x509_file_st(Structure): - pass -x509_file_st._fields_ = [ - ('num_paths', c_int), - ('num_alloced', c_int), - ('paths', POINTER(STRING)), - ('path_type', POINTER(c_int)), -] -assert sizeof(x509_file_st) == 16, sizeof(x509_file_st) -assert alignment(x509_file_st) == 4, alignment(x509_file_st) -X509_CERT_FILE_CTX = x509_file_st -class x509_object_st(Structure): - pass -class N14x509_object_st4DOLLAR_14E(Union): - pass -N14x509_object_st4DOLLAR_14E._fields_ = [ - ('ptr', STRING), - ('x509', POINTER(X509)), - ('crl', POINTER(X509_CRL)), - ('pkey', POINTER(EVP_PKEY)), -] -assert sizeof(N14x509_object_st4DOLLAR_14E) == 4, sizeof(N14x509_object_st4DOLLAR_14E) -assert alignment(N14x509_object_st4DOLLAR_14E) == 4, alignment(N14x509_object_st4DOLLAR_14E) -x509_object_st._fields_ = [ - ('type', c_int), - ('data', N14x509_object_st4DOLLAR_14E), -] -assert sizeof(x509_object_st) == 8, sizeof(x509_object_st) -assert alignment(x509_object_st) == 4, alignment(x509_object_st) -X509_OBJECT = x509_object_st -class x509_lookup_st(Structure): - pass -X509_LOOKUP = x509_lookup_st -class x509_lookup_method_st(Structure): - pass -x509_lookup_method_st._fields_ = [ - ('name', STRING), - ('new_item', CFUNCTYPE(c_int, POINTER(X509_LOOKUP))), - ('free', CFUNCTYPE(None, POINTER(X509_LOOKUP))), - ('init', CFUNCTYPE(c_int, POINTER(X509_LOOKUP))), - ('shutdown', CFUNCTYPE(c_int, POINTER(X509_LOOKUP))), - ('ctrl', CFUNCTYPE(c_int, POINTER(X509_LOOKUP), c_int, STRING, c_long, POINTER(STRING))), - ('get_by_subject', CFUNCTYPE(c_int, POINTER(X509_LOOKUP), c_int, POINTER(X509_NAME), POINTER(X509_OBJECT))), - ('get_by_issuer_serial', CFUNCTYPE(c_int, POINTER(X509_LOOKUP), c_int, POINTER(X509_NAME), POINTER(ASN1_INTEGER), POINTER(X509_OBJECT))), - ('get_by_fingerprint', CFUNCTYPE(c_int, POINTER(X509_LOOKUP), c_int, POINTER(c_ubyte), c_int, POINTER(X509_OBJECT))), - ('get_by_alias', CFUNCTYPE(c_int, POINTER(X509_LOOKUP), c_int, STRING, c_int, POINTER(X509_OBJECT))), -] -assert sizeof(x509_lookup_method_st) == 40, sizeof(x509_lookup_method_st) -assert alignment(x509_lookup_method_st) == 4, alignment(x509_lookup_method_st) -X509_LOOKUP_METHOD = x509_lookup_method_st -x509_store_st._fields_ = [ - ('cache', c_int), - ('objs', POINTER(STACK)), - ('get_cert_methods', POINTER(STACK)), - ('flags', c_ulong), - ('purpose', c_int), - ('trust', c_int), - ('verify', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX))), - ('verify_cb', CFUNCTYPE(c_int, c_int, POINTER(X509_STORE_CTX))), - ('get_issuer', CFUNCTYPE(c_int, POINTER(POINTER(X509)), POINTER(X509_STORE_CTX), POINTER(X509))), - ('check_issued', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(X509), POINTER(X509))), - ('check_revocation', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX))), - ('get_crl', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(POINTER(X509_CRL)), POINTER(X509))), - ('check_crl', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(X509_CRL))), - ('cert_crl', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(X509_CRL), POINTER(X509))), - ('cleanup', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX))), - ('ex_data', CRYPTO_EX_DATA), - ('references', c_int), - ('depth', c_int), -] -assert sizeof(x509_store_st) == 76, sizeof(x509_store_st) -assert alignment(x509_store_st) == 4, alignment(x509_store_st) -x509_lookup_st._fields_ = [ - ('init', c_int), - ('skip', c_int), - ('method', POINTER(X509_LOOKUP_METHOD)), - ('method_data', STRING), - ('store_ctx', POINTER(X509_STORE)), -] -assert sizeof(x509_lookup_st) == 20, sizeof(x509_lookup_st) -assert alignment(x509_lookup_st) == 4, alignment(x509_lookup_st) -time_t = __darwin_time_t -x509_store_ctx_st._fields_ = [ - ('ctx', POINTER(X509_STORE)), - ('current_method', c_int), - ('cert', POINTER(X509)), - ('untrusted', POINTER(STACK)), - ('purpose', c_int), - ('trust', c_int), - ('check_time', time_t), - ('flags', c_ulong), - ('other_ctx', c_void_p), - ('verify', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX))), - ('verify_cb', CFUNCTYPE(c_int, c_int, POINTER(X509_STORE_CTX))), - ('get_issuer', CFUNCTYPE(c_int, POINTER(POINTER(X509)), POINTER(X509_STORE_CTX), POINTER(X509))), - ('check_issued', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(X509), POINTER(X509))), - ('check_revocation', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX))), - ('get_crl', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(POINTER(X509_CRL)), POINTER(X509))), - ('check_crl', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(X509_CRL))), - ('cert_crl', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX), POINTER(X509_CRL), POINTER(X509))), - ('cleanup', CFUNCTYPE(c_int, POINTER(X509_STORE_CTX))), - ('depth', c_int), - ('valid', c_int), - ('last_untrusted', c_int), - ('chain', POINTER(STACK)), - ('error_depth', c_int), - ('error', c_int), - ('current_cert', POINTER(X509)), - ('current_issuer', POINTER(X509)), - ('current_crl', POINTER(X509_CRL)), - ('ex_data', CRYPTO_EX_DATA), -] -assert sizeof(x509_store_ctx_st) == 116, sizeof(x509_store_ctx_st) -assert alignment(x509_store_ctx_st) == 4, alignment(x509_store_ctx_st) -va_list = __darwin_va_list -__darwin_off_t = __int64_t -fpos_t = __darwin_off_t -class __sbuf(Structure): - pass -__sbuf._fields_ = [ - ('_base', POINTER(c_ubyte)), - ('_size', c_int), -] -assert sizeof(__sbuf) == 8, sizeof(__sbuf) -assert alignment(__sbuf) == 4, alignment(__sbuf) -class __sFILEX(Structure): - pass -__sFILEX._fields_ = [ -] -class __sFILE(Structure): - pass -__sFILE._pack_ = 4 -__sFILE._fields_ = [ - ('_p', POINTER(c_ubyte)), - ('_r', c_int), - ('_w', c_int), - ('_flags', c_short), - ('_file', c_short), - ('_bf', __sbuf), - ('_lbfsize', c_int), - ('_cookie', c_void_p), - ('_close', CFUNCTYPE(c_int, c_void_p)), - ('_read', CFUNCTYPE(c_int, c_void_p, STRING, c_int)), - ('_seek', CFUNCTYPE(fpos_t, c_void_p, c_longlong, c_int)), - ('_write', CFUNCTYPE(c_int, c_void_p, STRING, c_int)), - ('_ub', __sbuf), - ('_extra', POINTER(__sFILEX)), - ('_ur', c_int), - ('_ubuf', c_ubyte * 3), - ('_nbuf', c_ubyte * 1), - ('_lb', __sbuf), - ('_blksize', c_int), - ('_offset', fpos_t), -] -assert sizeof(__sFILE) == 88, sizeof(__sFILE) -assert alignment(__sFILE) == 4, alignment(__sFILE) -FILE = __sFILE -ct_rune_t = __darwin_ct_rune_t -rune_t = __darwin_rune_t -class div_t(Structure): - pass -div_t._fields_ = [ - ('quot', c_int), - ('rem', c_int), -] -assert sizeof(div_t) == 8, sizeof(div_t) -assert alignment(div_t) == 4, alignment(div_t) -class ldiv_t(Structure): - pass -ldiv_t._fields_ = [ - ('quot', c_long), - ('rem', c_long), -] -assert sizeof(ldiv_t) == 8, sizeof(ldiv_t) -assert alignment(ldiv_t) == 4, alignment(ldiv_t) -class lldiv_t(Structure): - pass -lldiv_t._pack_ = 4 -lldiv_t._fields_ = [ - ('quot', c_longlong), - ('rem', c_longlong), -] -assert sizeof(lldiv_t) == 16, sizeof(lldiv_t) -assert alignment(lldiv_t) == 4, alignment(lldiv_t) -__darwin_dev_t = __int32_t -dev_t = __darwin_dev_t -__darwin_mode_t = __uint16_t -mode_t = __darwin_mode_t -class mcontext(Structure): - pass -mcontext._fields_ = [ -] -class mcontext64(Structure): - pass -mcontext64._fields_ = [ -] -class __darwin_pthread_handler_rec(Structure): - pass -__darwin_pthread_handler_rec._fields_ = [ - ('__routine', CFUNCTYPE(None, c_void_p)), - ('__arg', c_void_p), - ('__next', POINTER(__darwin_pthread_handler_rec)), -] -assert sizeof(__darwin_pthread_handler_rec) == 12, sizeof(__darwin_pthread_handler_rec) -assert alignment(__darwin_pthread_handler_rec) == 4, alignment(__darwin_pthread_handler_rec) -class _opaque_pthread_attr_t(Structure): - pass -_opaque_pthread_attr_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 36), -] -assert sizeof(_opaque_pthread_attr_t) == 40, sizeof(_opaque_pthread_attr_t) -assert alignment(_opaque_pthread_attr_t) == 4, alignment(_opaque_pthread_attr_t) -class _opaque_pthread_cond_t(Structure): - pass -_opaque_pthread_cond_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 24), -] -assert sizeof(_opaque_pthread_cond_t) == 28, sizeof(_opaque_pthread_cond_t) -assert alignment(_opaque_pthread_cond_t) == 4, alignment(_opaque_pthread_cond_t) -class _opaque_pthread_condattr_t(Structure): - pass -_opaque_pthread_condattr_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 4), -] -assert sizeof(_opaque_pthread_condattr_t) == 8, sizeof(_opaque_pthread_condattr_t) -assert alignment(_opaque_pthread_condattr_t) == 4, alignment(_opaque_pthread_condattr_t) -class _opaque_pthread_mutex_t(Structure): - pass -_opaque_pthread_mutex_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 40), -] -assert sizeof(_opaque_pthread_mutex_t) == 44, sizeof(_opaque_pthread_mutex_t) -assert alignment(_opaque_pthread_mutex_t) == 4, alignment(_opaque_pthread_mutex_t) -class _opaque_pthread_mutexattr_t(Structure): - pass -_opaque_pthread_mutexattr_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 8), -] -assert sizeof(_opaque_pthread_mutexattr_t) == 12, sizeof(_opaque_pthread_mutexattr_t) -assert alignment(_opaque_pthread_mutexattr_t) == 4, alignment(_opaque_pthread_mutexattr_t) -class _opaque_pthread_once_t(Structure): - pass -_opaque_pthread_once_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 4), -] -assert sizeof(_opaque_pthread_once_t) == 8, sizeof(_opaque_pthread_once_t) -assert alignment(_opaque_pthread_once_t) == 4, alignment(_opaque_pthread_once_t) -class _opaque_pthread_rwlock_t(Structure): - pass -_opaque_pthread_rwlock_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 124), -] -assert sizeof(_opaque_pthread_rwlock_t) == 128, sizeof(_opaque_pthread_rwlock_t) -assert alignment(_opaque_pthread_rwlock_t) == 4, alignment(_opaque_pthread_rwlock_t) -class _opaque_pthread_rwlockattr_t(Structure): - pass -_opaque_pthread_rwlockattr_t._fields_ = [ - ('__sig', c_long), - ('__opaque', c_char * 12), -] -assert sizeof(_opaque_pthread_rwlockattr_t) == 16, sizeof(_opaque_pthread_rwlockattr_t) -assert alignment(_opaque_pthread_rwlockattr_t) == 4, alignment(_opaque_pthread_rwlockattr_t) -class _opaque_pthread_t(Structure): - pass -_opaque_pthread_t._fields_ = [ - ('__sig', c_long), - ('__cleanup_stack', POINTER(__darwin_pthread_handler_rec)), - ('__opaque', c_char * 596), -] -assert sizeof(_opaque_pthread_t) == 604, sizeof(_opaque_pthread_t) -assert alignment(_opaque_pthread_t) == 4, alignment(_opaque_pthread_t) -__darwin_blkcnt_t = __int64_t -__darwin_blksize_t = __int32_t -__darwin_fsblkcnt_t = c_uint -__darwin_fsfilcnt_t = c_uint -__darwin_gid_t = __uint32_t -__darwin_id_t = __uint32_t -__darwin_ino_t = __uint32_t -__darwin_mach_port_name_t = __darwin_natural_t -__darwin_mach_port_t = __darwin_mach_port_name_t -__darwin_mcontext_t = POINTER(mcontext) -__darwin_mcontext64_t = POINTER(mcontext64) -__darwin_pid_t = __int32_t -__darwin_pthread_attr_t = _opaque_pthread_attr_t -__darwin_pthread_cond_t = _opaque_pthread_cond_t -__darwin_pthread_condattr_t = _opaque_pthread_condattr_t -__darwin_pthread_key_t = c_ulong -__darwin_pthread_mutex_t = _opaque_pthread_mutex_t -__darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t -__darwin_pthread_once_t = _opaque_pthread_once_t -__darwin_pthread_rwlock_t = _opaque_pthread_rwlock_t -__darwin_pthread_rwlockattr_t = _opaque_pthread_rwlockattr_t -__darwin_pthread_t = POINTER(_opaque_pthread_t) -__darwin_sigset_t = __uint32_t -__darwin_suseconds_t = __int32_t -__darwin_uid_t = __uint32_t -__darwin_useconds_t = __uint32_t -__darwin_uuid_t = c_ubyte * 16 -class sigaltstack(Structure): - pass -sigaltstack._fields_ = [ - ('ss_sp', c_void_p), - ('ss_size', __darwin_size_t), - ('ss_flags', c_int), -] -assert sizeof(sigaltstack) == 12, sizeof(sigaltstack) -assert alignment(sigaltstack) == 4, alignment(sigaltstack) -__darwin_stack_t = sigaltstack -class ucontext(Structure): - pass -ucontext._fields_ = [ - ('uc_onstack', c_int), - ('uc_sigmask', __darwin_sigset_t), - ('uc_stack', __darwin_stack_t), - ('uc_link', POINTER(ucontext)), - ('uc_mcsize', __darwin_size_t), - ('uc_mcontext', __darwin_mcontext_t), -] -assert sizeof(ucontext) == 32, sizeof(ucontext) -assert alignment(ucontext) == 4, alignment(ucontext) -__darwin_ucontext_t = ucontext -class ucontext64(Structure): - pass -ucontext64._fields_ = [ - ('uc_onstack', c_int), - ('uc_sigmask', __darwin_sigset_t), - ('uc_stack', __darwin_stack_t), - ('uc_link', POINTER(ucontext64)), - ('uc_mcsize', __darwin_size_t), - ('uc_mcontext64', __darwin_mcontext64_t), -] -assert sizeof(ucontext64) == 32, sizeof(ucontext64) -assert alignment(ucontext64) == 4, alignment(ucontext64) -__darwin_ucontext64_t = ucontext64 -class timeval(Structure): - pass -timeval._fields_ = [ - ('tv_sec', __darwin_time_t), - ('tv_usec', __darwin_suseconds_t), -] -assert sizeof(timeval) == 8, sizeof(timeval) -assert alignment(timeval) == 4, alignment(timeval) -rlim_t = __int64_t -class rusage(Structure): - pass -rusage._fields_ = [ - ('ru_utime', timeval), - ('ru_stime', timeval), - ('ru_maxrss', c_long), - ('ru_ixrss', c_long), - ('ru_idrss', c_long), - ('ru_isrss', c_long), - ('ru_minflt', c_long), - ('ru_majflt', c_long), - ('ru_nswap', c_long), - ('ru_inblock', c_long), - ('ru_oublock', c_long), - ('ru_msgsnd', c_long), - ('ru_msgrcv', c_long), - ('ru_nsignals', c_long), - ('ru_nvcsw', c_long), - ('ru_nivcsw', c_long), -] -assert sizeof(rusage) == 72, sizeof(rusage) -assert alignment(rusage) == 4, alignment(rusage) -class rlimit(Structure): - pass -rlimit._pack_ = 4 -rlimit._fields_ = [ - ('rlim_cur', rlim_t), - ('rlim_max', rlim_t), -] -assert sizeof(rlimit) == 16, sizeof(rlimit) -assert alignment(rlimit) == 4, alignment(rlimit) -mcontext_t = __darwin_mcontext_t -mcontext64_t = __darwin_mcontext64_t -pthread_attr_t = __darwin_pthread_attr_t -sigset_t = __darwin_sigset_t -ucontext_t = __darwin_ucontext_t -ucontext64_t = __darwin_ucontext64_t -uid_t = __darwin_uid_t -class sigval(Union): - pass -sigval._fields_ = [ - ('sival_int', c_int), - ('sival_ptr', c_void_p), -] -assert sizeof(sigval) == 4, sizeof(sigval) -assert alignment(sigval) == 4, alignment(sigval) -class sigevent(Structure): - pass -sigevent._fields_ = [ - ('sigev_notify', c_int), - ('sigev_signo', c_int), - ('sigev_value', sigval), - ('sigev_notify_function', CFUNCTYPE(None, sigval)), - ('sigev_notify_attributes', POINTER(pthread_attr_t)), -] -assert sizeof(sigevent) == 20, sizeof(sigevent) -assert alignment(sigevent) == 4, alignment(sigevent) -class __siginfo(Structure): - pass -pid_t = __darwin_pid_t -__siginfo._fields_ = [ - ('si_signo', c_int), - ('si_errno', c_int), - ('si_code', c_int), - ('si_pid', pid_t), - ('si_uid', uid_t), - ('si_status', c_int), - ('si_addr', c_void_p), - ('si_value', sigval), - ('si_band', c_long), - ('pad', c_ulong * 7), -] -assert sizeof(__siginfo) == 64, sizeof(__siginfo) -assert alignment(__siginfo) == 4, alignment(__siginfo) -siginfo_t = __siginfo -class __sigaction_u(Union): - pass -__sigaction_u._fields_ = [ - ('__sa_handler', CFUNCTYPE(None, c_int)), - ('__sa_sigaction', CFUNCTYPE(None, c_int, POINTER(__siginfo), c_void_p)), -] -assert sizeof(__sigaction_u) == 4, sizeof(__sigaction_u) -assert alignment(__sigaction_u) == 4, alignment(__sigaction_u) -class __sigaction(Structure): - pass -__sigaction._fields_ = [ - ('__sigaction_u', __sigaction_u), - ('sa_tramp', CFUNCTYPE(None, c_void_p, c_int, c_int, POINTER(siginfo_t), c_void_p)), - ('sa_mask', sigset_t), - ('sa_flags', c_int), -] -assert sizeof(__sigaction) == 16, sizeof(__sigaction) -assert alignment(__sigaction) == 4, alignment(__sigaction) -class sigaction(Structure): - pass -sigaction._fields_ = [ - ('__sigaction_u', __sigaction_u), - ('sa_mask', sigset_t), - ('sa_flags', c_int), -] -assert sizeof(sigaction) == 12, sizeof(sigaction) -assert alignment(sigaction) == 4, alignment(sigaction) -sig_t = CFUNCTYPE(None, c_int) -stack_t = __darwin_stack_t -class sigvec(Structure): - pass -sigvec._fields_ = [ - ('sv_handler', CFUNCTYPE(None, c_int)), - ('sv_mask', c_int), - ('sv_flags', c_int), -] -assert sizeof(sigvec) == 12, sizeof(sigvec) -assert alignment(sigvec) == 4, alignment(sigvec) -class sigstack(Structure): - pass -sigstack._fields_ = [ - ('ss_sp', STRING), - ('ss_onstack', c_int), -] -assert sizeof(sigstack) == 8, sizeof(sigstack) -assert alignment(sigstack) == 4, alignment(sigstack) -u_char = c_ubyte -u_short = c_ushort -u_int = c_uint -u_long = c_ulong -ushort = c_ushort -uint = c_uint -u_quad_t = u_int64_t -quad_t = int64_t -qaddr_t = POINTER(quad_t) -caddr_t = STRING -daddr_t = int32_t -fixpt_t = u_int32_t -blkcnt_t = __darwin_blkcnt_t -blksize_t = __darwin_blksize_t -gid_t = __darwin_gid_t -in_addr_t = __uint32_t -in_port_t = __uint16_t -ino_t = __darwin_ino_t -key_t = __int32_t -nlink_t = __uint16_t -off_t = __darwin_off_t -segsz_t = int32_t -swblk_t = int32_t -clock_t = __darwin_clock_t -ssize_t = __darwin_ssize_t -useconds_t = __darwin_useconds_t -suseconds_t = __darwin_suseconds_t -fd_mask = __int32_t -class fd_set(Structure): - pass -fd_set._fields_ = [ - ('fds_bits', __int32_t * 32), -] -assert sizeof(fd_set) == 128, sizeof(fd_set) -assert alignment(fd_set) == 4, alignment(fd_set) -pthread_cond_t = __darwin_pthread_cond_t -pthread_condattr_t = __darwin_pthread_condattr_t -pthread_mutex_t = __darwin_pthread_mutex_t -pthread_mutexattr_t = __darwin_pthread_mutexattr_t -pthread_once_t = __darwin_pthread_once_t -pthread_rwlock_t = __darwin_pthread_rwlock_t -pthread_rwlockattr_t = __darwin_pthread_rwlockattr_t -pthread_t = __darwin_pthread_t -pthread_key_t = __darwin_pthread_key_t -fsblkcnt_t = __darwin_fsblkcnt_t -fsfilcnt_t = __darwin_fsfilcnt_t - -# values for enumeration 'idtype_t' -idtype_t = c_int # enum -id_t = __darwin_id_t -class wait(Union): - pass -class N4wait3DOLLAR_3E(Structure): - pass -N4wait3DOLLAR_3E._fields_ = [ - ('w_Termsig', c_uint, 7), - ('w_Coredump', c_uint, 1), - ('w_Retcode', c_uint, 8), - ('w_Filler', c_uint, 16), -] -assert sizeof(N4wait3DOLLAR_3E) == 4, sizeof(N4wait3DOLLAR_3E) -assert alignment(N4wait3DOLLAR_3E) == 4, alignment(N4wait3DOLLAR_3E) -class N4wait3DOLLAR_4E(Structure): - pass -N4wait3DOLLAR_4E._fields_ = [ - ('w_Stopval', c_uint, 8), - ('w_Stopsig', c_uint, 8), - ('w_Filler', c_uint, 16), -] -assert sizeof(N4wait3DOLLAR_4E) == 4, sizeof(N4wait3DOLLAR_4E) -assert alignment(N4wait3DOLLAR_4E) == 4, alignment(N4wait3DOLLAR_4E) -wait._fields_ = [ - ('w_status', c_int), - ('w_T', N4wait3DOLLAR_3E), - ('w_S', N4wait3DOLLAR_4E), -] -assert sizeof(wait) == 4, sizeof(wait) -assert alignment(wait) == 4, alignment(wait) -class timespec(Structure): - pass -timespec._fields_ = [ - ('tv_sec', time_t), - ('tv_nsec', c_long), -] -assert sizeof(timespec) == 8, sizeof(timespec) -assert alignment(timespec) == 4, alignment(timespec) -class tm(Structure): - pass -tm._fields_ = [ - ('tm_sec', c_int), - ('tm_min', c_int), - ('tm_hour', c_int), - ('tm_mday', c_int), - ('tm_mon', c_int), - ('tm_year', c_int), - ('tm_wday', c_int), - ('tm_yday', c_int), - ('tm_isdst', c_int), - ('tm_gmtoff', c_long), - ('tm_zone', STRING), -] -assert sizeof(tm) == 44, sizeof(tm) -assert alignment(tm) == 4, alignment(tm) -__gnuc_va_list = STRING -ptrdiff_t = c_int -int8_t = c_byte -int16_t = c_short -uint8_t = c_ubyte -uint16_t = c_ushort -uint32_t = c_uint -uint64_t = c_ulonglong -int_least8_t = int8_t -int_least16_t = int16_t -int_least32_t = int32_t -int_least64_t = int64_t -uint_least8_t = uint8_t -uint_least16_t = uint16_t -uint_least32_t = uint32_t -uint_least64_t = uint64_t -int_fast8_t = int8_t -int_fast16_t = int16_t -int_fast32_t = int32_t -int_fast64_t = int64_t -uint_fast8_t = uint8_t -uint_fast16_t = uint16_t -uint_fast32_t = uint32_t -uint_fast64_t = uint64_t -intptr_t = c_long -uintptr_t = c_ulong -intmax_t = c_longlong -uintmax_t = c_ulonglong -__all__ = ['ENGINE', 'pkcs7_enc_content_st', '__int16_t', - 'X509_REVOKED', 'SSL_CTX', 'UIT_BOOLEAN', - '__darwin_time_t', 'ucontext64_t', 'int_fast32_t', - 'pem_ctx_st', 'uint8_t', 'fpos_t', 'X509', 'COMP_CTX', - 'tm', 'N10pem_ctx_st4DOLLAR_17E', 'swblk_t', - 'ASN1_TEMPLATE', '__darwin_pthread_t', 'fixpt_t', - 'BIO_METHOD', 'ASN1_PRINTABLESTRING', 'EVP_ENCODE_CTX', - 'dh_method', 'bio_f_buffer_ctx_struct', 'in_port_t', - 'X509_SIG', '__darwin_ssize_t', '__darwin_sigset_t', - 'wait', 'uint_fast16_t', 'N12asn1_type_st4DOLLAR_11E', - 'uint_least8_t', 'pthread_rwlock_t', 'ASN1_IA5STRING', - 'fsfilcnt_t', 'ucontext', '__uint64_t', 'timespec', - 'x509_cinf_st', 'COMP_METHOD', 'MD5_CTX', 'buf_mem_st', - 'ASN1_ENCODING_st', 'PBEPARAM', 'X509_NAME_ENTRY', - '__darwin_va_list', 'ucontext_t', 'lhash_st', - 'N4wait3DOLLAR_4E', '__darwin_uuid_t', - '_ossl_old_des_ks_struct', 'id_t', 'ASN1_BIT_STRING', - 'va_list', '__darwin_wchar_t', 'pthread_key_t', - 'pkcs7_signer_info_st', 'ASN1_METHOD', 'DSA_SIG', 'DSA', - 'UIT_NONE', 'pthread_t', '__darwin_useconds_t', - 'uint_fast8_t', 'UI_STRING', 'DES_cblock', - '__darwin_mcontext64_t', 'rlim_t', 'PEM_Encode_Seal_st', - 'SHAstate_st', 'u_quad_t', 'openssl_fptr', - '_opaque_pthread_rwlockattr_t', - 'N18x509_attributes_st4DOLLAR_13E', - '__darwin_pthread_rwlock_t', 'daddr_t', 'ui_string_st', - 'x509_file_st', 'X509_req_info_st', 'int_least64_t', - 'evp_Encode_Ctx_st', 'X509_OBJECTS', 'CRYPTO_EX_DATA', - '__int8_t', 'AUTHORITY_KEYID_st', '_opaque_pthread_attr_t', - 'sigstack', 'EVP_CIPHER_CTX', 'X509_extension_st', 'pid_t', - 'RSA_METHOD', 'PEM_USER', 'pem_recip_st', 'env_md_ctx_st', - 'rc5_key_st', 'ui_st', 'X509_PUBKEY', 'u_int8_t', - 'ASN1_ITEM_st', 'pkcs7_recip_info_st', 'ssl2_state_st', - 'off_t', 'N10ssl_ctx_st4DOLLAR_18E', 'crypto_ex_data_st', - 'ui_method_st', '__darwin_pthread_rwlockattr_t', - 'CRYPTO_EX_dup', '__darwin_ino_t', '__sFILE', - 'OSUnknownByteOrder', 'BN_MONT_CTX', 'ASN1_NULL', 'time_t', - 'CRYPTO_EX_new', 'asn1_type_st', 'CRYPTO_EX_DATA_FUNCS', - 'user_time_t', 'BIGNUM', 'pthread_rwlockattr_t', - 'ASN1_VALUE_st', 'DH_METHOD', '__darwin_off_t', - '_opaque_pthread_t', 'bn_blinding_st', 'RSA', 'ssize_t', - 'mcontext64_t', 'user_long_t', 'fsblkcnt_t', 'cert_st', - '__darwin_pthread_condattr_t', 'X509_PKEY', - '__darwin_id_t', '__darwin_nl_item', 'SSL2_STATE', 'FILE', - 'pthread_mutexattr_t', 'size_t', - '_ossl_old_des_key_schedule', 'pkcs7_issuer_and_serial_st', - 'sigval', 'CRYPTO_MEM_LEAK_CB', 'X509_NAME', 'blkcnt_t', - 'uint_least16_t', '__darwin_dev_t', 'evp_cipher_info_st', - 'BN_BLINDING', 'ssl3_state_st', 'uint_least64_t', - 'user_addr_t', 'DES_key_schedule', 'RIPEMD160_CTX', - 'u_char', 'X509_algor_st', 'uid_t', 'sess_cert_st', - 'u_int64_t', 'u_int16_t', 'sigset_t', '__darwin_ptrdiff_t', - 'ASN1_CTX', 'STACK', '__int32_t', 'UI_METHOD', - 'NETSCAPE_SPKI', 'UIT_PROMPT', 'st_CRYPTO_EX_DATA_IMPL', - 'cast_key_st', 'X509_HASH_DIR_CTX', 'sigevent', - 'user_ssize_t', 'clock_t', 'aes_key_st', - '__darwin_socklen_t', '__darwin_intptr_t', 'int_fast64_t', - 'asn1_string_table_st', 'uint_fast32_t', - 'ASN1_VISIBLESTRING', 'DSA_SIG_st', 'obj_name_st', - 'X509_LOOKUP_METHOD', 'u_int32_t', 'EVP_CIPHER_INFO', - '__gnuc_va_list', 'AES_KEY', 'PKCS7_ISSUER_AND_SERIAL', - 'BN_CTX', '__darwin_blkcnt_t', 'key_t', 'SHA_CTX', - 'pkcs7_signed_st', 'SSL', 'N10pem_ctx_st4DOLLAR_16E', - 'pthread_attr_t', 'EVP_MD', 'uint', 'ASN1_BOOLEAN', - 'ino_t', '__darwin_clock_t', 'ASN1_OCTET_STRING', - 'asn1_ctx_st', 'BIO_F_BUFFER_CTX', 'bn_mont_ctx_st', - 'X509_REQ_INFO', 'PEM_CTX', 'sigvec', - '__darwin_pthread_mutexattr_t', 'x509_attributes_st', - 'stack_t', '__darwin_mode_t', '__mbstate_t', - 'asn1_object_st', 'ASN1_ENCODING', '__uint8_t', - 'LHASH_NODE', 'PKCS7_SIGNER_INFO', 'asn1_method_st', - 'stack_st', 'bio_info_cb', 'div_t', 'UIT_VERIFY', - 'PBEPARAM_st', 'N4wait3DOLLAR_3E', 'quad_t', '__siginfo', - '__darwin_mbstate_t', 'rsa_st', 'ASN1_UNIVERSALSTRING', - 'uint64_t', 'ssl_comp_st', 'X509_OBJECT', 'pthread_cond_t', - 'DH', '__darwin_wctype_t', 'PKCS7_ENVELOPE', 'ASN1_TLC_st', - 'sig_atomic_t', 'BIO', 'nlink_t', 'BUF_MEM', 'SSL3_RECORD', - 'bio_method_st', 'timeval', 'UI_string_types', 'BIO_dummy', - 'ssl_ctx_st', 'NETSCAPE_CERT_SEQUENCE', - 'BIT_STRING_BITNAME_st', '__darwin_pthread_attr_t', - 'int8_t', '__darwin_wint_t', 'OBJ_NAME', - 'PKCS8_PRIV_KEY_INFO', 'PBE2PARAM_st', - 'LHASH_DOALL_FN_TYPE', 'x509_st', 'X509_VAL', 'dev_t', - 'ASN1_TEMPLATE_st', 'MD5state_st', '__uint16_t', - 'LHASH_DOALL_ARG_FN_TYPE', 'mdc2_ctx_st', 'SSL3_STATE', - 'ssl3_buffer_st', 'ASN1_ITEM_EXP', - '_opaque_pthread_condattr_t', 'mode_t', 'ASN1_VALUE', - 'qaddr_t', '__darwin_gid_t', 'EVP_PKEY', 'CRYPTO_EX_free', - '_ossl_old_des_cblock', 'X509_INFO', 'asn1_string_st', - 'intptr_t', 'UIT_INFO', 'int_fast8_t', 'sigaltstack', - 'env_md_st', 'LHASH', '__darwin_ucontext_t', - 'PKCS7_SIGN_ENVELOPE', '__darwin_mcontext_t', 'ct_rune_t', - 'MD2_CTX', 'pthread_once_t', 'SSL3_BUFFER', 'fd_mask', - 'ASN1_TYPE', 'PKCS7_SIGNED', 'ssl3_record_st', 'BF_KEY', - 'MD4state_st', 'MD4_CTX', 'int16_t', 'SSL_CIPHER', - 'rune_t', 'X509_TRUST', 'siginfo_t', 'X509_STORE', - '__sbuf', 'X509_STORE_CTX', '__darwin_blksize_t', 'ldiv_t', - 'ASN1_TIME', 'SSL_METHOD', 'X509_LOOKUP', - 'Netscape_spki_st', 'P_PID', 'sigaction', 'sig_t', - 'hostent', 'x509_cert_aux_st', '_opaque_pthread_cond_t', - 'segsz_t', 'ushort', '__darwin_ct_rune_t', 'fd_set', - 'BN_RECP_CTX', 'x509_lookup_st', 'uint16_t', 'pkcs7_st', - 'asn1_header_st', '__darwin_pthread_key_t', - 'x509_trust_st', '__darwin_pthread_handler_rec', 'int32_t', - 'X509_CRL_INFO', 'N11evp_pkey_st4DOLLAR_12E', 'MDC2_CTX', - 'N23_ossl_old_des_ks_struct4DOLLAR_10E', 'ASN1_HEADER', - 'X509_crl_info_st', 'LHASH_HASH_FN_TYPE', - '_opaque_pthread_mutexattr_t', 'ssl_st', - 'N8pkcs7_st4DOLLAR_15E', 'evp_pkey_st', - 'pkcs7_signedandenveloped_st', '__darwin_mach_port_t', - 'EVP_PBE_KEYGEN', '_opaque_pthread_mutex_t', - 'ASN1_UTCTIME', 'mcontext', 'crypto_ex_data_func_st', - 'u_long', 'PBKDF2PARAM_st', 'rc4_key_st', 'DSA_METHOD', - 'EVP_CIPHER', 'BIT_STRING_BITNAME', 'PKCS7_RECIP_INFO', - 'ssl3_enc_method', 'X509_CERT_AUX', 'uintmax_t', - 'int_fast16_t', 'RC5_32_KEY', 'ucontext64', 'ASN1_INTEGER', - 'u_short', 'N14x509_object_st4DOLLAR_14E', 'mcontext64', - 'X509_sig_st', 'ASN1_GENERALSTRING', 'PKCS7', '__sFILEX', - 'X509_name_entry_st', 'ssl_session_st', 'caddr_t', - 'bignum_st', 'X509_CINF', '__darwin_pthread_cond_t', - 'ASN1_TLC', 'PKCS7_ENCRYPT', 'NETSCAPE_SPKAC', - 'Netscape_spkac_st', 'idtype_t', 'UIT_ERROR', - 'uint_fast64_t', 'in_addr_t', 'pthread_mutex_t', - '__int64_t', 'ASN1_BMPSTRING', 'uint32_t', - 'PEM_ENCODE_SEAL_CTX', 'suseconds_t', 'ASN1_OBJECT', - 'X509_val_st', 'private_key_st', 'CRYPTO_dynlock', - 'X509_objects_st', 'CRYPTO_EX_DATA_IMPL', - 'pthread_condattr_t', 'PKCS7_DIGEST', 'uint_least32_t', - 'ASN1_STRING', '__uint32_t', 'P_PGID', 'rsa_meth_st', - 'X509_crl_st', 'RC2_KEY', '__darwin_fsfilcnt_t', - 'X509_revoked_st', 'PBE2PARAM', 'blksize_t', - 'Netscape_certificate_sequence', 'ssl_cipher_st', - 'bignum_ctx', 'register_t', 'ASN1_UTF8STRING', - 'pkcs7_encrypted_st', 'RC4_KEY', '__darwin_ucontext64_t', - 'N13ssl2_state_st4DOLLAR_19E', 'bn_recp_ctx_st', - 'CAST_KEY', 'X509_ATTRIBUTE', '__darwin_suseconds_t', - '__sigaction', 'user_ulong_t', 'syscall_arg_t', - 'evp_cipher_ctx_st', 'X509_ALGOR', 'mcontext_t', - 'const_DES_cblock', '__darwin_fsblkcnt_t', 'dsa_st', - 'int_least8_t', 'MD2state_st', 'X509_EXTENSION', - 'GEN_SESSION_CB', 'int_least16_t', '__darwin_wctrans_t', - 'PBKDF2PARAM', 'x509_lookup_method_st', 'pem_password_cb', - 'X509_info_st', 'x509_store_st', '__darwin_natural_t', - 'X509_pubkey_st', 'pkcs7_digest_st', '__darwin_size_t', - 'ASN1_STRING_TABLE', 'OSLittleEndian', 'RIPEMD160state_st', - 'pkcs7_enveloped_st', 'UI', 'ptrdiff_t', 'X509_REQ', - 'CRYPTO_dynlock_value', 'X509_req_st', 'x509_store_ctx_st', - 'N13ssl3_state_st4DOLLAR_20E', 'lhash_node_st', - '__darwin_pthread_mutex_t', 'LHASH_COMP_FN_TYPE', - '__darwin_rune_t', 'rlimit', '__darwin_pthread_once_t', - 'OSBigEndian', 'uintptr_t', '__darwin_uid_t', 'u_int', - 'ASN1_T61STRING', 'gid_t', 'ssl_method_st', 'ASN1_ITEM', - 'ASN1_ENUMERATED', '_opaque_pthread_rwlock_t', - 'pkcs8_priv_key_info_st', 'intmax_t', 'sigcontext', - 'X509_CRL', 'rc2_key_st', 'engine_st', 'x509_object_st', - '_opaque_pthread_once_t', 'DES_ks', 'SSL_COMP', - 'dsa_method', 'int64_t', 'bio_st', 'bf_key_st', - 'ASN1_GENERALIZEDTIME', 'PKCS7_ENC_CONTENT', - '__darwin_pid_t', 'lldiv_t', 'comp_method_st', - 'EVP_MD_CTX', 'evp_cipher_st', 'X509_name_st', - 'x509_hash_dir_st', '__darwin_mach_port_name_t', - 'useconds_t', 'user_size_t', 'SSL_SESSION', 'rusage', - 'ssl_crock_st', 'int_least32_t', '__sigaction_u', 'dh_st', - 'P_ALL', '__darwin_stack_t', 'N6DES_ks3DOLLAR_9E', - 'comp_ctx_st', 'X509_CERT_FILE_CTX'] diff --git a/Lib/test/test_lib2to3/data/py2_test_grammar.py b/Lib/test/test_lib2to3/data/py2_test_grammar.py deleted file mode 100644 index 1a631510f4dba7..00000000000000 --- a/Lib/test/test_lib2to3/data/py2_test_grammar.py +++ /dev/null @@ -1,971 +0,0 @@ -# Python test set -- part 1, grammar. -# This just tests whether the parser accepts them all. - -# NOTE: When you run this test as a script from the command line, you -# get warnings about certain hex/oct constants. Since those are -# issued by the parser, you can't suppress them by adding a -# filterwarnings() call to this module. Therefore, to shut up the -# regression test, the filterwarnings() call has been added to -# regrtest.py. - -from test.test_support import check_syntax_error -import unittest -import sys -# testing import * -from sys import * - -class TokenTests(unittest.TestCase): - - def testBackslash(self): - # Backslash means line continuation: - x = 1 \ - + 1 - self.assertEquals(x, 2, 'backslash for line continuation') - - # Backslash does not means continuation in comments :\ - x = 0 - self.assertEquals(x, 0, 'backslash ending comment') - - def testPlainIntegers(self): - self.assertEquals(0xff, 255) - self.assertEquals(0377, 255) - self.assertEquals(2147483647, 017777777777) - # "0x" is not a valid literal - self.assertRaises(SyntaxError, eval, "0x") - from sys import maxint - if maxint == 2147483647: - self.assertEquals(-2147483647-1, -020000000000) - # XXX -2147483648 - self.assert_(037777777777 > 0) - self.assert_(0xffffffff > 0) - for s in '2147483648', '040000000000', '0x100000000': - try: - x = eval(s) - except OverflowError: - self.fail("OverflowError on huge integer literal %r" % s) - elif maxint == 9223372036854775807: - self.assertEquals(-9223372036854775807-1, -01000000000000000000000) - self.assert_(01777777777777777777777 > 0) - self.assert_(0xffffffffffffffff > 0) - for s in '9223372036854775808', '02000000000000000000000', \ - '0x10000000000000000': - try: - x = eval(s) - except OverflowError: - self.fail("OverflowError on huge integer literal %r" % s) - else: - self.fail('Weird maxint value %r' % maxint) - - def testLongIntegers(self): - x = 0L - x = 0l - x = 0xffffffffffffffffL - x = 0xffffffffffffffffl - x = 077777777777777777L - x = 077777777777777777l - x = 123456789012345678901234567890L - x = 123456789012345678901234567890l - - def testFloats(self): - x = 3.14 - x = 314. - x = 0.314 - # XXX x = 000.314 - x = .314 - x = 3e14 - x = 3E14 - x = 3e-14 - x = 3e+14 - x = 3.e14 - x = .3e14 - x = 3.1e4 - - def testStringLiterals(self): - x = ''; y = ""; self.assert_(len(x) == 0 and x == y) - x = '\''; y = "'"; self.assert_(len(x) == 1 and x == y and ord(x) == 39) - x = '"'; y = "\""; self.assert_(len(x) == 1 and x == y and ord(x) == 34) - x = "doesn't \"shrink\" does it" - y = 'doesn\'t "shrink" does it' - self.assert_(len(x) == 24 and x == y) - x = "does \"shrink\" doesn't it" - y = 'does "shrink" doesn\'t it' - self.assert_(len(x) == 24 and x == y) - x = """ -The "quick" -brown fox -jumps over -the 'lazy' dog. -""" - y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n' - self.assertEquals(x, y) - y = ''' -The "quick" -brown fox -jumps over -the 'lazy' dog. -''' - self.assertEquals(x, y) - y = "\n\ -The \"quick\"\n\ -brown fox\n\ -jumps over\n\ -the 'lazy' dog.\n\ -" - self.assertEquals(x, y) - y = '\n\ -The \"quick\"\n\ -brown fox\n\ -jumps over\n\ -the \'lazy\' dog.\n\ -' - self.assertEquals(x, y) - - -class GrammarTests(unittest.TestCase): - - # single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE - # XXX can't test in a script -- this rule is only used when interactive - - # file_input: (NEWLINE | stmt)* ENDMARKER - # Being tested as this very moment this very module - - # expr_input: testlist NEWLINE - # XXX Hard to test -- used only in calls to input() - - def testEvalInput(self): - # testlist ENDMARKER - x = eval('1, 0 or 1') - - def testFuncdef(self): - ### 'def' NAME parameters ':' suite - ### parameters: '(' [varargslist] ')' - ### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME] - ### | ('**'|'*' '*') NAME) - ### | fpdef ['=' test] (',' fpdef ['=' test])* [','] - ### fpdef: NAME | '(' fplist ')' - ### fplist: fpdef (',' fpdef)* [','] - ### arglist: (argument ',')* (argument | *' test [',' '**' test] | '**' test) - ### argument: [test '='] test # Really [keyword '='] test - def f1(): pass - f1() - f1(*()) - f1(*(), **{}) - def f2(one_argument): pass - def f3(two, arguments): pass - def f4(two, (compound, (argument, list))): pass - def f5((compound, first), two): pass - self.assertEquals(f2.func_code.co_varnames, ('one_argument',)) - self.assertEquals(f3.func_code.co_varnames, ('two', 'arguments')) - if sys.platform.startswith('java'): - self.assertEquals(f4.func_code.co_varnames, - ('two', '(compound, (argument, list))', 'compound', 'argument', - 'list',)) - self.assertEquals(f5.func_code.co_varnames, - ('(compound, first)', 'two', 'compound', 'first')) - else: - self.assertEquals(f4.func_code.co_varnames, - ('two', '.1', 'compound', 'argument', 'list')) - self.assertEquals(f5.func_code.co_varnames, - ('.0', 'two', 'compound', 'first')) - def a1(one_arg,): pass - def a2(two, args,): pass - def v0(*rest): pass - def v1(a, *rest): pass - def v2(a, b, *rest): pass - def v3(a, (b, c), *rest): return a, b, c, rest - - f1() - f2(1) - f2(1,) - f3(1, 2) - f3(1, 2,) - f4(1, (2, (3, 4))) - v0() - v0(1) - v0(1,) - v0(1,2) - v0(1,2,3,4,5,6,7,8,9,0) - v1(1) - v1(1,) - v1(1,2) - v1(1,2,3) - v1(1,2,3,4,5,6,7,8,9,0) - v2(1,2) - v2(1,2,3) - v2(1,2,3,4) - v2(1,2,3,4,5,6,7,8,9,0) - v3(1,(2,3)) - v3(1,(2,3),4) - v3(1,(2,3),4,5,6,7,8,9,0) - - # ceval unpacks the formal arguments into the first argcount names; - # thus, the names nested inside tuples must appear after these names. - if sys.platform.startswith('java'): - self.assertEquals(v3.func_code.co_varnames, ('a', '(b, c)', 'rest', 'b', 'c')) - else: - self.assertEquals(v3.func_code.co_varnames, ('a', '.1', 'rest', 'b', 'c')) - self.assertEquals(v3(1, (2, 3), 4), (1, 2, 3, (4,))) - def d01(a=1): pass - d01() - d01(1) - d01(*(1,)) - d01(**{'a':2}) - def d11(a, b=1): pass - d11(1) - d11(1, 2) - d11(1, **{'b':2}) - def d21(a, b, c=1): pass - d21(1, 2) - d21(1, 2, 3) - d21(*(1, 2, 3)) - d21(1, *(2, 3)) - d21(1, 2, *(3,)) - d21(1, 2, **{'c':3}) - def d02(a=1, b=2): pass - d02() - d02(1) - d02(1, 2) - d02(*(1, 2)) - d02(1, *(2,)) - d02(1, **{'b':2}) - d02(**{'a': 1, 'b': 2}) - def d12(a, b=1, c=2): pass - d12(1) - d12(1, 2) - d12(1, 2, 3) - def d22(a, b, c=1, d=2): pass - d22(1, 2) - d22(1, 2, 3) - d22(1, 2, 3, 4) - def d01v(a=1, *rest): pass - d01v() - d01v(1) - d01v(1, 2) - d01v(*(1, 2, 3, 4)) - d01v(*(1,)) - d01v(**{'a':2}) - def d11v(a, b=1, *rest): pass - d11v(1) - d11v(1, 2) - d11v(1, 2, 3) - def d21v(a, b, c=1, *rest): pass - d21v(1, 2) - d21v(1, 2, 3) - d21v(1, 2, 3, 4) - d21v(*(1, 2, 3, 4)) - d21v(1, 2, **{'c': 3}) - def d02v(a=1, b=2, *rest): pass - d02v() - d02v(1) - d02v(1, 2) - d02v(1, 2, 3) - d02v(1, *(2, 3, 4)) - d02v(**{'a': 1, 'b': 2}) - def d12v(a, b=1, c=2, *rest): pass - d12v(1) - d12v(1, 2) - d12v(1, 2, 3) - d12v(1, 2, 3, 4) - d12v(*(1, 2, 3, 4)) - d12v(1, 2, *(3, 4, 5)) - d12v(1, *(2,), **{'c': 3}) - def d22v(a, b, c=1, d=2, *rest): pass - d22v(1, 2) - d22v(1, 2, 3) - d22v(1, 2, 3, 4) - d22v(1, 2, 3, 4, 5) - d22v(*(1, 2, 3, 4)) - d22v(1, 2, *(3, 4, 5)) - d22v(1, *(2, 3), **{'d': 4}) - def d31v((x)): pass - d31v(1) - def d32v((x,)): pass - d32v((1,)) - - # keyword arguments after *arglist - def f(*args, **kwargs): - return args, kwargs - self.assertEquals(f(1, x=2, *[3, 4], y=5), ((1, 3, 4), - {'x':2, 'y':5})) - self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)") - self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)") - - # Check ast errors in *args and *kwargs - check_syntax_error(self, "f(*g(1=2))") - check_syntax_error(self, "f(**g(1=2))") - - def testLambdef(self): - ### lambdef: 'lambda' [varargslist] ':' test - l1 = lambda : 0 - self.assertEquals(l1(), 0) - l2 = lambda : a[d] # XXX just testing the expression - l3 = lambda : [2 < x for x in [-1, 3, 0L]] - self.assertEquals(l3(), [0, 1, 0]) - l4 = lambda x = lambda y = lambda z=1 : z : y() : x() - self.assertEquals(l4(), 1) - l5 = lambda x, y, z=2: x + y + z - self.assertEquals(l5(1, 2), 5) - self.assertEquals(l5(1, 2, 3), 6) - check_syntax_error(self, "lambda x: x = 2") - check_syntax_error(self, "lambda (None,): None") - - ### stmt: simple_stmt | compound_stmt - # Tested below - - def testSimpleStmt(self): - ### simple_stmt: small_stmt (';' small_stmt)* [';'] - x = 1; pass; del x - def foo(): - # verify statements that end with semi-colons - x = 1; pass; del x; - foo() - - ### small_stmt: expr_stmt | print_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt - # Tested below - - def testExprStmt(self): - # (exprlist '=')* exprlist - 1 - 1, 2, 3 - x = 1 - x = 1, 2, 3 - x = y = z = 1, 2, 3 - x, y, z = 1, 2, 3 - abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4) - - check_syntax_error(self, "x + 1 = 1") - check_syntax_error(self, "a + 1 = b + 2") - - def testPrintStmt(self): - # 'print' (test ',')* [test] - import StringIO - - # Can't test printing to real stdout without comparing output - # which is not available in unittest. - save_stdout = sys.stdout - sys.stdout = StringIO.StringIO() - - print 1, 2, 3 - print 1, 2, 3, - print - print 0 or 1, 0 or 1, - print 0 or 1 - - # 'print' '>>' test ',' - print >> sys.stdout, 1, 2, 3 - print >> sys.stdout, 1, 2, 3, - print >> sys.stdout - print >> sys.stdout, 0 or 1, 0 or 1, - print >> sys.stdout, 0 or 1 - - # test printing to an instance - class Gulp: - def write(self, msg): pass - - gulp = Gulp() - print >> gulp, 1, 2, 3 - print >> gulp, 1, 2, 3, - print >> gulp - print >> gulp, 0 or 1, 0 or 1, - print >> gulp, 0 or 1 - - # test print >> None - def driver(): - oldstdout = sys.stdout - sys.stdout = Gulp() - try: - tellme(Gulp()) - tellme() - finally: - sys.stdout = oldstdout - - # we should see this once - def tellme(file=sys.stdout): - print >> file, 'hello world' - - driver() - - # we should not see this at all - def tellme(file=None): - print >> file, 'goodbye universe' - - driver() - - self.assertEqual(sys.stdout.getvalue(), '''\ -1 2 3 -1 2 3 -1 1 1 -1 2 3 -1 2 3 -1 1 1 -hello world -''') - sys.stdout = save_stdout - - # syntax errors - check_syntax_error(self, 'print ,') - check_syntax_error(self, 'print >> x,') - - def testDelStmt(self): - # 'del' exprlist - abc = [1,2,3] - x, y, z = abc - xyz = x, y, z - - del abc - del x, y, (z, xyz) - - def testPassStmt(self): - # 'pass' - pass - - # flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt - # Tested below - - def testBreakStmt(self): - # 'break' - while 1: break - - def testContinueStmt(self): - # 'continue' - i = 1 - while i: i = 0; continue - - msg = "" - while not msg: - msg = "ok" - try: - continue - msg = "continue failed to continue inside try" - except: - msg = "continue inside try called except block" - if msg != "ok": - self.fail(msg) - - msg = "" - while not msg: - msg = "finally block not called" - try: - continue - finally: - msg = "ok" - if msg != "ok": - self.fail(msg) - - def test_break_continue_loop(self): - # This test warrants an explanation. It is a test specifically for SF bugs - # #463359 and #462937. The bug is that a 'break' statement executed or - # exception raised inside a try/except inside a loop, *after* a continue - # statement has been executed in that loop, will cause the wrong number of - # arguments to be popped off the stack and the instruction pointer reset to - # a very small number (usually 0.) Because of this, the following test - # *must* written as a function, and the tracking vars *must* be function - # arguments with default values. Otherwise, the test will loop and loop. - - def test_inner(extra_burning_oil = 1, count=0): - big_hippo = 2 - while big_hippo: - count += 1 - try: - if extra_burning_oil and big_hippo == 1: - extra_burning_oil -= 1 - break - big_hippo -= 1 - continue - except: - raise - if count > 2 or big_hippo <> 1: - self.fail("continue then break in try/except in loop broken!") - test_inner() - - def testReturn(self): - # 'return' [testlist] - def g1(): return - def g2(): return 1 - g1() - x = g2() - check_syntax_error(self, "class foo:return 1") - - def testYield(self): - check_syntax_error(self, "class foo:yield 1") - - def testRaise(self): - # 'raise' test [',' test] - try: raise RuntimeError, 'just testing' - except RuntimeError: pass - try: raise KeyboardInterrupt - except KeyboardInterrupt: pass - - def testImport(self): - # 'import' dotted_as_names - import sys - import time, sys - # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names) - from time import time - from time import (time) - # not testable inside a function, but already done at top of the module - # from sys import * - from sys import path, argv - from sys import (path, argv) - from sys import (path, argv,) - - def testGlobal(self): - # 'global' NAME (',' NAME)* - global a - global a, b - global one, two, three, four, five, six, seven, eight, nine, ten - - def testExec(self): - # 'exec' expr ['in' expr [',' expr]] - z = None - del z - exec 'z=1+1\n' - if z != 2: self.fail('exec \'z=1+1\'\\n') - del z - exec 'z=1+1' - if z != 2: self.fail('exec \'z=1+1\'') - z = None - del z - import types - if hasattr(types, "UnicodeType"): - exec r"""if 1: - exec u'z=1+1\n' - if z != 2: self.fail('exec u\'z=1+1\'\\n') - del z - exec u'z=1+1' - if z != 2: self.fail('exec u\'z=1+1\'')""" - g = {} - exec 'z = 1' in g - if g.has_key('__builtins__'): del g['__builtins__'] - if g != {'z': 1}: self.fail('exec \'z = 1\' in g') - g = {} - l = {} - - import warnings - warnings.filterwarnings("ignore", "global statement", module="") - exec 'global a; a = 1; b = 2' in g, l - if g.has_key('__builtins__'): del g['__builtins__'] - if l.has_key('__builtins__'): del l['__builtins__'] - if (g, l) != ({'a':1}, {'b':2}): - self.fail('exec ... in g (%s), l (%s)' %(g,l)) - - def testAssert(self): - # assert_stmt: 'assert' test [',' test] - assert 1 - assert 1, 1 - assert lambda x:x - assert 1, lambda x:x+1 - try: - assert 0, "msg" - except AssertionError, e: - self.assertEquals(e.args[0], "msg") - else: - if __debug__: - self.fail("AssertionError not raised by assert 0") - - ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef - # Tested below - - def testIf(self): - # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] - if 1: pass - if 1: pass - else: pass - if 0: pass - elif 0: pass - if 0: pass - elif 0: pass - elif 0: pass - elif 0: pass - else: pass - - def testWhile(self): - # 'while' test ':' suite ['else' ':' suite] - while 0: pass - while 0: pass - else: pass - - # Issue1920: "while 0" is optimized away, - # ensure that the "else" clause is still present. - x = 0 - while 0: - x = 1 - else: - x = 2 - self.assertEquals(x, 2) - - def testFor(self): - # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] - for i in 1, 2, 3: pass - for i, j, k in (): pass - else: pass - class Squares: - def __init__(self, max): - self.max = max - self.sofar = [] - def __len__(self): return len(self.sofar) - def __getitem__(self, i): - if not 0 <= i < self.max: raise IndexError - n = len(self.sofar) - while n <= i: - self.sofar.append(n*n) - n = n+1 - return self.sofar[i] - n = 0 - for x in Squares(10): n = n+x - if n != 285: - self.fail('for over growing sequence') - - result = [] - for x, in [(1,), (2,), (3,)]: - result.append(x) - self.assertEqual(result, [1, 2, 3]) - - def testTry(self): - ### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite] - ### | 'try' ':' suite 'finally' ':' suite - ### except_clause: 'except' [expr [('as' | ',') expr]] - try: - 1/0 - except ZeroDivisionError: - pass - else: - pass - try: 1/0 - except EOFError: pass - except TypeError as msg: pass - except RuntimeError, msg: pass - except: pass - else: pass - try: 1/0 - except (EOFError, TypeError, ZeroDivisionError): pass - try: 1/0 - except (EOFError, TypeError, ZeroDivisionError), msg: pass - try: pass - finally: pass - - def testSuite(self): - # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT - if 1: pass - if 1: - pass - if 1: - # - # - # - pass - pass - # - pass - # - - def testTest(self): - ### and_test ('or' and_test)* - ### and_test: not_test ('and' not_test)* - ### not_test: 'not' not_test | comparison - if not 1: pass - if 1 and 1: pass - if 1 or 1: pass - if not not not 1: pass - if not 1 and 1 and 1: pass - if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass - - def testComparison(self): - ### comparison: expr (comp_op expr)* - ### comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' - if 1: pass - x = (1 == 1) - if 1 == 1: pass - if 1 != 1: pass - if 1 <> 1: pass - if 1 < 1: pass - if 1 > 1: pass - if 1 <= 1: pass - if 1 >= 1: pass - if 1 is 1: pass - if 1 is not 1: pass - if 1 in (): pass - if 1 not in (): pass - if 1 < 1 > 1 == 1 >= 1 <= 1 <> 1 != 1 in 1 not in 1 is 1 is not 1: pass - - def testBinaryMaskOps(self): - x = 1 & 1 - x = 1 ^ 1 - x = 1 | 1 - - def testShiftOps(self): - x = 1 << 1 - x = 1 >> 1 - x = 1 << 1 >> 1 - - def testAdditiveOps(self): - x = 1 - x = 1 + 1 - x = 1 - 1 - 1 - x = 1 - 1 + 1 - 1 + 1 - - def testMultiplicativeOps(self): - x = 1 * 1 - x = 1 / 1 - x = 1 % 1 - x = 1 / 1 * 1 % 1 - - def testUnaryOps(self): - x = +1 - x = -1 - x = ~1 - x = ~1 ^ 1 & 1 | 1 & 1 ^ -1 - x = -1*1/1 + 1*1 - ---1*1 - - def testSelectors(self): - ### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME - ### subscript: expr | [expr] ':' [expr] - - import sys, time - c = sys.path[0] - x = time.time() - x = sys.modules['time'].time() - a = '01234' - c = a[0] - c = a[-1] - s = a[0:5] - s = a[:5] - s = a[0:] - s = a[:] - s = a[-5:] - s = a[:-1] - s = a[-4:-3] - # A rough test of SF bug 1333982. https://bugs.python.org/issue1333982 - # The testing here is fairly incomplete. - # Test cases should include: commas with 1 and 2 colons - d = {} - d[1] = 1 - d[1,] = 2 - d[1,2] = 3 - d[1,2,3] = 4 - L = list(d) - L.sort() - self.assertEquals(str(L), '[1, (1,), (1, 2), (1, 2, 3)]') - - def testAtoms(self): - ### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING - ### dictmaker: test ':' test (',' test ':' test)* [','] - - x = (1) - x = (1 or 2 or 3) - x = (1 or 2 or 3, 2, 3) - - x = [] - x = [1] - x = [1 or 2 or 3] - x = [1 or 2 or 3, 2, 3] - x = [] - - x = {} - x = {'one': 1} - x = {'one': 1,} - x = {'one' or 'two': 1 or 2} - x = {'one': 1, 'two': 2} - x = {'one': 1, 'two': 2,} - x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6} - - x = `x` - x = `1 or 2 or 3` - self.assertEqual(`1,2`, '(1, 2)') - - x = x - x = 'x' - x = 123 - - ### exprlist: expr (',' expr)* [','] - ### testlist: test (',' test)* [','] - # These have been exercised enough above - - def testClassdef(self): - # 'class' NAME ['(' [testlist] ')'] ':' suite - class B: pass - class B2(): pass - class C1(B): pass - class C2(B): pass - class D(C1, C2, B): pass - class C: - def meth1(self): pass - def meth2(self, arg): pass - def meth3(self, a1, a2): pass - # decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE - # decorators: decorator+ - # decorated: decorators (classdef | funcdef) - def class_decorator(x): - x.decorated = True - return x - @class_decorator - class G: - pass - self.assertEqual(G.decorated, True) - - def testListcomps(self): - # list comprehension tests - nums = [1, 2, 3, 4, 5] - strs = ["Apple", "Banana", "Coconut"] - spcs = [" Apple", " Banana ", "Coco nut "] - - self.assertEqual([s.strip() for s in spcs], ['Apple', 'Banana', 'Coco nut']) - self.assertEqual([3 * x for x in nums], [3, 6, 9, 12, 15]) - self.assertEqual([x for x in nums if x > 2], [3, 4, 5]) - self.assertEqual([(i, s) for i in nums for s in strs], - [(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), - (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), - (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), - (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), - (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]) - self.assertEqual([(i, s) for i in nums for s in [f for f in strs if "n" in f]], - [(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), - (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), - (5, 'Banana'), (5, 'Coconut')]) - self.assertEqual([(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)], - [[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]]) - - def test_in_func(l): - return [None < x < 3 for x in l if x > 2] - - self.assertEqual(test_in_func(nums), [False, False, False]) - - def test_nested_front(): - self.assertEqual([[y for y in [x, x + 1]] for x in [1,3,5]], - [[1, 2], [3, 4], [5, 6]]) - - test_nested_front() - - check_syntax_error(self, "[i, s for i in nums for s in strs]") - check_syntax_error(self, "[x if y]") - - suppliers = [ - (1, "Boeing"), - (2, "Ford"), - (3, "Macdonalds") - ] - - parts = [ - (10, "Airliner"), - (20, "Engine"), - (30, "Cheeseburger") - ] - - suppart = [ - (1, 10), (1, 20), (2, 20), (3, 30) - ] - - x = [ - (sname, pname) - for (sno, sname) in suppliers - for (pno, pname) in parts - for (sp_sno, sp_pno) in suppart - if sno == sp_sno and pno == sp_pno - ] - - self.assertEqual(x, [('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), - ('Macdonalds', 'Cheeseburger')]) - - def testGenexps(self): - # generator expression tests - g = ([x for x in range(10)] for x in range(1)) - self.assertEqual(g.next(), [x for x in range(10)]) - try: - g.next() - self.fail('should produce StopIteration exception') - except StopIteration: - pass - - a = 1 - try: - g = (a for d in a) - g.next() - self.fail('should produce TypeError') - except TypeError: - pass - - self.assertEqual(list((x, y) for x in 'abcd' for y in 'abcd'), [(x, y) for x in 'abcd' for y in 'abcd']) - self.assertEqual(list((x, y) for x in 'ab' for y in 'xy'), [(x, y) for x in 'ab' for y in 'xy']) - - a = [x for x in range(10)] - b = (x for x in (y for y in a)) - self.assertEqual(sum(b), sum([x for x in range(10)])) - - self.assertEqual(sum(x**2 for x in range(10)), sum([x**2 for x in range(10)])) - self.assertEqual(sum(x*x for x in range(10) if x%2), sum([x*x for x in range(10) if x%2])) - self.assertEqual(sum(x for x in (y for y in range(10))), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10)))), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in [y for y in (z for z in range(10))]), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True)) if True), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True) if False) if True), 0) - check_syntax_error(self, "foo(x for x in range(10), 100)") - check_syntax_error(self, "foo(100, x for x in range(10))") - - def testComprehensionSpecials(self): - # test for outmost iterable precomputation - x = 10; g = (i for i in range(x)); x = 5 - self.assertEqual(len(list(g)), 10) - - # This should hold, since we're only precomputing outmost iterable. - x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x)) - x = 5; t = True; - self.assertEqual([(i,j) for i in range(10) for j in range(5)], list(g)) - - # Grammar allows multiple adjacent 'if's in listcomps and genexps, - # even though it's silly. Make sure it works (ifelse broke this.) - self.assertEqual([ x for x in range(10) if x % 2 if x % 3 ], [1, 5, 7]) - self.assertEqual(list(x for x in range(10) if x % 2 if x % 3), [1, 5, 7]) - - # verify unpacking single element tuples in listcomp/genexp. - self.assertEqual([x for x, in [(4,), (5,), (6,)]], [4, 5, 6]) - self.assertEqual(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9]) - - def test_with_statement(self): - class manager(object): - def __enter__(self): - return (1, 2) - def __exit__(self, *args): - pass - - with manager(): - pass - with manager() as x: - pass - with manager() as (x, y): - pass - with manager(), manager(): - pass - with manager() as x, manager() as y: - pass - with manager() as x, manager(): - pass - - def testIfElseExpr(self): - # Test ifelse expressions in various cases - def _checkeval(msg, ret): - "helper to check that evaluation of expressions is done correctly" - print x - return ret - - self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True]) - self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True]) - self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True]) - self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5) - self.assertEqual((_checkeval("check 2", 0) if 0 else 5), 5) - self.assertEqual((5 and 6 if 0 else 1), 1) - self.assertEqual(((5 and 6) if 0 else 1), 1) - self.assertEqual((5 and (6 if 1 else 1)), 6) - self.assertEqual((0 or _checkeval("check 3", 2) if 0 else 3), 3) - self.assertEqual((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)), 1) - self.assertEqual((0 or 5 if 1 else _checkeval("check 6", 3)), 5) - self.assertEqual((not 5 if 1 else 1), False) - self.assertEqual((not 5 if 0 else 1), 1) - self.assertEqual((6 + 1 if 1 else 2), 7) - self.assertEqual((6 - 1 if 1 else 2), 5) - self.assertEqual((6 * 2 if 1 else 4), 12) - self.assertEqual((6 / 2 if 1 else 3), 3) - self.assertEqual((6 < 4 if 0 else 2), 2) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_lib2to3/data/py3_test_grammar.py b/Lib/test/test_lib2to3/data/py3_test_grammar.py deleted file mode 100644 index 774851f5bd7e85..00000000000000 --- a/Lib/test/test_lib2to3/data/py3_test_grammar.py +++ /dev/null @@ -1,956 +0,0 @@ -# Python test set -- part 1, grammar. -# This just tests whether the parser accepts them all. - -# NOTE: When you run this test as a script from the command line, you -# get warnings about certain hex/oct constants. Since those are -# issued by the parser, you can't suppress them by adding a -# filterwarnings() call to this module. Therefore, to shut up the -# regression test, the filterwarnings() call has been added to -# regrtest.py. - -from test.support import check_syntax_error -import unittest -import sys -# testing import * -from sys import * - -class TokenTests(unittest.TestCase): - - def testBackslash(self): - # Backslash means line continuation: - x = 1 \ - + 1 - self.assertEquals(x, 2, 'backslash for line continuation') - - # Backslash does not means continuation in comments :\ - x = 0 - self.assertEquals(x, 0, 'backslash ending comment') - - def testPlainIntegers(self): - self.assertEquals(type(000), type(0)) - self.assertEquals(0xff, 255) - self.assertEquals(0o377, 255) - self.assertEquals(2147483647, 0o17777777777) - self.assertEquals(0b1001, 9) - # "0x" is not a valid literal - self.assertRaises(SyntaxError, eval, "0x") - from sys import maxsize - if maxsize == 2147483647: - self.assertEquals(-2147483647-1, -0o20000000000) - # XXX -2147483648 - self.assert_(0o37777777777 > 0) - self.assert_(0xffffffff > 0) - self.assert_(0b1111111111111111111111111111111 > 0) - for s in ('2147483648', '0o40000000000', '0x100000000', - '0b10000000000000000000000000000000'): - try: - x = eval(s) - except OverflowError: - self.fail("OverflowError on huge integer literal %r" % s) - elif maxsize == 9223372036854775807: - self.assertEquals(-9223372036854775807-1, -0o1000000000000000000000) - self.assert_(0o1777777777777777777777 > 0) - self.assert_(0xffffffffffffffff > 0) - self.assert_(0b11111111111111111111111111111111111111111111111111111111111111 > 0) - for s in '9223372036854775808', '0o2000000000000000000000', \ - '0x10000000000000000', \ - '0b100000000000000000000000000000000000000000000000000000000000000': - try: - x = eval(s) - except OverflowError: - self.fail("OverflowError on huge integer literal %r" % s) - else: - self.fail('Weird maxsize value %r' % maxsize) - - def testLongIntegers(self): - x = 0 - x = 0xffffffffffffffff - x = 0Xffffffffffffffff - x = 0o77777777777777777 - x = 0O77777777777777777 - x = 123456789012345678901234567890 - x = 0b100000000000000000000000000000000000000000000000000000000000000000000 - x = 0B111111111111111111111111111111111111111111111111111111111111111111111 - - def testUnderscoresInNumbers(self): - # Integers - x = 1_0 - x = 123_456_7_89 - x = 0xabc_123_4_5 - x = 0X_abc_123 - x = 0B11_01 - x = 0b_11_01 - x = 0o45_67 - x = 0O_45_67 - - # Floats - x = 3_1.4 - x = 03_1.4 - x = 3_1. - x = .3_1 - x = 3.1_4 - x = 0_3.1_4 - x = 3e1_4 - x = 3_1e+4_1 - x = 3_1E-4_1 - - def testFloats(self): - x = 3.14 - x = 314. - x = 0.314 - # XXX x = 000.314 - x = .314 - x = 3e14 - x = 3E14 - x = 3e-14 - x = 3e+14 - x = 3.e14 - x = .3e14 - x = 3.1e4 - - def testStringLiterals(self): - x = ''; y = ""; self.assert_(len(x) == 0 and x == y) - x = '\''; y = "'"; self.assert_(len(x) == 1 and x == y and ord(x) == 39) - x = '"'; y = "\""; self.assert_(len(x) == 1 and x == y and ord(x) == 34) - x = "doesn't \"shrink\" does it" - y = 'doesn\'t "shrink" does it' - self.assert_(len(x) == 24 and x == y) - x = "does \"shrink\" doesn't it" - y = 'does "shrink" doesn\'t it' - self.assert_(len(x) == 24 and x == y) - x = """ -The "quick" -brown fox -jumps over -the 'lazy' dog. -""" - y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n' - self.assertEquals(x, y) - y = ''' -The "quick" -brown fox -jumps over -the 'lazy' dog. -''' - self.assertEquals(x, y) - y = "\n\ -The \"quick\"\n\ -brown fox\n\ -jumps over\n\ -the 'lazy' dog.\n\ -" - self.assertEquals(x, y) - y = '\n\ -The \"quick\"\n\ -brown fox\n\ -jumps over\n\ -the \'lazy\' dog.\n\ -' - self.assertEquals(x, y) - x = rf"hello \{True}"; y = f"hello \\{True}" - self.assertEquals(x, y) - - def testEllipsis(self): - x = ... - self.assert_(x is Ellipsis) - self.assertRaises(SyntaxError, eval, ".. .") - -class GrammarTests(unittest.TestCase): - - # single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE - # XXX can't test in a script -- this rule is only used when interactive - - # file_input: (NEWLINE | stmt)* ENDMARKER - # Being tested as this very moment this very module - - # expr_input: testlist NEWLINE - # XXX Hard to test -- used only in calls to input() - - def testEvalInput(self): - # testlist ENDMARKER - x = eval('1, 0 or 1') - - def testFuncdef(self): - ### [decorators] 'def' NAME parameters ['->' test] ':' suite - ### decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE - ### decorators: decorator+ - ### parameters: '(' [typedargslist] ')' - ### typedargslist: ((tfpdef ['=' test] ',')* - ### ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef) - ### | tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) - ### tfpdef: NAME [':' test] - ### varargslist: ((vfpdef ['=' test] ',')* - ### ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) - ### | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) - ### vfpdef: NAME - def f1(): pass - f1() - f1(*()) - f1(*(), **{}) - def f2(one_argument): pass - def f3(two, arguments): pass - self.assertEquals(f2.__code__.co_varnames, ('one_argument',)) - self.assertEquals(f3.__code__.co_varnames, ('two', 'arguments')) - def a1(one_arg,): pass - def a2(two, args,): pass - def v0(*rest): pass - def v1(a, *rest): pass - def v2(a, b, *rest): pass - - f1() - f2(1) - f2(1,) - f3(1, 2) - f3(1, 2,) - v0() - v0(1) - v0(1,) - v0(1,2) - v0(1,2,3,4,5,6,7,8,9,0) - v1(1) - v1(1,) - v1(1,2) - v1(1,2,3) - v1(1,2,3,4,5,6,7,8,9,0) - v2(1,2) - v2(1,2,3) - v2(1,2,3,4) - v2(1,2,3,4,5,6,7,8,9,0) - - def d01(a=1): pass - d01() - d01(1) - d01(*(1,)) - d01(**{'a':2}) - def d11(a, b=1): pass - d11(1) - d11(1, 2) - d11(1, **{'b':2}) - def d21(a, b, c=1): pass - d21(1, 2) - d21(1, 2, 3) - d21(*(1, 2, 3)) - d21(1, *(2, 3)) - d21(1, 2, *(3,)) - d21(1, 2, **{'c':3}) - def d02(a=1, b=2): pass - d02() - d02(1) - d02(1, 2) - d02(*(1, 2)) - d02(1, *(2,)) - d02(1, **{'b':2}) - d02(**{'a': 1, 'b': 2}) - def d12(a, b=1, c=2): pass - d12(1) - d12(1, 2) - d12(1, 2, 3) - def d22(a, b, c=1, d=2): pass - d22(1, 2) - d22(1, 2, 3) - d22(1, 2, 3, 4) - def d01v(a=1, *rest): pass - d01v() - d01v(1) - d01v(1, 2) - d01v(*(1, 2, 3, 4)) - d01v(*(1,)) - d01v(**{'a':2}) - def d11v(a, b=1, *rest): pass - d11v(1) - d11v(1, 2) - d11v(1, 2, 3) - def d21v(a, b, c=1, *rest): pass - d21v(1, 2) - d21v(1, 2, 3) - d21v(1, 2, 3, 4) - d21v(*(1, 2, 3, 4)) - d21v(1, 2, **{'c': 3}) - def d02v(a=1, b=2, *rest): pass - d02v() - d02v(1) - d02v(1, 2) - d02v(1, 2, 3) - d02v(1, *(2, 3, 4)) - d02v(**{'a': 1, 'b': 2}) - def d12v(a, b=1, c=2, *rest): pass - d12v(1) - d12v(1, 2) - d12v(1, 2, 3) - d12v(1, 2, 3, 4) - d12v(*(1, 2, 3, 4)) - d12v(1, 2, *(3, 4, 5)) - d12v(1, *(2,), **{'c': 3}) - def d22v(a, b, c=1, d=2, *rest): pass - d22v(1, 2) - d22v(1, 2, 3) - d22v(1, 2, 3, 4) - d22v(1, 2, 3, 4, 5) - d22v(*(1, 2, 3, 4)) - d22v(1, 2, *(3, 4, 5)) - d22v(1, *(2, 3), **{'d': 4}) - - # keyword argument type tests - try: - str('x', **{b'foo':1 }) - except TypeError: - pass - else: - self.fail('Bytes should not work as keyword argument names') - # keyword only argument tests - def pos0key1(*, key): return key - pos0key1(key=100) - def pos2key2(p1, p2, *, k1, k2=100): return p1,p2,k1,k2 - pos2key2(1, 2, k1=100) - pos2key2(1, 2, k1=100, k2=200) - pos2key2(1, 2, k2=100, k1=200) - def pos2key2dict(p1, p2, *, k1=100, k2, **kwarg): return p1,p2,k1,k2,kwarg - pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200) - pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100) - - # keyword arguments after *arglist - def f(*args, **kwargs): - return args, kwargs - self.assertEquals(f(1, x=2, *[3, 4], y=5), ((1, 3, 4), - {'x':2, 'y':5})) - self.assertRaises(SyntaxError, eval, "f(1, *(2,3), 4)") - self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)") - - # argument annotation tests - def f(x) -> list: pass - self.assertEquals(f.__annotations__, {'return': list}) - def f(x:int): pass - self.assertEquals(f.__annotations__, {'x': int}) - def f(*x:str): pass - self.assertEquals(f.__annotations__, {'x': str}) - def f(**x:float): pass - self.assertEquals(f.__annotations__, {'x': float}) - def f(x, y:1+2): pass - self.assertEquals(f.__annotations__, {'y': 3}) - def f(a, b:1, c:2, d): pass - self.assertEquals(f.__annotations__, {'b': 1, 'c': 2}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6): pass - self.assertEquals(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6}) - def f(a, b:1, c:2, d, e:3=4, f=5, *g:6, h:7, i=8, j:9=10, - **k:11) -> 12: pass - self.assertEquals(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, - 'k': 11, 'return': 12}) - # Check for SF Bug #1697248 - mixing decorators and a return annotation - def null(x): return x - @null - def f(x) -> list: pass - self.assertEquals(f.__annotations__, {'return': list}) - - # test closures with a variety of oparg's - closure = 1 - def f(): return closure - def f(x=1): return closure - def f(*, k=1): return closure - def f() -> int: return closure - - # Check ast errors in *args and *kwargs - check_syntax_error(self, "f(*g(1=2))") - check_syntax_error(self, "f(**g(1=2))") - - def testLambdef(self): - ### lambdef: 'lambda' [varargslist] ':' test - l1 = lambda : 0 - self.assertEquals(l1(), 0) - l2 = lambda : a[d] # XXX just testing the expression - l3 = lambda : [2 < x for x in [-1, 3, 0]] - self.assertEquals(l3(), [0, 1, 0]) - l4 = lambda x = lambda y = lambda z=1 : z : y() : x() - self.assertEquals(l4(), 1) - l5 = lambda x, y, z=2: x + y + z - self.assertEquals(l5(1, 2), 5) - self.assertEquals(l5(1, 2, 3), 6) - check_syntax_error(self, "lambda x: x = 2") - check_syntax_error(self, "lambda (None,): None") - l6 = lambda x, y, *, k=20: x+y+k - self.assertEquals(l6(1,2), 1+2+20) - self.assertEquals(l6(1,2,k=10), 1+2+10) - - - ### stmt: simple_stmt | compound_stmt - # Tested below - - def testSimpleStmt(self): - ### simple_stmt: small_stmt (';' small_stmt)* [';'] - x = 1; pass; del x - def foo(): - # verify statements that end with semi-colons - x = 1; pass; del x; - foo() - - ### small_stmt: expr_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt - # Tested below - - def testExprStmt(self): - # (exprlist '=')* exprlist - 1 - 1, 2, 3 - x = 1 - x = 1, 2, 3 - x = y = z = 1, 2, 3 - x, y, z = 1, 2, 3 - abc = a, b, c = x, y, z = xyz = 1, 2, (3, 4) - - check_syntax_error(self, "x + 1 = 1") - check_syntax_error(self, "a + 1 = b + 2") - - def testDelStmt(self): - # 'del' exprlist - abc = [1,2,3] - x, y, z = abc - xyz = x, y, z - - del abc - del x, y, (z, xyz) - - def testPassStmt(self): - # 'pass' - pass - - # flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt - # Tested below - - def testBreakStmt(self): - # 'break' - while 1: break - - def testContinueStmt(self): - # 'continue' - i = 1 - while i: i = 0; continue - - msg = "" - while not msg: - msg = "ok" - try: - continue - msg = "continue failed to continue inside try" - except: - msg = "continue inside try called except block" - if msg != "ok": - self.fail(msg) - - msg = "" - while not msg: - msg = "finally block not called" - try: - continue - finally: - msg = "ok" - if msg != "ok": - self.fail(msg) - - def test_break_continue_loop(self): - # This test warrants an explanation. It is a test specifically for SF bugs - # #463359 and #462937. The bug is that a 'break' statement executed or - # exception raised inside a try/except inside a loop, *after* a continue - # statement has been executed in that loop, will cause the wrong number of - # arguments to be popped off the stack and the instruction pointer reset to - # a very small number (usually 0.) Because of this, the following test - # *must* written as a function, and the tracking vars *must* be function - # arguments with default values. Otherwise, the test will loop and loop. - - def test_inner(extra_burning_oil = 1, count=0): - big_hippo = 2 - while big_hippo: - count += 1 - try: - if extra_burning_oil and big_hippo == 1: - extra_burning_oil -= 1 - break - big_hippo -= 1 - continue - except: - raise - if count > 2 or big_hippo != 1: - self.fail("continue then break in try/except in loop broken!") - test_inner() - - def testReturn(self): - # 'return' [testlist_star_expr] - def g1(): return - def g2(): return 1 - return_list = [2, 3] - def g3(): return 1, *return_list - g1() - x = g2() - x3 = g3() - check_syntax_error(self, "class foo:return 1") - - def testYield(self): - # 'yield' [yield_arg] - def g1(): yield 1 - yield_list = [2, 3] - def g2(): yield 1, *yield_list - def g3(): yield from iter(yield_list) - x1 = g1() - x2 = g2() - x3 = g3() - check_syntax_error(self, "class foo:yield 1") - check_syntax_error(self, "def g4(): yield from *a") - - def testRaise(self): - # 'raise' test [',' test] - try: raise RuntimeError('just testing') - except RuntimeError: pass - try: raise KeyboardInterrupt - except KeyboardInterrupt: pass - - def testImport(self): - # 'import' dotted_as_names - import sys - import time, sys - # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names) - from time import time - from time import (time) - # not testable inside a function, but already done at top of the module - # from sys import * - from sys import path, argv - from sys import (path, argv) - from sys import (path, argv,) - - def testGlobal(self): - # 'global' NAME (',' NAME)* - global a - global a, b - global one, two, three, four, five, six, seven, eight, nine, ten - - def testNonlocal(self): - # 'nonlocal' NAME (',' NAME)* - x = 0 - y = 0 - def f(): - nonlocal x - nonlocal x, y - - def testAssert(self): - # assert_stmt: 'assert' test [',' test] - assert 1 - assert 1, 1 - assert lambda x:x - assert 1, lambda x:x+1 - try: - assert 0, "msg" - except AssertionError as e: - self.assertEquals(e.args[0], "msg") - else: - if __debug__: - self.fail("AssertionError not raised by assert 0") - - ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef - # Tested below - - def testIf(self): - # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] - if 1: pass - if 1: pass - else: pass - if 0: pass - elif 0: pass - if 0: pass - elif 0: pass - elif 0: pass - elif 0: pass - else: pass - - def testWhile(self): - # 'while' test ':' suite ['else' ':' suite] - while 0: pass - while 0: pass - else: pass - - # Issue1920: "while 0" is optimized away, - # ensure that the "else" clause is still present. - x = 0 - while 0: - x = 1 - else: - x = 2 - self.assertEquals(x, 2) - - def testFor(self): - # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] - for i in 1, 2, 3: pass - for i, j, k in (): pass - else: pass - class Squares: - def __init__(self, max): - self.max = max - self.sofar = [] - def __len__(self): return len(self.sofar) - def __getitem__(self, i): - if not 0 <= i < self.max: raise IndexError - n = len(self.sofar) - while n <= i: - self.sofar.append(n*n) - n = n+1 - return self.sofar[i] - n = 0 - for x in Squares(10): n = n+x - if n != 285: - self.fail('for over growing sequence') - - result = [] - for x, in [(1,), (2,), (3,)]: - result.append(x) - self.assertEqual(result, [1, 2, 3]) - - def testTry(self): - ### try_stmt: 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite] - ### | 'try' ':' suite 'finally' ':' suite - ### except_clause: 'except' [expr ['as' expr]] - try: - 1/0 - except ZeroDivisionError: - pass - else: - pass - try: 1/0 - except EOFError: pass - except TypeError as msg: pass - except RuntimeError as msg: pass - except: pass - else: pass - try: 1/0 - except (EOFError, TypeError, ZeroDivisionError): pass - try: 1/0 - except (EOFError, TypeError, ZeroDivisionError) as msg: pass - try: pass - finally: pass - - def testSuite(self): - # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT - if 1: pass - if 1: - pass - if 1: - # - # - # - pass - pass - # - pass - # - - def testTest(self): - ### and_test ('or' and_test)* - ### and_test: not_test ('and' not_test)* - ### not_test: 'not' not_test | comparison - if not 1: pass - if 1 and 1: pass - if 1 or 1: pass - if not not not 1: pass - if not 1 and 1 and 1: pass - if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass - - def testComparison(self): - ### comparison: expr (comp_op expr)* - ### comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'in'|'not' 'in'|'is'|'is' 'not' - if 1: pass - x = (1 == 1) - if 1 == 1: pass - if 1 != 1: pass - if 1 < 1: pass - if 1 > 1: pass - if 1 <= 1: pass - if 1 >= 1: pass - if 1 is 1: pass - if 1 is not 1: pass - if 1 in (): pass - if 1 not in (): pass - if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in 1 is 1 is not 1: pass - - def testBinaryMaskOps(self): - x = 1 & 1 - x = 1 ^ 1 - x = 1 | 1 - - def testShiftOps(self): - x = 1 << 1 - x = 1 >> 1 - x = 1 << 1 >> 1 - - def testAdditiveOps(self): - x = 1 - x = 1 + 1 - x = 1 - 1 - 1 - x = 1 - 1 + 1 - 1 + 1 - - def testMultiplicativeOps(self): - x = 1 * 1 - x = 1 / 1 - x = 1 % 1 - x = 1 / 1 * 1 % 1 - - def testUnaryOps(self): - x = +1 - x = -1 - x = ~1 - x = ~1 ^ 1 & 1 | 1 & 1 ^ -1 - x = -1*1/1 + 1*1 - ---1*1 - - def testSelectors(self): - ### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME - ### subscript: expr | [expr] ':' [expr] - - import sys, time - c = sys.path[0] - x = time.time() - x = sys.modules['time'].time() - a = '01234' - c = a[0] - c = a[-1] - s = a[0:5] - s = a[:5] - s = a[0:] - s = a[:] - s = a[-5:] - s = a[:-1] - s = a[-4:-3] - # A rough test of SF bug 1333982. https://bugs.python.org/issue1333982 - # The testing here is fairly incomplete. - # Test cases should include: commas with 1 and 2 colons - d = {} - d[1] = 1 - d[1,] = 2 - d[1,2] = 3 - d[1,2,3] = 4 - L = list(d) - L.sort(key=lambda x: x if isinstance(x, tuple) else ()) - self.assertEquals(str(L), '[1, (1,), (1, 2), (1, 2, 3)]') - - def testAtoms(self): - ### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictsetmaker] '}' | NAME | NUMBER | STRING - ### dictsetmaker: (test ':' test (',' test ':' test)* [',']) | (test (',' test)* [',']) - - x = (1) - x = (1 or 2 or 3) - x = (1 or 2 or 3, 2, 3) - - x = [] - x = [1] - x = [1 or 2 or 3] - x = [1 or 2 or 3, 2, 3] - x = [] - - x = {} - x = {'one': 1} - x = {'one': 1,} - x = {'one' or 'two': 1 or 2} - x = {'one': 1, 'two': 2} - x = {'one': 1, 'two': 2,} - x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6} - - x = {'one'} - x = {'one', 1,} - x = {'one', 'two', 'three'} - x = {2, 3, 4,} - - x = x - x = 'x' - x = 123 - - ### exprlist: expr (',' expr)* [','] - ### testlist: test (',' test)* [','] - # These have been exercised enough above - - def testClassdef(self): - # 'class' NAME ['(' [testlist] ')'] ':' suite - class B: pass - class B2(): pass - class C1(B): pass - class C2(B): pass - class D(C1, C2, B): pass - class C: - def meth1(self): pass - def meth2(self, arg): pass - def meth3(self, a1, a2): pass - - # decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE - # decorators: decorator+ - # decorated: decorators (classdef | funcdef) - def class_decorator(x): return x - @class_decorator - class G: pass - - def testDictcomps(self): - # dictorsetmaker: ( (test ':' test (comp_for | - # (',' test ':' test)* [','])) | - # (test (comp_for | (',' test)* [','])) ) - nums = [1, 2, 3] - self.assertEqual({i:i+1 for i in nums}, {1: 2, 2: 3, 3: 4}) - - def testListcomps(self): - # list comprehension tests - nums = [1, 2, 3, 4, 5] - strs = ["Apple", "Banana", "Coconut"] - spcs = [" Apple", " Banana ", "Coco nut "] - - self.assertEqual([s.strip() for s in spcs], ['Apple', 'Banana', 'Coco nut']) - self.assertEqual([3 * x for x in nums], [3, 6, 9, 12, 15]) - self.assertEqual([x for x in nums if x > 2], [3, 4, 5]) - self.assertEqual([(i, s) for i in nums for s in strs], - [(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), - (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), - (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), - (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), - (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]) - self.assertEqual([(i, s) for i in nums for s in [f for f in strs if "n" in f]], - [(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), - (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), - (5, 'Banana'), (5, 'Coconut')]) - self.assertEqual([(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)], - [[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]]) - - def test_in_func(l): - return [0 < x < 3 for x in l if x > 2] - - self.assertEqual(test_in_func(nums), [False, False, False]) - - def test_nested_front(): - self.assertEqual([[y for y in [x, x + 1]] for x in [1,3,5]], - [[1, 2], [3, 4], [5, 6]]) - - test_nested_front() - - check_syntax_error(self, "[i, s for i in nums for s in strs]") - check_syntax_error(self, "[x if y]") - - suppliers = [ - (1, "Boeing"), - (2, "Ford"), - (3, "Macdonalds") - ] - - parts = [ - (10, "Airliner"), - (20, "Engine"), - (30, "Cheeseburger") - ] - - suppart = [ - (1, 10), (1, 20), (2, 20), (3, 30) - ] - - x = [ - (sname, pname) - for (sno, sname) in suppliers - for (pno, pname) in parts - for (sp_sno, sp_pno) in suppart - if sno == sp_sno and pno == sp_pno - ] - - self.assertEqual(x, [('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), - ('Macdonalds', 'Cheeseburger')]) - - def testGenexps(self): - # generator expression tests - g = ([x for x in range(10)] for x in range(1)) - self.assertEqual(next(g), [x for x in range(10)]) - try: - next(g) - self.fail('should produce StopIteration exception') - except StopIteration: - pass - - a = 1 - try: - g = (a for d in a) - next(g) - self.fail('should produce TypeError') - except TypeError: - pass - - self.assertEqual(list((x, y) for x in 'abcd' for y in 'abcd'), [(x, y) for x in 'abcd' for y in 'abcd']) - self.assertEqual(list((x, y) for x in 'ab' for y in 'xy'), [(x, y) for x in 'ab' for y in 'xy']) - - a = [x for x in range(10)] - b = (x for x in (y for y in a)) - self.assertEqual(sum(b), sum([x for x in range(10)])) - - self.assertEqual(sum(x**2 for x in range(10)), sum([x**2 for x in range(10)])) - self.assertEqual(sum(x*x for x in range(10) if x%2), sum([x*x for x in range(10) if x%2])) - self.assertEqual(sum(x for x in (y for y in range(10))), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10)))), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in [y for y in (z for z in range(10))]), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True)) if True), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True) if False) if True), 0) - check_syntax_error(self, "foo(x for x in range(10), 100)") - check_syntax_error(self, "foo(100, x for x in range(10))") - - def testComprehensionSpecials(self): - # test for outmost iterable precomputation - x = 10; g = (i for i in range(x)); x = 5 - self.assertEqual(len(list(g)), 10) - - # This should hold, since we're only precomputing outmost iterable. - x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x)) - x = 5; t = True; - self.assertEqual([(i,j) for i in range(10) for j in range(5)], list(g)) - - # Grammar allows multiple adjacent 'if's in listcomps and genexps, - # even though it's silly. Make sure it works (ifelse broke this.) - self.assertEqual([ x for x in range(10) if x % 2 if x % 3 ], [1, 5, 7]) - self.assertEqual(list(x for x in range(10) if x % 2 if x % 3), [1, 5, 7]) - - # verify unpacking single element tuples in listcomp/genexp. - self.assertEqual([x for x, in [(4,), (5,), (6,)]], [4, 5, 6]) - self.assertEqual(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9]) - - def test_with_statement(self): - class manager(object): - def __enter__(self): - return (1, 2) - def __exit__(self, *args): - pass - - with manager(): - pass - with manager() as x: - pass - with manager() as (x, y): - pass - with manager(), manager(): - pass - with manager() as x, manager() as y: - pass - with manager() as x, manager(): - pass - - def testIfElseExpr(self): - # Test ifelse expressions in various cases - def _checkeval(msg, ret): - "helper to check that evaluation of expressions is done correctly" - print(x) - return ret - - # the next line is not allowed anymore - #self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True]) - self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True]) - self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True]) - self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5) - self.assertEqual((_checkeval("check 2", 0) if 0 else 5), 5) - self.assertEqual((5 and 6 if 0 else 1), 1) - self.assertEqual(((5 and 6) if 0 else 1), 1) - self.assertEqual((5 and (6 if 1 else 1)), 6) - self.assertEqual((0 or _checkeval("check 3", 2) if 0 else 3), 3) - self.assertEqual((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)), 1) - self.assertEqual((0 or 5 if 1 else _checkeval("check 6", 3)), 5) - self.assertEqual((not 5 if 1 else 1), False) - self.assertEqual((not 5 if 0 else 1), 1) - self.assertEqual((6 + 1 if 1 else 2), 7) - self.assertEqual((6 - 1 if 1 else 2), 5) - self.assertEqual((6 * 2 if 1 else 4), 12) - self.assertEqual((6 / 2 if 1 else 3), 3) - self.assertEqual((6 < 4 if 0 else 2), 2) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_lib2to3/pytree_idempotency.py b/Lib/test/test_lib2to3/pytree_idempotency.py deleted file mode 100755 index eb2e2aa02ae0ed..00000000000000 --- a/Lib/test/test_lib2to3/pytree_idempotency.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Main program for testing the infrastructure.""" - -from __future__ import print_function - -__author__ = "Guido van Rossum " - -# Support imports (need to be imported first) -from . import support - -# Python imports -import os -import sys -import logging - -# Local imports -from lib2to3 import pytree -from lib2to3 import pgen2 -from lib2to3.pgen2 import driver - -logging.basicConfig() - -def main(): - gr = driver.load_grammar("Grammar.txt") - dr = driver.Driver(gr, convert=pytree.convert) - - fn = "example.py" - tree = dr.parse_file(fn, debug=True) - if not diff(fn, tree): - print("No diffs.") - if not sys.argv[1:]: - return # Pass a dummy argument to run the complete test suite below - - problems = [] - - # Process every imported module - for name in sys.modules: - mod = sys.modules[name] - if mod is None or not hasattr(mod, "__file__"): - continue - fn = mod.__file__ - if fn.endswith(".pyc"): - fn = fn[:-1] - if not fn.endswith(".py"): - continue - print("Parsing", fn, file=sys.stderr) - tree = dr.parse_file(fn, debug=True) - if diff(fn, tree): - problems.append(fn) - - # Process every single module on sys.path (but not in packages) - for dir in sys.path: - try: - names = os.listdir(dir) - except OSError: - continue - print("Scanning", dir, "...", file=sys.stderr) - for name in names: - if not name.endswith(".py"): - continue - print("Parsing", name, file=sys.stderr) - fn = os.path.join(dir, name) - try: - tree = dr.parse_file(fn, debug=True) - except pgen2.parse.ParseError as err: - print("ParseError:", err) - else: - if diff(fn, tree): - problems.append(fn) - - # Show summary of problem files - if not problems: - print("No problems. Congratulations!") - else: - print("Problems in following files:") - for fn in problems: - print("***", fn) - -def diff(fn, tree): - f = open("@", "w") - try: - f.write(str(tree)) - finally: - f.close() - try: - return os.system("diff -u %s @" % fn) - finally: - os.remove("@") - -if __name__ == "__main__": - main() diff --git a/Lib/test/test_lib2to3/support.py b/Lib/test/test_lib2to3/support.py deleted file mode 100644 index 9e56273e95992b..00000000000000 --- a/Lib/test/test_lib2to3/support.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Support code for test_*.py files""" -# Author: Collin Winter - -# Python imports -import unittest -import os -import os.path -from textwrap import dedent - -# Local imports -import lib2to3 -from lib2to3 import pytree, refactor -from lib2to3.pgen2 import driver as pgen2_driver - -lib2to3_dir = os.path.dirname(lib2to3.__file__) -test_dir = os.path.dirname(__file__) -proj_dir = os.path.normpath(os.path.join(test_dir, "..")) -grammar_path = os.path.join(lib2to3_dir, "Grammar.txt") -grammar = pgen2_driver.load_grammar(grammar_path) -grammar_no_print_statement = pgen2_driver.load_grammar(grammar_path) -del grammar_no_print_statement.keywords["print"] -driver = pgen2_driver.Driver(grammar, convert=pytree.convert) -driver_no_print_statement = pgen2_driver.Driver( - grammar_no_print_statement, - convert=pytree.convert -) - -def parse_string(string): - return driver.parse_string(reformat(string), debug=True) - -def run_all_tests(test_mod=None, tests=None): - if tests is None: - tests = unittest.TestLoader().loadTestsFromModule(test_mod) - unittest.TextTestRunner(verbosity=2).run(tests) - -def reformat(string): - return dedent(string) + "\n\n" - -def get_refactorer(fixer_pkg="lib2to3", fixers=None, options=None): - """ - A convenience function for creating a RefactoringTool for tests. - - fixers is a list of fixers for the RefactoringTool to use. By default - "lib2to3.fixes.*" is used. options is an optional dictionary of options to - be passed to the RefactoringTool. - """ - if fixers is not None: - fixers = [fixer_pkg + ".fixes.fix_" + fix for fix in fixers] - else: - fixers = refactor.get_fixers_from_package(fixer_pkg + ".fixes") - options = options or {} - return refactor.RefactoringTool(fixers, options, explicit=True) - -def _all_project_files(root, files): - for dirpath, dirnames, filenames in os.walk(root): - for filename in filenames: - if not filename.endswith(".py"): - continue - files.append(os.path.join(dirpath, filename)) - -def all_project_files(): - files = [] - _all_project_files(lib2to3_dir, files) - _all_project_files(test_dir, files) - # Sort to get more reproducible tests - files.sort() - return files - -TestCase = unittest.TestCase diff --git a/Lib/test/test_lib2to3/test_all_fixers.py b/Lib/test/test_lib2to3/test_all_fixers.py deleted file mode 100644 index d0fca7072482cb..00000000000000 --- a/Lib/test/test_lib2to3/test_all_fixers.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Tests that run all fixer modules over an input stream. - -This has been broken out into its own test module because of its -running time. -""" -# Author: Collin Winter - -# Python imports -import os.path -import test.support -import unittest - -# Local imports -from . import support - - -@test.support.requires_resource('cpu') -class Test_all(support.TestCase): - - def setUp(self): - self.refactor = support.get_refactorer() - - def refactor_file(self, filepath): - if test.support.verbose: - print(f"Refactor file: {filepath}") - if os.path.basename(filepath) == 'infinite_recursion.py': - # bpo-46542: Processing infinite_recursion.py can crash Python - # if Python is built in debug mode: lower the recursion limit - # to prevent a crash. - with test.support.infinite_recursion(150): - self.refactor.refactor_file(filepath) - else: - self.refactor.refactor_file(filepath) - - def test_all_project_files(self): - for filepath in support.all_project_files(): - with self.subTest(filepath=filepath): - self.refactor_file(filepath) - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_lib2to3/test_fixers.py b/Lib/test/test_lib2to3/test_fixers.py deleted file mode 100644 index 68efeee7abb4d5..00000000000000 --- a/Lib/test/test_lib2to3/test_fixers.py +++ /dev/null @@ -1,4649 +0,0 @@ -""" Test suite for the fixer modules """ - -# Python imports -import os -from itertools import chain -from operator import itemgetter - -# Local imports -from lib2to3 import pygram, fixer_util -from test.test_lib2to3 import support - - -class FixerTestCase(support.TestCase): - - # Other test cases can subclass this class and replace "fixer_pkg" with - # their own. - def setUp(self, fix_list=None, fixer_pkg="lib2to3", options=None): - if fix_list is None: - fix_list = [self.fixer] - self.refactor = support.get_refactorer(fixer_pkg, fix_list, options) - self.fixer_log = [] - self.filename = "" - - for fixer in chain(self.refactor.pre_order, - self.refactor.post_order): - fixer.log = self.fixer_log - - def _check(self, before, after): - before = support.reformat(before) - after = support.reformat(after) - tree = self.refactor.refactor_string(before, self.filename) - self.assertEqual(after, str(tree)) - return tree - - def check(self, before, after, ignore_warnings=False): - tree = self._check(before, after) - self.assertTrue(tree.was_changed) - if not ignore_warnings: - self.assertEqual(self.fixer_log, []) - - def warns(self, before, after, message, unchanged=False): - tree = self._check(before, after) - self.assertIn(message, "".join(self.fixer_log)) - if not unchanged: - self.assertTrue(tree.was_changed) - - def warns_unchanged(self, before, message): - self.warns(before, before, message, unchanged=True) - - def unchanged(self, before, ignore_warnings=False): - self._check(before, before) - if not ignore_warnings: - self.assertEqual(self.fixer_log, []) - - def assert_runs_after(self, *names): - fixes = [self.fixer] - fixes.extend(names) - r = support.get_refactorer("lib2to3", fixes) - (pre, post) = r.get_fixers() - n = "fix_" + self.fixer - if post and post[-1].__class__.__module__.endswith(n): - # We're the last fixer to run - return - if pre and pre[-1].__class__.__module__.endswith(n) and not post: - # We're the last in pre and post is empty - return - self.fail("Fixer run order (%s) is incorrect; %s should be last."\ - %(", ".join([x.__class__.__module__ for x in (pre+post)]), n)) - -class Test_ne(FixerTestCase): - fixer = "ne" - - def test_basic(self): - b = """if x <> y: - pass""" - - a = """if x != y: - pass""" - self.check(b, a) - - def test_no_spaces(self): - b = """if x<>y: - pass""" - - a = """if x!=y: - pass""" - self.check(b, a) - - def test_chained(self): - b = """if x<>y<>z: - pass""" - - a = """if x!=y!=z: - pass""" - self.check(b, a) - -class Test_has_key(FixerTestCase): - fixer = "has_key" - - def test_1(self): - b = """x = d.has_key("x") or d.has_key("y")""" - a = """x = "x" in d or "y" in d""" - self.check(b, a) - - def test_2(self): - b = """x = a.b.c.d.has_key("x") ** 3""" - a = """x = ("x" in a.b.c.d) ** 3""" - self.check(b, a) - - def test_3(self): - b = """x = a.b.has_key(1 + 2).__repr__()""" - a = """x = (1 + 2 in a.b).__repr__()""" - self.check(b, a) - - def test_4(self): - b = """x = a.b.has_key(1 + 2).__repr__() ** -3 ** 4""" - a = """x = (1 + 2 in a.b).__repr__() ** -3 ** 4""" - self.check(b, a) - - def test_5(self): - b = """x = a.has_key(f or g)""" - a = """x = (f or g) in a""" - self.check(b, a) - - def test_6(self): - b = """x = a + b.has_key(c)""" - a = """x = a + (c in b)""" - self.check(b, a) - - def test_7(self): - b = """x = a.has_key(lambda: 12)""" - a = """x = (lambda: 12) in a""" - self.check(b, a) - - def test_8(self): - b = """x = a.has_key(a for a in b)""" - a = """x = (a for a in b) in a""" - self.check(b, a) - - def test_9(self): - b = """if not a.has_key(b): pass""" - a = """if b not in a: pass""" - self.check(b, a) - - def test_10(self): - b = """if not a.has_key(b).__repr__(): pass""" - a = """if not (b in a).__repr__(): pass""" - self.check(b, a) - - def test_11(self): - b = """if not a.has_key(b) ** 2: pass""" - a = """if not (b in a) ** 2: pass""" - self.check(b, a) - -class Test_apply(FixerTestCase): - fixer = "apply" - - def test_1(self): - b = """x = apply(f, g + h)""" - a = """x = f(*g + h)""" - self.check(b, a) - - def test_2(self): - b = """y = apply(f, g, h)""" - a = """y = f(*g, **h)""" - self.check(b, a) - - def test_3(self): - b = """z = apply(fs[0], g or h, h or g)""" - a = """z = fs[0](*g or h, **h or g)""" - self.check(b, a) - - def test_4(self): - b = """apply(f, (x, y) + t)""" - a = """f(*(x, y) + t)""" - self.check(b, a) - - def test_5(self): - b = """apply(f, args,)""" - a = """f(*args)""" - self.check(b, a) - - def test_6(self): - b = """apply(f, args, kwds,)""" - a = """f(*args, **kwds)""" - self.check(b, a) - - # Test that complex functions are parenthesized - - def test_complex_1(self): - b = """x = apply(f+g, args)""" - a = """x = (f+g)(*args)""" - self.check(b, a) - - def test_complex_2(self): - b = """x = apply(f*g, args)""" - a = """x = (f*g)(*args)""" - self.check(b, a) - - def test_complex_3(self): - b = """x = apply(f**g, args)""" - a = """x = (f**g)(*args)""" - self.check(b, a) - - # But dotted names etc. not - - def test_dotted_name(self): - b = """x = apply(f.g, args)""" - a = """x = f.g(*args)""" - self.check(b, a) - - def test_subscript(self): - b = """x = apply(f[x], args)""" - a = """x = f[x](*args)""" - self.check(b, a) - - def test_call(self): - b = """x = apply(f(), args)""" - a = """x = f()(*args)""" - self.check(b, a) - - # Extreme case - def test_extreme(self): - b = """x = apply(a.b.c.d.e.f, args, kwds)""" - a = """x = a.b.c.d.e.f(*args, **kwds)""" - self.check(b, a) - - # XXX Comments in weird places still get lost - def test_weird_comments(self): - b = """apply( # foo - f, # bar - args)""" - a = """f(*args)""" - self.check(b, a) - - # These should *not* be touched - - def test_unchanged_1(self): - s = """apply()""" - self.unchanged(s) - - def test_unchanged_2(self): - s = """apply(f)""" - self.unchanged(s) - - def test_unchanged_3(self): - s = """apply(f,)""" - self.unchanged(s) - - def test_unchanged_4(self): - s = """apply(f, args, kwds, extras)""" - self.unchanged(s) - - def test_unchanged_5(self): - s = """apply(f, *args, **kwds)""" - self.unchanged(s) - - def test_unchanged_6(self): - s = """apply(f, *args)""" - self.unchanged(s) - - def test_unchanged_6b(self): - s = """apply(f, **kwds)""" - self.unchanged(s) - - def test_unchanged_7(self): - s = """apply(func=f, args=args, kwds=kwds)""" - self.unchanged(s) - - def test_unchanged_8(self): - s = """apply(f, args=args, kwds=kwds)""" - self.unchanged(s) - - def test_unchanged_9(self): - s = """apply(f, args, kwds=kwds)""" - self.unchanged(s) - - def test_space_1(self): - a = """apply( f, args, kwds)""" - b = """f(*args, **kwds)""" - self.check(a, b) - - def test_space_2(self): - a = """apply( f ,args,kwds )""" - b = """f(*args, **kwds)""" - self.check(a, b) - -class Test_reload(FixerTestCase): - fixer = "reload" - - def test(self): - b = """reload(a)""" - a = """import importlib\nimportlib.reload(a)""" - self.check(b, a) - - def test_comment(self): - b = """reload( a ) # comment""" - a = """import importlib\nimportlib.reload( a ) # comment""" - self.check(b, a) - - # PEP 8 comments - b = """reload( a ) # comment""" - a = """import importlib\nimportlib.reload( a ) # comment""" - self.check(b, a) - - def test_space(self): - b = """reload( a )""" - a = """import importlib\nimportlib.reload( a )""" - self.check(b, a) - - b = """reload( a)""" - a = """import importlib\nimportlib.reload( a)""" - self.check(b, a) - - b = """reload(a )""" - a = """import importlib\nimportlib.reload(a )""" - self.check(b, a) - - def test_unchanged(self): - s = """reload(a=1)""" - self.unchanged(s) - - s = """reload(f, g)""" - self.unchanged(s) - - s = """reload(f, *h)""" - self.unchanged(s) - - s = """reload(f, *h, **i)""" - self.unchanged(s) - - s = """reload(f, **i)""" - self.unchanged(s) - - s = """reload(*h, **i)""" - self.unchanged(s) - - s = """reload(*h)""" - self.unchanged(s) - - s = """reload(**i)""" - self.unchanged(s) - - s = """reload()""" - self.unchanged(s) - -class Test_intern(FixerTestCase): - fixer = "intern" - - def test_prefix_preservation(self): - b = """x = intern( a )""" - a = """import sys\nx = sys.intern( a )""" - self.check(b, a) - - b = """y = intern("b" # test - )""" - a = """import sys\ny = sys.intern("b" # test - )""" - self.check(b, a) - - b = """z = intern(a+b+c.d, )""" - a = """import sys\nz = sys.intern(a+b+c.d, )""" - self.check(b, a) - - def test(self): - b = """x = intern(a)""" - a = """import sys\nx = sys.intern(a)""" - self.check(b, a) - - b = """z = intern(a+b+c.d,)""" - a = """import sys\nz = sys.intern(a+b+c.d,)""" - self.check(b, a) - - b = """intern("y%s" % 5).replace("y", "")""" - a = """import sys\nsys.intern("y%s" % 5).replace("y", "")""" - self.check(b, a) - - # These should not be refactored - - def test_unchanged(self): - s = """intern(a=1)""" - self.unchanged(s) - - s = """intern(f, g)""" - self.unchanged(s) - - s = """intern(*h)""" - self.unchanged(s) - - s = """intern(**i)""" - self.unchanged(s) - - s = """intern()""" - self.unchanged(s) - -class Test_reduce(FixerTestCase): - fixer = "reduce" - - def test_simple_call(self): - b = "reduce(a, b, c)" - a = "from functools import reduce\nreduce(a, b, c)" - self.check(b, a) - - def test_bug_7253(self): - # fix_tuple_params was being bad and orphaning nodes in the tree. - b = "def x(arg): reduce(sum, [])" - a = "from functools import reduce\ndef x(arg): reduce(sum, [])" - self.check(b, a) - - def test_call_with_lambda(self): - b = "reduce(lambda x, y: x + y, seq)" - a = "from functools import reduce\nreduce(lambda x, y: x + y, seq)" - self.check(b, a) - - def test_unchanged(self): - s = "reduce(a)" - self.unchanged(s) - - s = "reduce(a, b=42)" - self.unchanged(s) - - s = "reduce(a, b, c, d)" - self.unchanged(s) - - s = "reduce(**c)" - self.unchanged(s) - - s = "reduce()" - self.unchanged(s) - -class Test_print(FixerTestCase): - fixer = "print" - - def test_prefix_preservation(self): - b = """print 1, 1+1, 1+1+1""" - a = """print(1, 1+1, 1+1+1)""" - self.check(b, a) - - def test_idempotency(self): - s = """print()""" - self.unchanged(s) - - s = """print('')""" - self.unchanged(s) - - def test_idempotency_print_as_function(self): - self.refactor.driver.grammar = pygram.python_grammar_no_print_statement - s = """print(1, 1+1, 1+1+1)""" - self.unchanged(s) - - s = """print()""" - self.unchanged(s) - - s = """print('')""" - self.unchanged(s) - - def test_1(self): - b = """print 1, 1+1, 1+1+1""" - a = """print(1, 1+1, 1+1+1)""" - self.check(b, a) - - def test_2(self): - b = """print 1, 2""" - a = """print(1, 2)""" - self.check(b, a) - - def test_3(self): - b = """print""" - a = """print()""" - self.check(b, a) - - def test_4(self): - # from bug 3000 - b = """print whatever; print""" - a = """print(whatever); print()""" - self.check(b, a) - - def test_5(self): - b = """print; print whatever;""" - a = """print(); print(whatever);""" - self.check(b, a) - - def test_tuple(self): - b = """print (a, b, c)""" - a = """print((a, b, c))""" - self.check(b, a) - - # trailing commas - - def test_trailing_comma_1(self): - b = """print 1, 2, 3,""" - a = """print(1, 2, 3, end=' ')""" - self.check(b, a) - - def test_trailing_comma_2(self): - b = """print 1, 2,""" - a = """print(1, 2, end=' ')""" - self.check(b, a) - - def test_trailing_comma_3(self): - b = """print 1,""" - a = """print(1, end=' ')""" - self.check(b, a) - - # >> stuff - - def test_vargs_without_trailing_comma(self): - b = """print >>sys.stderr, 1, 2, 3""" - a = """print(1, 2, 3, file=sys.stderr)""" - self.check(b, a) - - def test_with_trailing_comma(self): - b = """print >>sys.stderr, 1, 2,""" - a = """print(1, 2, end=' ', file=sys.stderr)""" - self.check(b, a) - - def test_no_trailing_comma(self): - b = """print >>sys.stderr, 1+1""" - a = """print(1+1, file=sys.stderr)""" - self.check(b, a) - - def test_spaces_before_file(self): - b = """print >> sys.stderr""" - a = """print(file=sys.stderr)""" - self.check(b, a) - - def test_with_future_print_function(self): - s = "from __future__ import print_function\n" \ - "print('Hai!', end=' ')" - self.unchanged(s) - - b = "print 'Hello, world!'" - a = "print('Hello, world!')" - self.check(b, a) - - -class Test_exec(FixerTestCase): - fixer = "exec" - - def test_prefix_preservation(self): - b = """ exec code in ns1, ns2""" - a = """ exec(code, ns1, ns2)""" - self.check(b, a) - - def test_basic(self): - b = """exec code""" - a = """exec(code)""" - self.check(b, a) - - def test_with_globals(self): - b = """exec code in ns""" - a = """exec(code, ns)""" - self.check(b, a) - - def test_with_globals_locals(self): - b = """exec code in ns1, ns2""" - a = """exec(code, ns1, ns2)""" - self.check(b, a) - - def test_complex_1(self): - b = """exec (a.b()) in ns""" - a = """exec((a.b()), ns)""" - self.check(b, a) - - def test_complex_2(self): - b = """exec a.b() + c in ns""" - a = """exec(a.b() + c, ns)""" - self.check(b, a) - - # These should not be touched - - def test_unchanged_1(self): - s = """exec(code)""" - self.unchanged(s) - - def test_unchanged_2(self): - s = """exec (code)""" - self.unchanged(s) - - def test_unchanged_3(self): - s = """exec(code, ns)""" - self.unchanged(s) - - def test_unchanged_4(self): - s = """exec(code, ns1, ns2)""" - self.unchanged(s) - -class Test_repr(FixerTestCase): - fixer = "repr" - - def test_prefix_preservation(self): - b = """x = `1 + 2`""" - a = """x = repr(1 + 2)""" - self.check(b, a) - - def test_simple_1(self): - b = """x = `1 + 2`""" - a = """x = repr(1 + 2)""" - self.check(b, a) - - def test_simple_2(self): - b = """y = `x`""" - a = """y = repr(x)""" - self.check(b, a) - - def test_complex(self): - b = """z = `y`.__repr__()""" - a = """z = repr(y).__repr__()""" - self.check(b, a) - - def test_tuple(self): - b = """x = `1, 2, 3`""" - a = """x = repr((1, 2, 3))""" - self.check(b, a) - - def test_nested(self): - b = """x = `1 + `2``""" - a = """x = repr(1 + repr(2))""" - self.check(b, a) - - def test_nested_tuples(self): - b = """x = `1, 2 + `3, 4``""" - a = """x = repr((1, 2 + repr((3, 4))))""" - self.check(b, a) - -class Test_except(FixerTestCase): - fixer = "except" - - def test_prefix_preservation(self): - b = """ - try: - pass - except (RuntimeError, ImportError), e: - pass""" - a = """ - try: - pass - except (RuntimeError, ImportError) as e: - pass""" - self.check(b, a) - - def test_simple(self): - b = """ - try: - pass - except Foo, e: - pass""" - a = """ - try: - pass - except Foo as e: - pass""" - self.check(b, a) - - def test_simple_no_space_before_target(self): - b = """ - try: - pass - except Foo,e: - pass""" - a = """ - try: - pass - except Foo as e: - pass""" - self.check(b, a) - - def test_tuple_unpack(self): - b = """ - def foo(): - try: - pass - except Exception, (f, e): - pass - except ImportError, e: - pass""" - - a = """ - def foo(): - try: - pass - except Exception as xxx_todo_changeme: - (f, e) = xxx_todo_changeme.args - pass - except ImportError as e: - pass""" - self.check(b, a) - - def test_multi_class(self): - b = """ - try: - pass - except (RuntimeError, ImportError), e: - pass""" - - a = """ - try: - pass - except (RuntimeError, ImportError) as e: - pass""" - self.check(b, a) - - def test_list_unpack(self): - b = """ - try: - pass - except Exception, [a, b]: - pass""" - - a = """ - try: - pass - except Exception as xxx_todo_changeme: - [a, b] = xxx_todo_changeme.args - pass""" - self.check(b, a) - - def test_weird_target_1(self): - b = """ - try: - pass - except Exception, d[5]: - pass""" - - a = """ - try: - pass - except Exception as xxx_todo_changeme: - d[5] = xxx_todo_changeme - pass""" - self.check(b, a) - - def test_weird_target_2(self): - b = """ - try: - pass - except Exception, a.foo: - pass""" - - a = """ - try: - pass - except Exception as xxx_todo_changeme: - a.foo = xxx_todo_changeme - pass""" - self.check(b, a) - - def test_weird_target_3(self): - b = """ - try: - pass - except Exception, a().foo: - pass""" - - a = """ - try: - pass - except Exception as xxx_todo_changeme: - a().foo = xxx_todo_changeme - pass""" - self.check(b, a) - - def test_bare_except(self): - b = """ - try: - pass - except Exception, a: - pass - except: - pass""" - - a = """ - try: - pass - except Exception as a: - pass - except: - pass""" - self.check(b, a) - - def test_bare_except_and_else_finally(self): - b = """ - try: - pass - except Exception, a: - pass - except: - pass - else: - pass - finally: - pass""" - - a = """ - try: - pass - except Exception as a: - pass - except: - pass - else: - pass - finally: - pass""" - self.check(b, a) - - def test_multi_fixed_excepts_before_bare_except(self): - b = """ - try: - pass - except TypeError, b: - pass - except Exception, a: - pass - except: - pass""" - - a = """ - try: - pass - except TypeError as b: - pass - except Exception as a: - pass - except: - pass""" - self.check(b, a) - - def test_one_line_suites(self): - b = """ - try: raise TypeError - except TypeError, e: - pass - """ - a = """ - try: raise TypeError - except TypeError as e: - pass - """ - self.check(b, a) - b = """ - try: - raise TypeError - except TypeError, e: pass - """ - a = """ - try: - raise TypeError - except TypeError as e: pass - """ - self.check(b, a) - b = """ - try: raise TypeError - except TypeError, e: pass - """ - a = """ - try: raise TypeError - except TypeError as e: pass - """ - self.check(b, a) - b = """ - try: raise TypeError - except TypeError, e: pass - else: function() - finally: done() - """ - a = """ - try: raise TypeError - except TypeError as e: pass - else: function() - finally: done() - """ - self.check(b, a) - - # These should not be touched: - - def test_unchanged_1(self): - s = """ - try: - pass - except: - pass""" - self.unchanged(s) - - def test_unchanged_2(self): - s = """ - try: - pass - except Exception: - pass""" - self.unchanged(s) - - def test_unchanged_3(self): - s = """ - try: - pass - except (Exception, SystemExit): - pass""" - self.unchanged(s) - -class Test_raise(FixerTestCase): - fixer = "raise" - - def test_basic(self): - b = """raise Exception, 5""" - a = """raise Exception(5)""" - self.check(b, a) - - def test_prefix_preservation(self): - b = """raise Exception,5""" - a = """raise Exception(5)""" - self.check(b, a) - - b = """raise Exception, 5""" - a = """raise Exception(5)""" - self.check(b, a) - - def test_with_comments(self): - b = """raise Exception, 5 # foo""" - a = """raise Exception(5) # foo""" - self.check(b, a) - - b = """raise E, (5, 6) % (a, b) # foo""" - a = """raise E((5, 6) % (a, b)) # foo""" - self.check(b, a) - - b = """def foo(): - raise Exception, 5, 6 # foo""" - a = """def foo(): - raise Exception(5).with_traceback(6) # foo""" - self.check(b, a) - - def test_None_value(self): - b = """raise Exception(5), None, tb""" - a = """raise Exception(5).with_traceback(tb)""" - self.check(b, a) - - def test_tuple_value(self): - b = """raise Exception, (5, 6, 7)""" - a = """raise Exception(5, 6, 7)""" - self.check(b, a) - - def test_tuple_detection(self): - b = """raise E, (5, 6) % (a, b)""" - a = """raise E((5, 6) % (a, b))""" - self.check(b, a) - - def test_tuple_exc_1(self): - b = """raise (((E1, E2), E3), E4), V""" - a = """raise E1(V)""" - self.check(b, a) - - def test_tuple_exc_2(self): - b = """raise (E1, (E2, E3), E4), V""" - a = """raise E1(V)""" - self.check(b, a) - - # These should produce a warning - - def test_string_exc(self): - s = """raise 'foo'""" - self.warns_unchanged(s, "Python 3 does not support string exceptions") - - def test_string_exc_val(self): - s = """raise "foo", 5""" - self.warns_unchanged(s, "Python 3 does not support string exceptions") - - def test_string_exc_val_tb(self): - s = """raise "foo", 5, 6""" - self.warns_unchanged(s, "Python 3 does not support string exceptions") - - # These should result in traceback-assignment - - def test_tb_1(self): - b = """def foo(): - raise Exception, 5, 6""" - a = """def foo(): - raise Exception(5).with_traceback(6)""" - self.check(b, a) - - def test_tb_2(self): - b = """def foo(): - a = 5 - raise Exception, 5, 6 - b = 6""" - a = """def foo(): - a = 5 - raise Exception(5).with_traceback(6) - b = 6""" - self.check(b, a) - - def test_tb_3(self): - b = """def foo(): - raise Exception,5,6""" - a = """def foo(): - raise Exception(5).with_traceback(6)""" - self.check(b, a) - - def test_tb_4(self): - b = """def foo(): - a = 5 - raise Exception,5,6 - b = 6""" - a = """def foo(): - a = 5 - raise Exception(5).with_traceback(6) - b = 6""" - self.check(b, a) - - def test_tb_5(self): - b = """def foo(): - raise Exception, (5, 6, 7), 6""" - a = """def foo(): - raise Exception(5, 6, 7).with_traceback(6)""" - self.check(b, a) - - def test_tb_6(self): - b = """def foo(): - a = 5 - raise Exception, (5, 6, 7), 6 - b = 6""" - a = """def foo(): - a = 5 - raise Exception(5, 6, 7).with_traceback(6) - b = 6""" - self.check(b, a) - -class Test_throw(FixerTestCase): - fixer = "throw" - - def test_1(self): - b = """g.throw(Exception, 5)""" - a = """g.throw(Exception(5))""" - self.check(b, a) - - def test_2(self): - b = """g.throw(Exception,5)""" - a = """g.throw(Exception(5))""" - self.check(b, a) - - def test_3(self): - b = """g.throw(Exception, (5, 6, 7))""" - a = """g.throw(Exception(5, 6, 7))""" - self.check(b, a) - - def test_4(self): - b = """5 + g.throw(Exception, 5)""" - a = """5 + g.throw(Exception(5))""" - self.check(b, a) - - # These should produce warnings - - def test_warn_1(self): - s = """g.throw("foo")""" - self.warns_unchanged(s, "Python 3 does not support string exceptions") - - def test_warn_2(self): - s = """g.throw("foo", 5)""" - self.warns_unchanged(s, "Python 3 does not support string exceptions") - - def test_warn_3(self): - s = """g.throw("foo", 5, 6)""" - self.warns_unchanged(s, "Python 3 does not support string exceptions") - - # These should not be touched - - def test_untouched_1(self): - s = """g.throw(Exception)""" - self.unchanged(s) - - def test_untouched_2(self): - s = """g.throw(Exception(5, 6))""" - self.unchanged(s) - - def test_untouched_3(self): - s = """5 + g.throw(Exception(5, 6))""" - self.unchanged(s) - - # These should result in traceback-assignment - - def test_tb_1(self): - b = """def foo(): - g.throw(Exception, 5, 6)""" - a = """def foo(): - g.throw(Exception(5).with_traceback(6))""" - self.check(b, a) - - def test_tb_2(self): - b = """def foo(): - a = 5 - g.throw(Exception, 5, 6) - b = 6""" - a = """def foo(): - a = 5 - g.throw(Exception(5).with_traceback(6)) - b = 6""" - self.check(b, a) - - def test_tb_3(self): - b = """def foo(): - g.throw(Exception,5,6)""" - a = """def foo(): - g.throw(Exception(5).with_traceback(6))""" - self.check(b, a) - - def test_tb_4(self): - b = """def foo(): - a = 5 - g.throw(Exception,5,6) - b = 6""" - a = """def foo(): - a = 5 - g.throw(Exception(5).with_traceback(6)) - b = 6""" - self.check(b, a) - - def test_tb_5(self): - b = """def foo(): - g.throw(Exception, (5, 6, 7), 6)""" - a = """def foo(): - g.throw(Exception(5, 6, 7).with_traceback(6))""" - self.check(b, a) - - def test_tb_6(self): - b = """def foo(): - a = 5 - g.throw(Exception, (5, 6, 7), 6) - b = 6""" - a = """def foo(): - a = 5 - g.throw(Exception(5, 6, 7).with_traceback(6)) - b = 6""" - self.check(b, a) - - def test_tb_7(self): - b = """def foo(): - a + g.throw(Exception, 5, 6)""" - a = """def foo(): - a + g.throw(Exception(5).with_traceback(6))""" - self.check(b, a) - - def test_tb_8(self): - b = """def foo(): - a = 5 - a + g.throw(Exception, 5, 6) - b = 6""" - a = """def foo(): - a = 5 - a + g.throw(Exception(5).with_traceback(6)) - b = 6""" - self.check(b, a) - -class Test_long(FixerTestCase): - fixer = "long" - - def test_1(self): - b = """x = long(x)""" - a = """x = int(x)""" - self.check(b, a) - - def test_2(self): - b = """y = isinstance(x, long)""" - a = """y = isinstance(x, int)""" - self.check(b, a) - - def test_3(self): - b = """z = type(x) in (int, long)""" - a = """z = type(x) in (int, int)""" - self.check(b, a) - - def test_unchanged(self): - s = """long = True""" - self.unchanged(s) - - s = """s.long = True""" - self.unchanged(s) - - s = """def long(): pass""" - self.unchanged(s) - - s = """class long(): pass""" - self.unchanged(s) - - s = """def f(long): pass""" - self.unchanged(s) - - s = """def f(g, long): pass""" - self.unchanged(s) - - s = """def f(x, long=True): pass""" - self.unchanged(s) - - def test_prefix_preservation(self): - b = """x = long( x )""" - a = """x = int( x )""" - self.check(b, a) - - -class Test_execfile(FixerTestCase): - fixer = "execfile" - - def test_conversion(self): - b = """execfile("fn")""" - a = """exec(compile(open("fn", "rb").read(), "fn", 'exec'))""" - self.check(b, a) - - b = """execfile("fn", glob)""" - a = """exec(compile(open("fn", "rb").read(), "fn", 'exec'), glob)""" - self.check(b, a) - - b = """execfile("fn", glob, loc)""" - a = """exec(compile(open("fn", "rb").read(), "fn", 'exec'), glob, loc)""" - self.check(b, a) - - b = """execfile("fn", globals=glob)""" - a = """exec(compile(open("fn", "rb").read(), "fn", 'exec'), globals=glob)""" - self.check(b, a) - - b = """execfile("fn", locals=loc)""" - a = """exec(compile(open("fn", "rb").read(), "fn", 'exec'), locals=loc)""" - self.check(b, a) - - b = """execfile("fn", globals=glob, locals=loc)""" - a = """exec(compile(open("fn", "rb").read(), "fn", 'exec'), globals=glob, locals=loc)""" - self.check(b, a) - - def test_spacing(self): - b = """execfile( "fn" )""" - a = """exec(compile(open( "fn", "rb" ).read(), "fn", 'exec'))""" - self.check(b, a) - - b = """execfile("fn", globals = glob)""" - a = """exec(compile(open("fn", "rb").read(), "fn", 'exec'), globals = glob)""" - self.check(b, a) - - -class Test_isinstance(FixerTestCase): - fixer = "isinstance" - - def test_remove_multiple_items(self): - b = """isinstance(x, (int, int, int))""" - a = """isinstance(x, int)""" - self.check(b, a) - - b = """isinstance(x, (int, float, int, int, float))""" - a = """isinstance(x, (int, float))""" - self.check(b, a) - - b = """isinstance(x, (int, float, int, int, float, str))""" - a = """isinstance(x, (int, float, str))""" - self.check(b, a) - - b = """isinstance(foo() + bar(), (x(), y(), x(), int, int))""" - a = """isinstance(foo() + bar(), (x(), y(), x(), int))""" - self.check(b, a) - - def test_prefix_preservation(self): - b = """if isinstance( foo(), ( bar, bar, baz )) : pass""" - a = """if isinstance( foo(), ( bar, baz )) : pass""" - self.check(b, a) - - def test_unchanged(self): - self.unchanged("isinstance(x, (str, int))") - -class Test_dict(FixerTestCase): - fixer = "dict" - - def test_prefix_preservation(self): - b = "if d. keys ( ) : pass" - a = "if list(d. keys ( )) : pass" - self.check(b, a) - - b = "if d. items ( ) : pass" - a = "if list(d. items ( )) : pass" - self.check(b, a) - - b = "if d. iterkeys ( ) : pass" - a = "if iter(d. keys ( )) : pass" - self.check(b, a) - - b = "[i for i in d. iterkeys( ) ]" - a = "[i for i in d. keys( ) ]" - self.check(b, a) - - b = "if d. viewkeys ( ) : pass" - a = "if d. keys ( ) : pass" - self.check(b, a) - - b = "[i for i in d. viewkeys( ) ]" - a = "[i for i in d. keys( ) ]" - self.check(b, a) - - def test_trailing_comment(self): - b = "d.keys() # foo" - a = "list(d.keys()) # foo" - self.check(b, a) - - b = "d.items() # foo" - a = "list(d.items()) # foo" - self.check(b, a) - - b = "d.iterkeys() # foo" - a = "iter(d.keys()) # foo" - self.check(b, a) - - b = """[i for i in d.iterkeys() # foo - ]""" - a = """[i for i in d.keys() # foo - ]""" - self.check(b, a) - - b = """[i for i in d.iterkeys() # foo - ]""" - a = """[i for i in d.keys() # foo - ]""" - self.check(b, a) - - b = "d.viewitems() # foo" - a = "d.items() # foo" - self.check(b, a) - - def test_unchanged(self): - for wrapper in fixer_util.consuming_calls: - s = "s = %s(d.keys())" % wrapper - self.unchanged(s) - - s = "s = %s(d.values())" % wrapper - self.unchanged(s) - - s = "s = %s(d.items())" % wrapper - self.unchanged(s) - - def test_01(self): - b = "d.keys()" - a = "list(d.keys())" - self.check(b, a) - - b = "a[0].foo().keys()" - a = "list(a[0].foo().keys())" - self.check(b, a) - - def test_02(self): - b = "d.items()" - a = "list(d.items())" - self.check(b, a) - - def test_03(self): - b = "d.values()" - a = "list(d.values())" - self.check(b, a) - - def test_04(self): - b = "d.iterkeys()" - a = "iter(d.keys())" - self.check(b, a) - - def test_05(self): - b = "d.iteritems()" - a = "iter(d.items())" - self.check(b, a) - - def test_06(self): - b = "d.itervalues()" - a = "iter(d.values())" - self.check(b, a) - - def test_07(self): - s = "list(d.keys())" - self.unchanged(s) - - def test_08(self): - s = "sorted(d.keys())" - self.unchanged(s) - - def test_09(self): - b = "iter(d.keys())" - a = "iter(list(d.keys()))" - self.check(b, a) - - def test_10(self): - b = "foo(d.keys())" - a = "foo(list(d.keys()))" - self.check(b, a) - - def test_11(self): - b = "for i in d.keys(): print i" - a = "for i in list(d.keys()): print i" - self.check(b, a) - - def test_12(self): - b = "for i in d.iterkeys(): print i" - a = "for i in d.keys(): print i" - self.check(b, a) - - def test_13(self): - b = "[i for i in d.keys()]" - a = "[i for i in list(d.keys())]" - self.check(b, a) - - def test_14(self): - b = "[i for i in d.iterkeys()]" - a = "[i for i in d.keys()]" - self.check(b, a) - - def test_15(self): - b = "(i for i in d.keys())" - a = "(i for i in list(d.keys()))" - self.check(b, a) - - def test_16(self): - b = "(i for i in d.iterkeys())" - a = "(i for i in d.keys())" - self.check(b, a) - - def test_17(self): - b = "iter(d.iterkeys())" - a = "iter(d.keys())" - self.check(b, a) - - def test_18(self): - b = "list(d.iterkeys())" - a = "list(d.keys())" - self.check(b, a) - - def test_19(self): - b = "sorted(d.iterkeys())" - a = "sorted(d.keys())" - self.check(b, a) - - def test_20(self): - b = "foo(d.iterkeys())" - a = "foo(iter(d.keys()))" - self.check(b, a) - - def test_21(self): - b = "print h.iterkeys().next()" - a = "print iter(h.keys()).next()" - self.check(b, a) - - def test_22(self): - b = "print h.keys()[0]" - a = "print list(h.keys())[0]" - self.check(b, a) - - def test_23(self): - b = "print list(h.iterkeys().next())" - a = "print list(iter(h.keys()).next())" - self.check(b, a) - - def test_24(self): - b = "for x in h.keys()[0]: print x" - a = "for x in list(h.keys())[0]: print x" - self.check(b, a) - - def test_25(self): - b = "d.viewkeys()" - a = "d.keys()" - self.check(b, a) - - def test_26(self): - b = "d.viewitems()" - a = "d.items()" - self.check(b, a) - - def test_27(self): - b = "d.viewvalues()" - a = "d.values()" - self.check(b, a) - - def test_28(self): - b = "[i for i in d.viewkeys()]" - a = "[i for i in d.keys()]" - self.check(b, a) - - def test_29(self): - b = "(i for i in d.viewkeys())" - a = "(i for i in d.keys())" - self.check(b, a) - - def test_30(self): - b = "iter(d.viewkeys())" - a = "iter(d.keys())" - self.check(b, a) - - def test_31(self): - b = "list(d.viewkeys())" - a = "list(d.keys())" - self.check(b, a) - - def test_32(self): - b = "sorted(d.viewkeys())" - a = "sorted(d.keys())" - self.check(b, a) - -class Test_xrange(FixerTestCase): - fixer = "xrange" - - def test_prefix_preservation(self): - b = """x = xrange( 10 )""" - a = """x = range( 10 )""" - self.check(b, a) - - b = """x = xrange( 1 , 10 )""" - a = """x = range( 1 , 10 )""" - self.check(b, a) - - b = """x = xrange( 0 , 10 , 2 )""" - a = """x = range( 0 , 10 , 2 )""" - self.check(b, a) - - def test_single_arg(self): - b = """x = xrange(10)""" - a = """x = range(10)""" - self.check(b, a) - - def test_two_args(self): - b = """x = xrange(1, 10)""" - a = """x = range(1, 10)""" - self.check(b, a) - - def test_three_args(self): - b = """x = xrange(0, 10, 2)""" - a = """x = range(0, 10, 2)""" - self.check(b, a) - - def test_wrap_in_list(self): - b = """x = range(10, 3, 9)""" - a = """x = list(range(10, 3, 9))""" - self.check(b, a) - - b = """x = foo(range(10, 3, 9))""" - a = """x = foo(list(range(10, 3, 9)))""" - self.check(b, a) - - b = """x = range(10, 3, 9) + [4]""" - a = """x = list(range(10, 3, 9)) + [4]""" - self.check(b, a) - - b = """x = range(10)[::-1]""" - a = """x = list(range(10))[::-1]""" - self.check(b, a) - - b = """x = range(10) [3]""" - a = """x = list(range(10)) [3]""" - self.check(b, a) - - def test_xrange_in_for(self): - b = """for i in xrange(10):\n j=i""" - a = """for i in range(10):\n j=i""" - self.check(b, a) - - b = """[i for i in xrange(10)]""" - a = """[i for i in range(10)]""" - self.check(b, a) - - def test_range_in_for(self): - self.unchanged("for i in range(10): pass") - self.unchanged("[i for i in range(10)]") - - def test_in_contains_test(self): - self.unchanged("x in range(10, 3, 9)") - - def test_in_consuming_context(self): - for call in fixer_util.consuming_calls: - self.unchanged("a = %s(range(10))" % call) - -class Test_xrange_with_reduce(FixerTestCase): - - def setUp(self): - super(Test_xrange_with_reduce, self).setUp(["xrange", "reduce"]) - - def test_double_transform(self): - b = """reduce(x, xrange(5))""" - a = """from functools import reduce -reduce(x, range(5))""" - self.check(b, a) - -class Test_raw_input(FixerTestCase): - fixer = "raw_input" - - def test_prefix_preservation(self): - b = """x = raw_input( )""" - a = """x = input( )""" - self.check(b, a) - - b = """x = raw_input( '' )""" - a = """x = input( '' )""" - self.check(b, a) - - def test_1(self): - b = """x = raw_input()""" - a = """x = input()""" - self.check(b, a) - - def test_2(self): - b = """x = raw_input('')""" - a = """x = input('')""" - self.check(b, a) - - def test_3(self): - b = """x = raw_input('prompt')""" - a = """x = input('prompt')""" - self.check(b, a) - - def test_4(self): - b = """x = raw_input(foo(a) + 6)""" - a = """x = input(foo(a) + 6)""" - self.check(b, a) - - def test_5(self): - b = """x = raw_input(invite).split()""" - a = """x = input(invite).split()""" - self.check(b, a) - - def test_6(self): - b = """x = raw_input(invite) . split ()""" - a = """x = input(invite) . split ()""" - self.check(b, a) - - def test_8(self): - b = "x = int(raw_input())" - a = "x = int(input())" - self.check(b, a) - -class Test_funcattrs(FixerTestCase): - fixer = "funcattrs" - - attrs = ["closure", "doc", "name", "defaults", "code", "globals", "dict"] - - def test(self): - for attr in self.attrs: - b = "a.func_%s" % attr - a = "a.__%s__" % attr - self.check(b, a) - - b = "self.foo.func_%s.foo_bar" % attr - a = "self.foo.__%s__.foo_bar" % attr - self.check(b, a) - - def test_unchanged(self): - for attr in self.attrs: - s = "foo(func_%s + 5)" % attr - self.unchanged(s) - - s = "f(foo.__%s__)" % attr - self.unchanged(s) - - s = "f(foo.__%s__.foo)" % attr - self.unchanged(s) - -class Test_xreadlines(FixerTestCase): - fixer = "xreadlines" - - def test_call(self): - b = "for x in f.xreadlines(): pass" - a = "for x in f: pass" - self.check(b, a) - - b = "for x in foo().xreadlines(): pass" - a = "for x in foo(): pass" - self.check(b, a) - - b = "for x in (5 + foo()).xreadlines(): pass" - a = "for x in (5 + foo()): pass" - self.check(b, a) - - def test_attr_ref(self): - b = "foo(f.xreadlines + 5)" - a = "foo(f.__iter__ + 5)" - self.check(b, a) - - b = "foo(f().xreadlines + 5)" - a = "foo(f().__iter__ + 5)" - self.check(b, a) - - b = "foo((5 + f()).xreadlines + 5)" - a = "foo((5 + f()).__iter__ + 5)" - self.check(b, a) - - def test_unchanged(self): - s = "for x in f.xreadlines(5): pass" - self.unchanged(s) - - s = "for x in f.xreadlines(k=5): pass" - self.unchanged(s) - - s = "for x in f.xreadlines(*k, **v): pass" - self.unchanged(s) - - s = "foo(xreadlines)" - self.unchanged(s) - - -class ImportsFixerTests: - - def test_import_module(self): - for old, new in self.modules.items(): - b = "import %s" % old - a = "import %s" % new - self.check(b, a) - - b = "import foo, %s, bar" % old - a = "import foo, %s, bar" % new - self.check(b, a) - - def test_import_from(self): - for old, new in self.modules.items(): - b = "from %s import foo" % old - a = "from %s import foo" % new - self.check(b, a) - - b = "from %s import foo, bar" % old - a = "from %s import foo, bar" % new - self.check(b, a) - - b = "from %s import (yes, no)" % old - a = "from %s import (yes, no)" % new - self.check(b, a) - - def test_import_module_as(self): - for old, new in self.modules.items(): - b = "import %s as foo_bar" % old - a = "import %s as foo_bar" % new - self.check(b, a) - - b = "import %s as foo_bar" % old - a = "import %s as foo_bar" % new - self.check(b, a) - - def test_import_from_as(self): - for old, new in self.modules.items(): - b = "from %s import foo as bar" % old - a = "from %s import foo as bar" % new - self.check(b, a) - - def test_star(self): - for old, new in self.modules.items(): - b = "from %s import *" % old - a = "from %s import *" % new - self.check(b, a) - - def test_import_module_usage(self): - for old, new in self.modules.items(): - b = """ - import %s - foo(%s.bar) - """ % (old, old) - a = """ - import %s - foo(%s.bar) - """ % (new, new) - self.check(b, a) - - b = """ - from %s import x - %s = 23 - """ % (old, old) - a = """ - from %s import x - %s = 23 - """ % (new, old) - self.check(b, a) - - s = """ - def f(): - %s.method() - """ % (old,) - self.unchanged(s) - - # test nested usage - b = """ - import %s - %s.bar(%s.foo) - """ % (old, old, old) - a = """ - import %s - %s.bar(%s.foo) - """ % (new, new, new) - self.check(b, a) - - b = """ - import %s - x.%s - """ % (old, old) - a = """ - import %s - x.%s - """ % (new, old) - self.check(b, a) - - -class Test_imports(FixerTestCase, ImportsFixerTests): - fixer = "imports" - from lib2to3.fixes.fix_imports import MAPPING as modules - - def test_multiple_imports(self): - b = """import urlparse, cStringIO""" - a = """import urllib.parse, io""" - self.check(b, a) - - def test_multiple_imports_as(self): - b = """ - import copy_reg as bar, HTMLParser as foo, urlparse - s = urlparse.spam(bar.foo()) - """ - a = """ - import copyreg as bar, html.parser as foo, urllib.parse - s = urllib.parse.spam(bar.foo()) - """ - self.check(b, a) - - -class Test_imports2(FixerTestCase, ImportsFixerTests): - fixer = "imports2" - from lib2to3.fixes.fix_imports2 import MAPPING as modules - - -class Test_imports_fixer_order(FixerTestCase, ImportsFixerTests): - - def setUp(self): - super(Test_imports_fixer_order, self).setUp(['imports', 'imports2']) - from lib2to3.fixes.fix_imports2 import MAPPING as mapping2 - self.modules = mapping2.copy() - from lib2to3.fixes.fix_imports import MAPPING as mapping1 - for key in ('dbhash', 'dumbdbm', 'dbm', 'gdbm'): - self.modules[key] = mapping1[key] - - def test_after_local_imports_refactoring(self): - for fix in ("imports", "imports2"): - self.fixer = fix - self.assert_runs_after("import") - - -class Test_urllib(FixerTestCase): - fixer = "urllib" - from lib2to3.fixes.fix_urllib import MAPPING as modules - - def test_import_module(self): - for old, changes in self.modules.items(): - b = "import %s" % old - a = "import %s" % ", ".join(map(itemgetter(0), changes)) - self.check(b, a) - - def test_import_from(self): - for old, changes in self.modules.items(): - all_members = [] - for new, members in changes: - for member in members: - all_members.append(member) - b = "from %s import %s" % (old, member) - a = "from %s import %s" % (new, member) - self.check(b, a) - - s = "from foo import %s" % member - self.unchanged(s) - - b = "from %s import %s" % (old, ", ".join(members)) - a = "from %s import %s" % (new, ", ".join(members)) - self.check(b, a) - - s = "from foo import %s" % ", ".join(members) - self.unchanged(s) - - # test the breaking of a module into multiple replacements - b = "from %s import %s" % (old, ", ".join(all_members)) - a = "\n".join(["from %s import %s" % (new, ", ".join(members)) - for (new, members) in changes]) - self.check(b, a) - - def test_import_module_as(self): - for old in self.modules: - s = "import %s as foo" % old - self.warns_unchanged(s, "This module is now multiple modules") - - def test_import_from_as(self): - for old, changes in self.modules.items(): - for new, members in changes: - for member in members: - b = "from %s import %s as foo_bar" % (old, member) - a = "from %s import %s as foo_bar" % (new, member) - self.check(b, a) - b = "from %s import %s as blah, %s" % (old, member, member) - a = "from %s import %s as blah, %s" % (new, member, member) - self.check(b, a) - - def test_star(self): - for old in self.modules: - s = "from %s import *" % old - self.warns_unchanged(s, "Cannot handle star imports") - - def test_indented(self): - b = """ -def foo(): - from urllib import urlencode, urlopen -""" - a = """ -def foo(): - from urllib.parse import urlencode - from urllib.request import urlopen -""" - self.check(b, a) - - b = """ -def foo(): - other() - from urllib import urlencode, urlopen -""" - a = """ -def foo(): - other() - from urllib.parse import urlencode - from urllib.request import urlopen -""" - self.check(b, a) - - def test_single_import(self): - b = "from urllib import getproxies" - a = "from urllib.request import getproxies" - - self.check(b, a) - - def test_import_module_usage(self): - for old, changes in self.modules.items(): - for new, members in changes: - for member in members: - new_import = ", ".join([n for (n, mems) - in self.modules[old]]) - b = """ - import %s - foo(%s.%s) - """ % (old, old, member) - a = """ - import %s - foo(%s.%s) - """ % (new_import, new, member) - self.check(b, a) - b = """ - import %s - %s.%s(%s.%s) - """ % (old, old, member, old, member) - a = """ - import %s - %s.%s(%s.%s) - """ % (new_import, new, member, new, member) - self.check(b, a) - - -class Test_input(FixerTestCase): - fixer = "input" - - def test_prefix_preservation(self): - b = """x = input( )""" - a = """x = eval(input( ))""" - self.check(b, a) - - b = """x = input( '' )""" - a = """x = eval(input( '' ))""" - self.check(b, a) - - def test_trailing_comment(self): - b = """x = input() # foo""" - a = """x = eval(input()) # foo""" - self.check(b, a) - - def test_idempotency(self): - s = """x = eval(input())""" - self.unchanged(s) - - s = """x = eval(input(''))""" - self.unchanged(s) - - s = """x = eval(input(foo(5) + 9))""" - self.unchanged(s) - - def test_1(self): - b = """x = input()""" - a = """x = eval(input())""" - self.check(b, a) - - def test_2(self): - b = """x = input('')""" - a = """x = eval(input(''))""" - self.check(b, a) - - def test_3(self): - b = """x = input('prompt')""" - a = """x = eval(input('prompt'))""" - self.check(b, a) - - def test_4(self): - b = """x = input(foo(5) + 9)""" - a = """x = eval(input(foo(5) + 9))""" - self.check(b, a) - -class Test_tuple_params(FixerTestCase): - fixer = "tuple_params" - - def test_unchanged_1(self): - s = """def foo(): pass""" - self.unchanged(s) - - def test_unchanged_2(self): - s = """def foo(a, b, c): pass""" - self.unchanged(s) - - def test_unchanged_3(self): - s = """def foo(a=3, b=4, c=5): pass""" - self.unchanged(s) - - def test_1(self): - b = """ - def foo(((a, b), c)): - x = 5""" - - a = """ - def foo(xxx_todo_changeme): - ((a, b), c) = xxx_todo_changeme - x = 5""" - self.check(b, a) - - def test_2(self): - b = """ - def foo(((a, b), c), d): - x = 5""" - - a = """ - def foo(xxx_todo_changeme, d): - ((a, b), c) = xxx_todo_changeme - x = 5""" - self.check(b, a) - - def test_3(self): - b = """ - def foo(((a, b), c), d) -> e: - x = 5""" - - a = """ - def foo(xxx_todo_changeme, d) -> e: - ((a, b), c) = xxx_todo_changeme - x = 5""" - self.check(b, a) - - def test_semicolon(self): - b = """ - def foo(((a, b), c)): x = 5; y = 7""" - - a = """ - def foo(xxx_todo_changeme): ((a, b), c) = xxx_todo_changeme; x = 5; y = 7""" - self.check(b, a) - - def test_keywords(self): - b = """ - def foo(((a, b), c), d, e=5) -> z: - x = 5""" - - a = """ - def foo(xxx_todo_changeme, d, e=5) -> z: - ((a, b), c) = xxx_todo_changeme - x = 5""" - self.check(b, a) - - def test_varargs(self): - b = """ - def foo(((a, b), c), d, *vargs, **kwargs) -> z: - x = 5""" - - a = """ - def foo(xxx_todo_changeme, d, *vargs, **kwargs) -> z: - ((a, b), c) = xxx_todo_changeme - x = 5""" - self.check(b, a) - - def test_multi_1(self): - b = """ - def foo(((a, b), c), (d, e, f)) -> z: - x = 5""" - - a = """ - def foo(xxx_todo_changeme, xxx_todo_changeme1) -> z: - ((a, b), c) = xxx_todo_changeme - (d, e, f) = xxx_todo_changeme1 - x = 5""" - self.check(b, a) - - def test_multi_2(self): - b = """ - def foo(x, ((a, b), c), d, (e, f, g), y) -> z: - x = 5""" - - a = """ - def foo(x, xxx_todo_changeme, d, xxx_todo_changeme1, y) -> z: - ((a, b), c) = xxx_todo_changeme - (e, f, g) = xxx_todo_changeme1 - x = 5""" - self.check(b, a) - - def test_docstring(self): - b = """ - def foo(((a, b), c), (d, e, f)) -> z: - "foo foo foo foo" - x = 5""" - - a = """ - def foo(xxx_todo_changeme, xxx_todo_changeme1) -> z: - "foo foo foo foo" - ((a, b), c) = xxx_todo_changeme - (d, e, f) = xxx_todo_changeme1 - x = 5""" - self.check(b, a) - - def test_lambda_no_change(self): - s = """lambda x: x + 5""" - self.unchanged(s) - - def test_lambda_parens_single_arg(self): - b = """lambda (x): x + 5""" - a = """lambda x: x + 5""" - self.check(b, a) - - b = """lambda(x): x + 5""" - a = """lambda x: x + 5""" - self.check(b, a) - - b = """lambda ((((x)))): x + 5""" - a = """lambda x: x + 5""" - self.check(b, a) - - b = """lambda((((x)))): x + 5""" - a = """lambda x: x + 5""" - self.check(b, a) - - def test_lambda_simple(self): - b = """lambda (x, y): x + f(y)""" - a = """lambda x_y: x_y[0] + f(x_y[1])""" - self.check(b, a) - - b = """lambda(x, y): x + f(y)""" - a = """lambda x_y: x_y[0] + f(x_y[1])""" - self.check(b, a) - - b = """lambda (((x, y))): x + f(y)""" - a = """lambda x_y: x_y[0] + f(x_y[1])""" - self.check(b, a) - - b = """lambda(((x, y))): x + f(y)""" - a = """lambda x_y: x_y[0] + f(x_y[1])""" - self.check(b, a) - - def test_lambda_one_tuple(self): - b = """lambda (x,): x + f(x)""" - a = """lambda x1: x1[0] + f(x1[0])""" - self.check(b, a) - - b = """lambda (((x,))): x + f(x)""" - a = """lambda x1: x1[0] + f(x1[0])""" - self.check(b, a) - - def test_lambda_simple_multi_use(self): - b = """lambda (x, y): x + x + f(x) + x""" - a = """lambda x_y: x_y[0] + x_y[0] + f(x_y[0]) + x_y[0]""" - self.check(b, a) - - def test_lambda_simple_reverse(self): - b = """lambda (x, y): y + x""" - a = """lambda x_y: x_y[1] + x_y[0]""" - self.check(b, a) - - def test_lambda_nested(self): - b = """lambda (x, (y, z)): x + y + z""" - a = """lambda x_y_z: x_y_z[0] + x_y_z[1][0] + x_y_z[1][1]""" - self.check(b, a) - - b = """lambda (((x, (y, z)))): x + y + z""" - a = """lambda x_y_z: x_y_z[0] + x_y_z[1][0] + x_y_z[1][1]""" - self.check(b, a) - - def test_lambda_nested_multi_use(self): - b = """lambda (x, (y, z)): x + y + f(y)""" - a = """lambda x_y_z: x_y_z[0] + x_y_z[1][0] + f(x_y_z[1][0])""" - self.check(b, a) - -class Test_methodattrs(FixerTestCase): - fixer = "methodattrs" - - attrs = ["func", "self", "class"] - - def test(self): - for attr in self.attrs: - b = "a.im_%s" % attr - if attr == "class": - a = "a.__self__.__class__" - else: - a = "a.__%s__" % attr - self.check(b, a) - - b = "self.foo.im_%s.foo_bar" % attr - if attr == "class": - a = "self.foo.__self__.__class__.foo_bar" - else: - a = "self.foo.__%s__.foo_bar" % attr - self.check(b, a) - - def test_unchanged(self): - for attr in self.attrs: - s = "foo(im_%s + 5)" % attr - self.unchanged(s) - - s = "f(foo.__%s__)" % attr - self.unchanged(s) - - s = "f(foo.__%s__.foo)" % attr - self.unchanged(s) - -class Test_next(FixerTestCase): - fixer = "next" - - def test_1(self): - b = """it.next()""" - a = """next(it)""" - self.check(b, a) - - def test_2(self): - b = """a.b.c.d.next()""" - a = """next(a.b.c.d)""" - self.check(b, a) - - def test_3(self): - b = """(a + b).next()""" - a = """next((a + b))""" - self.check(b, a) - - def test_4(self): - b = """a().next()""" - a = """next(a())""" - self.check(b, a) - - def test_5(self): - b = """a().next() + b""" - a = """next(a()) + b""" - self.check(b, a) - - def test_6(self): - b = """c( a().next() + b)""" - a = """c( next(a()) + b)""" - self.check(b, a) - - def test_prefix_preservation_1(self): - b = """ - for a in b: - foo(a) - a.next() - """ - a = """ - for a in b: - foo(a) - next(a) - """ - self.check(b, a) - - def test_prefix_preservation_2(self): - b = """ - for a in b: - foo(a) # abc - # def - a.next() - """ - a = """ - for a in b: - foo(a) # abc - # def - next(a) - """ - self.check(b, a) - - def test_prefix_preservation_3(self): - b = """ - next = 5 - for a in b: - foo(a) - a.next() - """ - a = """ - next = 5 - for a in b: - foo(a) - a.__next__() - """ - self.check(b, a, ignore_warnings=True) - - def test_prefix_preservation_4(self): - b = """ - next = 5 - for a in b: - foo(a) # abc - # def - a.next() - """ - a = """ - next = 5 - for a in b: - foo(a) # abc - # def - a.__next__() - """ - self.check(b, a, ignore_warnings=True) - - def test_prefix_preservation_5(self): - b = """ - next = 5 - for a in b: - foo(foo(a), # abc - a.next()) - """ - a = """ - next = 5 - for a in b: - foo(foo(a), # abc - a.__next__()) - """ - self.check(b, a, ignore_warnings=True) - - def test_prefix_preservation_6(self): - b = """ - for a in b: - foo(foo(a), # abc - a.next()) - """ - a = """ - for a in b: - foo(foo(a), # abc - next(a)) - """ - self.check(b, a) - - def test_method_1(self): - b = """ - class A: - def next(self): - pass - """ - a = """ - class A: - def __next__(self): - pass - """ - self.check(b, a) - - def test_method_2(self): - b = """ - class A(object): - def next(self): - pass - """ - a = """ - class A(object): - def __next__(self): - pass - """ - self.check(b, a) - - def test_method_3(self): - b = """ - class A: - def next(x): - pass - """ - a = """ - class A: - def __next__(x): - pass - """ - self.check(b, a) - - def test_method_4(self): - b = """ - class A: - def __init__(self, foo): - self.foo = foo - - def next(self): - pass - - def __iter__(self): - return self - """ - a = """ - class A: - def __init__(self, foo): - self.foo = foo - - def __next__(self): - pass - - def __iter__(self): - return self - """ - self.check(b, a) - - def test_method_unchanged(self): - s = """ - class A: - def next(self, a, b): - pass - """ - self.unchanged(s) - - def test_shadowing_assign_simple(self): - s = """ - next = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_assign_tuple_1(self): - s = """ - (next, a) = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_assign_tuple_2(self): - s = """ - (a, (b, (next, c)), a) = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_assign_list_1(self): - s = """ - [next, a] = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_assign_list_2(self): - s = """ - [a, [b, [next, c]], a] = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_builtin_assign(self): - s = """ - def foo(): - __builtin__.next = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_builtin_assign_in_tuple(self): - s = """ - def foo(): - (a, __builtin__.next) = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_builtin_assign_in_list(self): - s = """ - def foo(): - [a, __builtin__.next] = foo - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_assign_to_next(self): - s = """ - def foo(): - A.next = foo - - class A: - def next(self, a, b): - pass - """ - self.unchanged(s) - - def test_assign_to_next_in_tuple(self): - s = """ - def foo(): - (a, A.next) = foo - - class A: - def next(self, a, b): - pass - """ - self.unchanged(s) - - def test_assign_to_next_in_list(self): - s = """ - def foo(): - [a, A.next] = foo - - class A: - def next(self, a, b): - pass - """ - self.unchanged(s) - - def test_shadowing_import_1(self): - s = """ - import foo.bar as next - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_import_2(self): - s = """ - import bar, bar.foo as next - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_import_3(self): - s = """ - import bar, bar.foo as next, baz - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_import_from_1(self): - s = """ - from x import next - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_import_from_2(self): - s = """ - from x.a import next - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_import_from_3(self): - s = """ - from x import a, next, b - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_import_from_4(self): - s = """ - from x.a import a, next, b - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_funcdef_1(self): - s = """ - def next(a): - pass - - class A: - def next(self, a, b): - pass - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_funcdef_2(self): - b = """ - def next(a): - pass - - class A: - def next(self): - pass - - it.next() - """ - a = """ - def next(a): - pass - - class A: - def __next__(self): - pass - - it.__next__() - """ - self.warns(b, a, "Calls to builtin next() possibly shadowed") - - def test_shadowing_global_1(self): - s = """ - def f(): - global next - next = 5 - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_global_2(self): - s = """ - def f(): - global a, next, b - next = 5 - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_for_simple(self): - s = """ - for next in it(): - pass - - b = 5 - c = 6 - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_for_tuple_1(self): - s = """ - for next, b in it(): - pass - - b = 5 - c = 6 - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_shadowing_for_tuple_2(self): - s = """ - for a, (next, c), b in it(): - pass - - b = 5 - c = 6 - """ - self.warns_unchanged(s, "Calls to builtin next() possibly shadowed") - - def test_noncall_access_1(self): - b = """gnext = g.next""" - a = """gnext = g.__next__""" - self.check(b, a) - - def test_noncall_access_2(self): - b = """f(g.next + 5)""" - a = """f(g.__next__ + 5)""" - self.check(b, a) - - def test_noncall_access_3(self): - b = """f(g().next + 5)""" - a = """f(g().__next__ + 5)""" - self.check(b, a) - -class Test_nonzero(FixerTestCase): - fixer = "nonzero" - - def test_1(self): - b = """ - class A: - def __nonzero__(self): - pass - """ - a = """ - class A: - def __bool__(self): - pass - """ - self.check(b, a) - - def test_2(self): - b = """ - class A(object): - def __nonzero__(self): - pass - """ - a = """ - class A(object): - def __bool__(self): - pass - """ - self.check(b, a) - - def test_unchanged_1(self): - s = """ - class A(object): - def __bool__(self): - pass - """ - self.unchanged(s) - - def test_unchanged_2(self): - s = """ - class A(object): - def __nonzero__(self, a): - pass - """ - self.unchanged(s) - - def test_unchanged_func(self): - s = """ - def __nonzero__(self): - pass - """ - self.unchanged(s) - -class Test_numliterals(FixerTestCase): - fixer = "numliterals" - - def test_octal_1(self): - b = """0755""" - a = """0o755""" - self.check(b, a) - - def test_long_int_1(self): - b = """a = 12L""" - a = """a = 12""" - self.check(b, a) - - def test_long_int_2(self): - b = """a = 12l""" - a = """a = 12""" - self.check(b, a) - - def test_long_hex(self): - b = """b = 0x12l""" - a = """b = 0x12""" - self.check(b, a) - - def test_comments_and_spacing(self): - b = """b = 0x12L""" - a = """b = 0x12""" - self.check(b, a) - - b = """b = 0755 # spam""" - a = """b = 0o755 # spam""" - self.check(b, a) - - def test_unchanged_int(self): - s = """5""" - self.unchanged(s) - - def test_unchanged_float(self): - s = """5.0""" - self.unchanged(s) - - def test_unchanged_octal(self): - s = """0o755""" - self.unchanged(s) - - def test_unchanged_hex(self): - s = """0xABC""" - self.unchanged(s) - - def test_unchanged_exp(self): - s = """5.0e10""" - self.unchanged(s) - - def test_unchanged_complex_int(self): - s = """5 + 4j""" - self.unchanged(s) - - def test_unchanged_complex_float(self): - s = """5.4 + 4.9j""" - self.unchanged(s) - - def test_unchanged_complex_bare(self): - s = """4j""" - self.unchanged(s) - s = """4.4j""" - self.unchanged(s) - -class Test_renames(FixerTestCase): - fixer = "renames" - - modules = {"sys": ("maxint", "maxsize"), - } - - def test_import_from(self): - for mod, (old, new) in list(self.modules.items()): - b = "from %s import %s" % (mod, old) - a = "from %s import %s" % (mod, new) - self.check(b, a) - - s = "from foo import %s" % old - self.unchanged(s) - - def test_import_from_as(self): - for mod, (old, new) in list(self.modules.items()): - b = "from %s import %s as foo_bar" % (mod, old) - a = "from %s import %s as foo_bar" % (mod, new) - self.check(b, a) - - def test_import_module_usage(self): - for mod, (old, new) in list(self.modules.items()): - b = """ - import %s - foo(%s, %s.%s) - """ % (mod, mod, mod, old) - a = """ - import %s - foo(%s, %s.%s) - """ % (mod, mod, mod, new) - self.check(b, a) - - def XXX_test_from_import_usage(self): - # not implemented yet - for mod, (old, new) in list(self.modules.items()): - b = """ - from %s import %s - foo(%s, %s) - """ % (mod, old, mod, old) - a = """ - from %s import %s - foo(%s, %s) - """ % (mod, new, mod, new) - self.check(b, a) - -class Test_unicode(FixerTestCase): - fixer = "unicode" - - def test_whitespace(self): - b = """unicode( x)""" - a = """str( x)""" - self.check(b, a) - - b = """ unicode(x )""" - a = """ str(x )""" - self.check(b, a) - - b = """ u'h'""" - a = """ 'h'""" - self.check(b, a) - - def test_unicode_call(self): - b = """unicode(x, y, z)""" - a = """str(x, y, z)""" - self.check(b, a) - - def test_unichr(self): - b = """unichr(u'h')""" - a = """chr('h')""" - self.check(b, a) - - def test_unicode_literal_1(self): - b = '''u"x"''' - a = '''"x"''' - self.check(b, a) - - def test_unicode_literal_2(self): - b = """ur'x'""" - a = """r'x'""" - self.check(b, a) - - def test_unicode_literal_3(self): - b = """UR'''x''' """ - a = """R'''x''' """ - self.check(b, a) - - def test_native_literal_escape_u(self): - b = r"""'\\\u20ac\U0001d121\\u20ac'""" - a = r"""'\\\\u20ac\\U0001d121\\u20ac'""" - self.check(b, a) - - b = r"""r'\\\u20ac\U0001d121\\u20ac'""" - a = r"""r'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) - - def test_bytes_literal_escape_u(self): - b = r"""b'\\\u20ac\U0001d121\\u20ac'""" - a = r"""b'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) - - b = r"""br'\\\u20ac\U0001d121\\u20ac'""" - a = r"""br'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) - - def test_unicode_literal_escape_u(self): - b = r"""u'\\\u20ac\U0001d121\\u20ac'""" - a = r"""'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) - - b = r"""ur'\\\u20ac\U0001d121\\u20ac'""" - a = r"""r'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) - - def test_native_unicode_literal_escape_u(self): - f = 'from __future__ import unicode_literals\n' - b = f + r"""'\\\u20ac\U0001d121\\u20ac'""" - a = f + r"""'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) - - b = f + r"""r'\\\u20ac\U0001d121\\u20ac'""" - a = f + r"""r'\\\u20ac\U0001d121\\u20ac'""" - self.check(b, a) - - -class Test_filter(FixerTestCase): - fixer = "filter" - - def test_prefix_preservation(self): - b = """x = filter( foo, 'abc' )""" - a = """x = list(filter( foo, 'abc' ))""" - self.check(b, a) - - b = """x = filter( None , 'abc' )""" - a = """x = [_f for _f in 'abc' if _f]""" - self.check(b, a) - - def test_filter_basic(self): - b = """x = filter(None, 'abc')""" - a = """x = [_f for _f in 'abc' if _f]""" - self.check(b, a) - - b = """x = len(filter(f, 'abc'))""" - a = """x = len(list(filter(f, 'abc')))""" - self.check(b, a) - - b = """x = filter(lambda x: x%2 == 0, range(10))""" - a = """x = [x for x in range(10) if x%2 == 0]""" - self.check(b, a) - - # Note the parens around x - b = """x = filter(lambda (x): x%2 == 0, range(10))""" - a = """x = [x for x in range(10) if x%2 == 0]""" - self.check(b, a) - - # bpo-38871 - b = """filter(lambda x: True if x > 2 else False, [1, 2, 3])""" - a = """[x for x in [1, 2, 3] if (True if x > 2 else False)]""" - self.check(b, a) - - def test_filter_trailers(self): - b = """x = filter(None, 'abc')[0]""" - a = """x = [_f for _f in 'abc' if _f][0]""" - self.check(b, a) - - b = """x = len(filter(f, 'abc')[0])""" - a = """x = len(list(filter(f, 'abc'))[0])""" - self.check(b, a) - - b = """x = filter(lambda x: x%2 == 0, range(10))[0]""" - a = """x = [x for x in range(10) if x%2 == 0][0]""" - self.check(b, a) - - # Note the parens around x - b = """x = filter(lambda (x): x%2 == 0, range(10))[0]""" - a = """x = [x for x in range(10) if x%2 == 0][0]""" - self.check(b, a) - - def test_filter_nochange(self): - a = """b.join(filter(f, 'abc'))""" - self.unchanged(a) - a = """(a + foo(5)).join(filter(f, 'abc'))""" - self.unchanged(a) - a = """iter(filter(f, 'abc'))""" - self.unchanged(a) - a = """list(filter(f, 'abc'))""" - self.unchanged(a) - a = """list(filter(f, 'abc'))[0]""" - self.unchanged(a) - a = """set(filter(f, 'abc'))""" - self.unchanged(a) - a = """set(filter(f, 'abc')).pop()""" - self.unchanged(a) - a = """tuple(filter(f, 'abc'))""" - self.unchanged(a) - a = """any(filter(f, 'abc'))""" - self.unchanged(a) - a = """all(filter(f, 'abc'))""" - self.unchanged(a) - a = """sum(filter(f, 'abc'))""" - self.unchanged(a) - a = """sorted(filter(f, 'abc'))""" - self.unchanged(a) - a = """sorted(filter(f, 'abc'), key=blah)""" - self.unchanged(a) - a = """sorted(filter(f, 'abc'), key=blah)[0]""" - self.unchanged(a) - a = """enumerate(filter(f, 'abc'))""" - self.unchanged(a) - a = """enumerate(filter(f, 'abc'), start=1)""" - self.unchanged(a) - a = """for i in filter(f, 'abc'): pass""" - self.unchanged(a) - a = """[x for x in filter(f, 'abc')]""" - self.unchanged(a) - a = """(x for x in filter(f, 'abc'))""" - self.unchanged(a) - - def test_future_builtins(self): - a = "from future_builtins import spam, filter; filter(f, 'ham')" - self.unchanged(a) - - b = """from future_builtins import spam; x = filter(f, 'abc')""" - a = """from future_builtins import spam; x = list(filter(f, 'abc'))""" - self.check(b, a) - - a = "from future_builtins import *; filter(f, 'ham')" - self.unchanged(a) - -class Test_map(FixerTestCase): - fixer = "map" - - def check(self, b, a): - self.unchanged("from future_builtins import map; " + b, a) - super(Test_map, self).check(b, a) - - def test_prefix_preservation(self): - b = """x = map( f, 'abc' )""" - a = """x = list(map( f, 'abc' ))""" - self.check(b, a) - - def test_map_trailers(self): - b = """x = map(f, 'abc')[0]""" - a = """x = list(map(f, 'abc'))[0]""" - self.check(b, a) - - b = """x = map(None, l)[0]""" - a = """x = list(l)[0]""" - self.check(b, a) - - b = """x = map(lambda x:x, l)[0]""" - a = """x = [x for x in l][0]""" - self.check(b, a) - - b = """x = map(f, 'abc')[0][1]""" - a = """x = list(map(f, 'abc'))[0][1]""" - self.check(b, a) - - def test_trailing_comment(self): - b = """x = map(f, 'abc') # foo""" - a = """x = list(map(f, 'abc')) # foo""" - self.check(b, a) - - def test_None_with_multiple_arguments(self): - s = """x = map(None, a, b, c)""" - self.warns_unchanged(s, "cannot convert map(None, ...) with " - "multiple arguments") - - def test_map_basic(self): - b = """x = map(f, 'abc')""" - a = """x = list(map(f, 'abc'))""" - self.check(b, a) - - b = """x = len(map(f, 'abc', 'def'))""" - a = """x = len(list(map(f, 'abc', 'def')))""" - self.check(b, a) - - b = """x = map(None, 'abc')""" - a = """x = list('abc')""" - self.check(b, a) - - b = """x = map(lambda x: x+1, range(4))""" - a = """x = [x+1 for x in range(4)]""" - self.check(b, a) - - # Note the parens around x - b = """x = map(lambda (x): x+1, range(4))""" - a = """x = [x+1 for x in range(4)]""" - self.check(b, a) - - b = """ - foo() - # foo - map(f, x) - """ - a = """ - foo() - # foo - list(map(f, x)) - """ - self.warns(b, a, "You should use a for loop here") - - def test_map_nochange(self): - a = """b.join(map(f, 'abc'))""" - self.unchanged(a) - a = """(a + foo(5)).join(map(f, 'abc'))""" - self.unchanged(a) - a = """iter(map(f, 'abc'))""" - self.unchanged(a) - a = """list(map(f, 'abc'))""" - self.unchanged(a) - a = """list(map(f, 'abc'))[0]""" - self.unchanged(a) - a = """set(map(f, 'abc'))""" - self.unchanged(a) - a = """set(map(f, 'abc')).pop()""" - self.unchanged(a) - a = """tuple(map(f, 'abc'))""" - self.unchanged(a) - a = """any(map(f, 'abc'))""" - self.unchanged(a) - a = """all(map(f, 'abc'))""" - self.unchanged(a) - a = """sum(map(f, 'abc'))""" - self.unchanged(a) - a = """sorted(map(f, 'abc'))""" - self.unchanged(a) - a = """sorted(map(f, 'abc'), key=blah)""" - self.unchanged(a) - a = """sorted(map(f, 'abc'), key=blah)[0]""" - self.unchanged(a) - a = """enumerate(map(f, 'abc'))""" - self.unchanged(a) - a = """enumerate(map(f, 'abc'), start=1)""" - self.unchanged(a) - a = """for i in map(f, 'abc'): pass""" - self.unchanged(a) - a = """[x for x in map(f, 'abc')]""" - self.unchanged(a) - a = """(x for x in map(f, 'abc'))""" - self.unchanged(a) - - def test_future_builtins(self): - a = "from future_builtins import spam, map, eggs; map(f, 'ham')" - self.unchanged(a) - - b = """from future_builtins import spam, eggs; x = map(f, 'abc')""" - a = """from future_builtins import spam, eggs; x = list(map(f, 'abc'))""" - self.check(b, a) - - a = "from future_builtins import *; map(f, 'ham')" - self.unchanged(a) - -class Test_zip(FixerTestCase): - fixer = "zip" - - def check(self, b, a): - self.unchanged("from future_builtins import zip; " + b, a) - super(Test_zip, self).check(b, a) - - def test_zip_basic(self): - b = """x = zip()""" - a = """x = list(zip())""" - self.check(b, a) - - b = """x = zip(a, b, c)""" - a = """x = list(zip(a, b, c))""" - self.check(b, a) - - b = """x = len(zip(a, b))""" - a = """x = len(list(zip(a, b)))""" - self.check(b, a) - - def test_zip_trailers(self): - b = """x = zip(a, b, c)[0]""" - a = """x = list(zip(a, b, c))[0]""" - self.check(b, a) - - b = """x = zip(a, b, c)[0][1]""" - a = """x = list(zip(a, b, c))[0][1]""" - self.check(b, a) - - def test_zip_nochange(self): - a = """b.join(zip(a, b))""" - self.unchanged(a) - a = """(a + foo(5)).join(zip(a, b))""" - self.unchanged(a) - a = """iter(zip(a, b))""" - self.unchanged(a) - a = """list(zip(a, b))""" - self.unchanged(a) - a = """list(zip(a, b))[0]""" - self.unchanged(a) - a = """set(zip(a, b))""" - self.unchanged(a) - a = """set(zip(a, b)).pop()""" - self.unchanged(a) - a = """tuple(zip(a, b))""" - self.unchanged(a) - a = """any(zip(a, b))""" - self.unchanged(a) - a = """all(zip(a, b))""" - self.unchanged(a) - a = """sum(zip(a, b))""" - self.unchanged(a) - a = """sorted(zip(a, b))""" - self.unchanged(a) - a = """sorted(zip(a, b), key=blah)""" - self.unchanged(a) - a = """sorted(zip(a, b), key=blah)[0]""" - self.unchanged(a) - a = """enumerate(zip(a, b))""" - self.unchanged(a) - a = """enumerate(zip(a, b), start=1)""" - self.unchanged(a) - a = """for i in zip(a, b): pass""" - self.unchanged(a) - a = """[x for x in zip(a, b)]""" - self.unchanged(a) - a = """(x for x in zip(a, b))""" - self.unchanged(a) - - def test_future_builtins(self): - a = "from future_builtins import spam, zip, eggs; zip(a, b)" - self.unchanged(a) - - b = """from future_builtins import spam, eggs; x = zip(a, b)""" - a = """from future_builtins import spam, eggs; x = list(zip(a, b))""" - self.check(b, a) - - a = "from future_builtins import *; zip(a, b)" - self.unchanged(a) - -class Test_standarderror(FixerTestCase): - fixer = "standarderror" - - def test(self): - b = """x = StandardError()""" - a = """x = Exception()""" - self.check(b, a) - - b = """x = StandardError(a, b, c)""" - a = """x = Exception(a, b, c)""" - self.check(b, a) - - b = """f(2 + StandardError(a, b, c))""" - a = """f(2 + Exception(a, b, c))""" - self.check(b, a) - -class Test_types(FixerTestCase): - fixer = "types" - - def test_basic_types_convert(self): - b = """types.StringType""" - a = """bytes""" - self.check(b, a) - - b = """types.DictType""" - a = """dict""" - self.check(b, a) - - b = """types . IntType""" - a = """int""" - self.check(b, a) - - b = """types.ListType""" - a = """list""" - self.check(b, a) - - b = """types.LongType""" - a = """int""" - self.check(b, a) - - b = """types.NoneType""" - a = """type(None)""" - self.check(b, a) - - b = "types.StringTypes" - a = "(str,)" - self.check(b, a) - -class Test_idioms(FixerTestCase): - fixer = "idioms" - - def test_while(self): - b = """while 1: foo()""" - a = """while True: foo()""" - self.check(b, a) - - b = """while 1: foo()""" - a = """while True: foo()""" - self.check(b, a) - - b = """ - while 1: - foo() - """ - a = """ - while True: - foo() - """ - self.check(b, a) - - def test_while_unchanged(self): - s = """while 11: foo()""" - self.unchanged(s) - - s = """while 0: foo()""" - self.unchanged(s) - - s = """while foo(): foo()""" - self.unchanged(s) - - s = """while []: foo()""" - self.unchanged(s) - - def test_eq_simple(self): - b = """type(x) == T""" - a = """isinstance(x, T)""" - self.check(b, a) - - b = """if type(x) == T: pass""" - a = """if isinstance(x, T): pass""" - self.check(b, a) - - def test_eq_reverse(self): - b = """T == type(x)""" - a = """isinstance(x, T)""" - self.check(b, a) - - b = """if T == type(x): pass""" - a = """if isinstance(x, T): pass""" - self.check(b, a) - - def test_eq_expression(self): - b = """type(x+y) == d.get('T')""" - a = """isinstance(x+y, d.get('T'))""" - self.check(b, a) - - b = """type( x + y) == d.get('T')""" - a = """isinstance(x + y, d.get('T'))""" - self.check(b, a) - - def test_is_simple(self): - b = """type(x) is T""" - a = """isinstance(x, T)""" - self.check(b, a) - - b = """if type(x) is T: pass""" - a = """if isinstance(x, T): pass""" - self.check(b, a) - - def test_is_reverse(self): - b = """T is type(x)""" - a = """isinstance(x, T)""" - self.check(b, a) - - b = """if T is type(x): pass""" - a = """if isinstance(x, T): pass""" - self.check(b, a) - - def test_is_expression(self): - b = """type(x+y) is d.get('T')""" - a = """isinstance(x+y, d.get('T'))""" - self.check(b, a) - - b = """type( x + y) is d.get('T')""" - a = """isinstance(x + y, d.get('T'))""" - self.check(b, a) - - def test_is_not_simple(self): - b = """type(x) is not T""" - a = """not isinstance(x, T)""" - self.check(b, a) - - b = """if type(x) is not T: pass""" - a = """if not isinstance(x, T): pass""" - self.check(b, a) - - def test_is_not_reverse(self): - b = """T is not type(x)""" - a = """not isinstance(x, T)""" - self.check(b, a) - - b = """if T is not type(x): pass""" - a = """if not isinstance(x, T): pass""" - self.check(b, a) - - def test_is_not_expression(self): - b = """type(x+y) is not d.get('T')""" - a = """not isinstance(x+y, d.get('T'))""" - self.check(b, a) - - b = """type( x + y) is not d.get('T')""" - a = """not isinstance(x + y, d.get('T'))""" - self.check(b, a) - - def test_ne_simple(self): - b = """type(x) != T""" - a = """not isinstance(x, T)""" - self.check(b, a) - - b = """if type(x) != T: pass""" - a = """if not isinstance(x, T): pass""" - self.check(b, a) - - def test_ne_reverse(self): - b = """T != type(x)""" - a = """not isinstance(x, T)""" - self.check(b, a) - - b = """if T != type(x): pass""" - a = """if not isinstance(x, T): pass""" - self.check(b, a) - - def test_ne_expression(self): - b = """type(x+y) != d.get('T')""" - a = """not isinstance(x+y, d.get('T'))""" - self.check(b, a) - - b = """type( x + y) != d.get('T')""" - a = """not isinstance(x + y, d.get('T'))""" - self.check(b, a) - - def test_type_unchanged(self): - a = """type(x).__name__""" - self.unchanged(a) - - def test_sort_list_call(self): - b = """ - v = list(t) - v.sort() - foo(v) - """ - a = """ - v = sorted(t) - foo(v) - """ - self.check(b, a) - - b = """ - v = list(foo(b) + d) - v.sort() - foo(v) - """ - a = """ - v = sorted(foo(b) + d) - foo(v) - """ - self.check(b, a) - - b = """ - while x: - v = list(t) - v.sort() - foo(v) - """ - a = """ - while x: - v = sorted(t) - foo(v) - """ - self.check(b, a) - - b = """ - v = list(t) - # foo - v.sort() - foo(v) - """ - a = """ - v = sorted(t) - # foo - foo(v) - """ - self.check(b, a) - - b = r""" - v = list( t) - v.sort() - foo(v) - """ - a = r""" - v = sorted( t) - foo(v) - """ - self.check(b, a) - - b = r""" - try: - m = list(s) - m.sort() - except: pass - """ - - a = r""" - try: - m = sorted(s) - except: pass - """ - self.check(b, a) - - b = r""" - try: - m = list(s) - # foo - m.sort() - except: pass - """ - - a = r""" - try: - m = sorted(s) - # foo - except: pass - """ - self.check(b, a) - - b = r""" - m = list(s) - # more comments - m.sort()""" - - a = r""" - m = sorted(s) - # more comments""" - self.check(b, a) - - def test_sort_simple_expr(self): - b = """ - v = t - v.sort() - foo(v) - """ - a = """ - v = sorted(t) - foo(v) - """ - self.check(b, a) - - b = """ - v = foo(b) - v.sort() - foo(v) - """ - a = """ - v = sorted(foo(b)) - foo(v) - """ - self.check(b, a) - - b = """ - v = b.keys() - v.sort() - foo(v) - """ - a = """ - v = sorted(b.keys()) - foo(v) - """ - self.check(b, a) - - b = """ - v = foo(b) + d - v.sort() - foo(v) - """ - a = """ - v = sorted(foo(b) + d) - foo(v) - """ - self.check(b, a) - - b = """ - while x: - v = t - v.sort() - foo(v) - """ - a = """ - while x: - v = sorted(t) - foo(v) - """ - self.check(b, a) - - b = """ - v = t - # foo - v.sort() - foo(v) - """ - a = """ - v = sorted(t) - # foo - foo(v) - """ - self.check(b, a) - - b = r""" - v = t - v.sort() - foo(v) - """ - a = r""" - v = sorted(t) - foo(v) - """ - self.check(b, a) - - def test_sort_unchanged(self): - s = """ - v = list(t) - w.sort() - foo(w) - """ - self.unchanged(s) - - s = """ - v = list(t) - v.sort(u) - foo(v) - """ - self.unchanged(s) - -class Test_basestring(FixerTestCase): - fixer = "basestring" - - def test_basestring(self): - b = """isinstance(x, basestring)""" - a = """isinstance(x, str)""" - self.check(b, a) - -class Test_buffer(FixerTestCase): - fixer = "buffer" - - def test_buffer(self): - b = """x = buffer(y)""" - a = """x = memoryview(y)""" - self.check(b, a) - - def test_slicing(self): - b = """buffer(y)[4:5]""" - a = """memoryview(y)[4:5]""" - self.check(b, a) - -class Test_future(FixerTestCase): - fixer = "future" - - def test_future(self): - b = """from __future__ import braces""" - a = """""" - self.check(b, a) - - b = """# comment\nfrom __future__ import braces""" - a = """# comment\n""" - self.check(b, a) - - b = """from __future__ import braces\n# comment""" - a = """\n# comment""" - self.check(b, a) - - def test_run_order(self): - self.assert_runs_after('print') - -class Test_itertools(FixerTestCase): - fixer = "itertools" - - def checkall(self, before, after): - # Because we need to check with and without the itertools prefix - # and on each of the three functions, these loops make it all - # much easier - for i in ('itertools.', ''): - for f in ('map', 'filter', 'zip'): - b = before %(i+'i'+f) - a = after %(f) - self.check(b, a) - - def test_0(self): - # A simple example -- test_1 covers exactly the same thing, - # but it's not quite as clear. - b = "itertools.izip(a, b)" - a = "zip(a, b)" - self.check(b, a) - - def test_1(self): - b = """%s(f, a)""" - a = """%s(f, a)""" - self.checkall(b, a) - - def test_qualified(self): - b = """itertools.ifilterfalse(a, b)""" - a = """itertools.filterfalse(a, b)""" - self.check(b, a) - - b = """itertools.izip_longest(a, b)""" - a = """itertools.zip_longest(a, b)""" - self.check(b, a) - - def test_2(self): - b = """ifilterfalse(a, b)""" - a = """filterfalse(a, b)""" - self.check(b, a) - - b = """izip_longest(a, b)""" - a = """zip_longest(a, b)""" - self.check(b, a) - - def test_space_1(self): - b = """ %s(f, a)""" - a = """ %s(f, a)""" - self.checkall(b, a) - - def test_space_2(self): - b = """ itertools.ifilterfalse(a, b)""" - a = """ itertools.filterfalse(a, b)""" - self.check(b, a) - - b = """ itertools.izip_longest(a, b)""" - a = """ itertools.zip_longest(a, b)""" - self.check(b, a) - - def test_run_order(self): - self.assert_runs_after('map', 'zip', 'filter') - - -class Test_itertools_imports(FixerTestCase): - fixer = 'itertools_imports' - - def test_reduced(self): - b = "from itertools import imap, izip, foo" - a = "from itertools import foo" - self.check(b, a) - - b = "from itertools import bar, imap, izip, foo" - a = "from itertools import bar, foo" - self.check(b, a) - - b = "from itertools import chain, imap, izip" - a = "from itertools import chain" - self.check(b, a) - - def test_comments(self): - b = "#foo\nfrom itertools import imap, izip" - a = "#foo\n" - self.check(b, a) - - def test_none(self): - b = "from itertools import imap, izip" - a = "" - self.check(b, a) - - b = "from itertools import izip" - a = "" - self.check(b, a) - - def test_import_as(self): - b = "from itertools import izip, bar as bang, imap" - a = "from itertools import bar as bang" - self.check(b, a) - - b = "from itertools import izip as _zip, imap, bar" - a = "from itertools import bar" - self.check(b, a) - - b = "from itertools import imap as _map" - a = "" - self.check(b, a) - - b = "from itertools import imap as _map, izip as _zip" - a = "" - self.check(b, a) - - s = "from itertools import bar as bang" - self.unchanged(s) - - def test_ifilter_and_zip_longest(self): - for name in "filterfalse", "zip_longest": - b = "from itertools import i%s" % (name,) - a = "from itertools import %s" % (name,) - self.check(b, a) - - b = "from itertools import imap, i%s, foo" % (name,) - a = "from itertools import %s, foo" % (name,) - self.check(b, a) - - b = "from itertools import bar, i%s, foo" % (name,) - a = "from itertools import bar, %s, foo" % (name,) - self.check(b, a) - - def test_import_star(self): - s = "from itertools import *" - self.unchanged(s) - - - def test_unchanged(self): - s = "from itertools import foo" - self.unchanged(s) - - -class Test_import(FixerTestCase): - fixer = "import" - - def setUp(self): - super(Test_import, self).setUp() - # Need to replace fix_import's exists method - # so we can check that it's doing the right thing - self.files_checked = [] - self.present_files = set() - self.always_exists = True - def fake_exists(name): - self.files_checked.append(name) - return self.always_exists or (name in self.present_files) - - from lib2to3.fixes import fix_import - fix_import.exists = fake_exists - - def tearDown(self): - from lib2to3.fixes import fix_import - fix_import.exists = os.path.exists - - def check_both(self, b, a): - self.always_exists = True - super(Test_import, self).check(b, a) - self.always_exists = False - super(Test_import, self).unchanged(b) - - def test_files_checked(self): - def p(path): - # Takes a unix path and returns a path with correct separators - return os.path.pathsep.join(path.split("/")) - - self.always_exists = False - self.present_files = set(['__init__.py']) - expected_extensions = ('.py', os.path.sep, '.pyc', '.so', '.sl', '.pyd') - names_to_test = (p("/spam/eggs.py"), "ni.py", p("../../shrubbery.py")) - - for name in names_to_test: - self.files_checked = [] - self.filename = name - self.unchanged("import jam") - - if os.path.dirname(name): - name = os.path.dirname(name) + '/jam' - else: - name = 'jam' - expected_checks = set(name + ext for ext in expected_extensions) - expected_checks.add("__init__.py") - - self.assertEqual(set(self.files_checked), expected_checks) - - def test_not_in_package(self): - s = "import bar" - self.always_exists = False - self.present_files = set(["bar.py"]) - self.unchanged(s) - - def test_with_absolute_import_enabled(self): - s = "from __future__ import absolute_import\nimport bar" - self.always_exists = False - self.present_files = set(["__init__.py", "bar.py"]) - self.unchanged(s) - - def test_in_package(self): - b = "import bar" - a = "from . import bar" - self.always_exists = False - self.present_files = set(["__init__.py", "bar.py"]) - self.check(b, a) - - def test_import_from_package(self): - b = "import bar" - a = "from . import bar" - self.always_exists = False - self.present_files = set(["__init__.py", "bar" + os.path.sep]) - self.check(b, a) - - def test_already_relative_import(self): - s = "from . import bar" - self.unchanged(s) - - def test_comments_and_indent(self): - b = "import bar # Foo" - a = "from . import bar # Foo" - self.check(b, a) - - def test_from(self): - b = "from foo import bar, baz" - a = "from .foo import bar, baz" - self.check_both(b, a) - - b = "from foo import bar" - a = "from .foo import bar" - self.check_both(b, a) - - b = "from foo import (bar, baz)" - a = "from .foo import (bar, baz)" - self.check_both(b, a) - - def test_dotted_from(self): - b = "from green.eggs import ham" - a = "from .green.eggs import ham" - self.check_both(b, a) - - def test_from_as(self): - b = "from green.eggs import ham as spam" - a = "from .green.eggs import ham as spam" - self.check_both(b, a) - - def test_import(self): - b = "import foo" - a = "from . import foo" - self.check_both(b, a) - - b = "import foo, bar" - a = "from . import foo, bar" - self.check_both(b, a) - - b = "import foo, bar, x" - a = "from . import foo, bar, x" - self.check_both(b, a) - - b = "import x, y, z" - a = "from . import x, y, z" - self.check_both(b, a) - - def test_import_as(self): - b = "import foo as x" - a = "from . import foo as x" - self.check_both(b, a) - - b = "import a as b, b as c, c as d" - a = "from . import a as b, b as c, c as d" - self.check_both(b, a) - - def test_local_and_absolute(self): - self.always_exists = False - self.present_files = set(["foo.py", "__init__.py"]) - - s = "import foo, bar" - self.warns_unchanged(s, "absolute and local imports together") - - def test_dotted_import(self): - b = "import foo.bar" - a = "from . import foo.bar" - self.check_both(b, a) - - def test_dotted_import_as(self): - b = "import foo.bar as bang" - a = "from . import foo.bar as bang" - self.check_both(b, a) - - def test_prefix(self): - b = """ - # prefix - import foo.bar - """ - a = """ - # prefix - from . import foo.bar - """ - self.check_both(b, a) - - -class Test_set_literal(FixerTestCase): - - fixer = "set_literal" - - def test_basic(self): - b = """set([1, 2, 3])""" - a = """{1, 2, 3}""" - self.check(b, a) - - b = """set((1, 2, 3))""" - a = """{1, 2, 3}""" - self.check(b, a) - - b = """set((1,))""" - a = """{1}""" - self.check(b, a) - - b = """set([1])""" - self.check(b, a) - - b = """set((a, b))""" - a = """{a, b}""" - self.check(b, a) - - b = """set([a, b])""" - self.check(b, a) - - b = """set((a*234, f(args=23)))""" - a = """{a*234, f(args=23)}""" - self.check(b, a) - - b = """set([a*23, f(23)])""" - a = """{a*23, f(23)}""" - self.check(b, a) - - b = """set([a-234**23])""" - a = """{a-234**23}""" - self.check(b, a) - - def test_listcomps(self): - b = """set([x for x in y])""" - a = """{x for x in y}""" - self.check(b, a) - - b = """set([x for x in y if x == m])""" - a = """{x for x in y if x == m}""" - self.check(b, a) - - b = """set([x for x in y for a in b])""" - a = """{x for x in y for a in b}""" - self.check(b, a) - - b = """set([f(x) - 23 for x in y])""" - a = """{f(x) - 23 for x in y}""" - self.check(b, a) - - def test_whitespace(self): - b = """set( [1, 2])""" - a = """{1, 2}""" - self.check(b, a) - - b = """set([1 , 2])""" - a = """{1 , 2}""" - self.check(b, a) - - b = """set([ 1 ])""" - a = """{ 1 }""" - self.check(b, a) - - b = """set( [1] )""" - a = """{1}""" - self.check(b, a) - - b = """set([ 1, 2 ])""" - a = """{ 1, 2 }""" - self.check(b, a) - - b = """set([x for x in y ])""" - a = """{x for x in y }""" - self.check(b, a) - - b = """set( - [1, 2] - ) - """ - a = """{1, 2}\n""" - self.check(b, a) - - def test_comments(self): - b = """set((1, 2)) # Hi""" - a = """{1, 2} # Hi""" - self.check(b, a) - - # This isn't optimal behavior, but the fixer is optional. - b = """ - # Foo - set( # Bar - (1, 2) - ) - """ - a = """ - # Foo - {1, 2} - """ - self.check(b, a) - - def test_unchanged(self): - s = """set()""" - self.unchanged(s) - - s = """set(a)""" - self.unchanged(s) - - s = """set(a, b, c)""" - self.unchanged(s) - - # Don't transform generators because they might have to be lazy. - s = """set(x for x in y)""" - self.unchanged(s) - - s = """set(x for x in y if z)""" - self.unchanged(s) - - s = """set(a*823-23**2 + f(23))""" - self.unchanged(s) - - -class Test_sys_exc(FixerTestCase): - fixer = "sys_exc" - - def test_0(self): - b = "sys.exc_type" - a = "sys.exc_info()[0]" - self.check(b, a) - - def test_1(self): - b = "sys.exc_value" - a = "sys.exc_info()[1]" - self.check(b, a) - - def test_2(self): - b = "sys.exc_traceback" - a = "sys.exc_info()[2]" - self.check(b, a) - - def test_3(self): - b = "sys.exc_type # Foo" - a = "sys.exc_info()[0] # Foo" - self.check(b, a) - - def test_4(self): - b = "sys. exc_type" - a = "sys. exc_info()[0]" - self.check(b, a) - - def test_5(self): - b = "sys .exc_type" - a = "sys .exc_info()[0]" - self.check(b, a) - - -class Test_paren(FixerTestCase): - fixer = "paren" - - def test_0(self): - b = """[i for i in 1, 2 ]""" - a = """[i for i in (1, 2) ]""" - self.check(b, a) - - def test_1(self): - b = """[i for i in 1, 2, ]""" - a = """[i for i in (1, 2,) ]""" - self.check(b, a) - - def test_2(self): - b = """[i for i in 1, 2 ]""" - a = """[i for i in (1, 2) ]""" - self.check(b, a) - - def test_3(self): - b = """[i for i in 1, 2 if i]""" - a = """[i for i in (1, 2) if i]""" - self.check(b, a) - - def test_4(self): - b = """[i for i in 1, 2 ]""" - a = """[i for i in (1, 2) ]""" - self.check(b, a) - - def test_5(self): - b = """(i for i in 1, 2)""" - a = """(i for i in (1, 2))""" - self.check(b, a) - - def test_6(self): - b = """(i for i in 1 ,2 if i)""" - a = """(i for i in (1 ,2) if i)""" - self.check(b, a) - - def test_unchanged_0(self): - s = """[i for i in (1, 2)]""" - self.unchanged(s) - - def test_unchanged_1(self): - s = """[i for i in foo()]""" - self.unchanged(s) - - def test_unchanged_2(self): - s = """[i for i in (1, 2) if nothing]""" - self.unchanged(s) - - def test_unchanged_3(self): - s = """(i for i in (1, 2))""" - self.unchanged(s) - - def test_unchanged_4(self): - s = """[i for i in m]""" - self.unchanged(s) - -class Test_metaclass(FixerTestCase): - - fixer = 'metaclass' - - def test_unchanged(self): - self.unchanged("class X(): pass") - self.unchanged("class X(object): pass") - self.unchanged("class X(object1, object2): pass") - self.unchanged("class X(object1, object2, object3): pass") - self.unchanged("class X(metaclass=Meta): pass") - self.unchanged("class X(b, arg=23, metclass=Meta): pass") - self.unchanged("class X(b, arg=23, metaclass=Meta, other=42): pass") - - s = """ - class X: - def __metaclass__(self): pass - """ - self.unchanged(s) - - s = """ - class X: - a[23] = 74 - """ - self.unchanged(s) - - def test_comments(self): - b = """ - class X: - # hi - __metaclass__ = AppleMeta - """ - a = """ - class X(metaclass=AppleMeta): - # hi - pass - """ - self.check(b, a) - - b = """ - class X: - __metaclass__ = Meta - # Bedtime! - """ - a = """ - class X(metaclass=Meta): - pass - # Bedtime! - """ - self.check(b, a) - - def test_meta(self): - # no-parent class, odd body - b = """ - class X(): - __metaclass__ = Q - pass - """ - a = """ - class X(metaclass=Q): - pass - """ - self.check(b, a) - - # one parent class, no body - b = """class X(object): __metaclass__ = Q""" - a = """class X(object, metaclass=Q): pass""" - self.check(b, a) - - - # one parent, simple body - b = """ - class X(object): - __metaclass__ = Meta - bar = 7 - """ - a = """ - class X(object, metaclass=Meta): - bar = 7 - """ - self.check(b, a) - - b = """ - class X: - __metaclass__ = Meta; x = 4; g = 23 - """ - a = """ - class X(metaclass=Meta): - x = 4; g = 23 - """ - self.check(b, a) - - # one parent, simple body, __metaclass__ last - b = """ - class X(object): - bar = 7 - __metaclass__ = Meta - """ - a = """ - class X(object, metaclass=Meta): - bar = 7 - """ - self.check(b, a) - - # redefining __metaclass__ - b = """ - class X(): - __metaclass__ = A - __metaclass__ = B - bar = 7 - """ - a = """ - class X(metaclass=B): - bar = 7 - """ - self.check(b, a) - - # multiple inheritance, simple body - b = """ - class X(clsA, clsB): - __metaclass__ = Meta - bar = 7 - """ - a = """ - class X(clsA, clsB, metaclass=Meta): - bar = 7 - """ - self.check(b, a) - - # keywords in the class statement - b = """class m(a, arg=23): __metaclass__ = Meta""" - a = """class m(a, arg=23, metaclass=Meta): pass""" - self.check(b, a) - - b = """ - class X(expression(2 + 4)): - __metaclass__ = Meta - """ - a = """ - class X(expression(2 + 4), metaclass=Meta): - pass - """ - self.check(b, a) - - b = """ - class X(expression(2 + 4), x**4): - __metaclass__ = Meta - """ - a = """ - class X(expression(2 + 4), x**4, metaclass=Meta): - pass - """ - self.check(b, a) - - b = """ - class X: - __metaclass__ = Meta - save.py = 23 - """ - a = """ - class X(metaclass=Meta): - save.py = 23 - """ - self.check(b, a) - - -class Test_getcwdu(FixerTestCase): - - fixer = 'getcwdu' - - def test_basic(self): - b = """os.getcwdu""" - a = """os.getcwd""" - self.check(b, a) - - b = """os.getcwdu()""" - a = """os.getcwd()""" - self.check(b, a) - - b = """meth = os.getcwdu""" - a = """meth = os.getcwd""" - self.check(b, a) - - b = """os.getcwdu(args)""" - a = """os.getcwd(args)""" - self.check(b, a) - - def test_comment(self): - b = """os.getcwdu() # Foo""" - a = """os.getcwd() # Foo""" - self.check(b, a) - - def test_unchanged(self): - s = """os.getcwd()""" - self.unchanged(s) - - s = """getcwdu()""" - self.unchanged(s) - - s = """os.getcwdb()""" - self.unchanged(s) - - def test_indentation(self): - b = """ - if 1: - os.getcwdu() - """ - a = """ - if 1: - os.getcwd() - """ - self.check(b, a) - - def test_multilation(self): - b = """os .getcwdu()""" - a = """os .getcwd()""" - self.check(b, a) - - b = """os. getcwdu""" - a = """os. getcwd""" - self.check(b, a) - - b = """os.getcwdu ( )""" - a = """os.getcwd ( )""" - self.check(b, a) - - -class Test_operator(FixerTestCase): - - fixer = "operator" - - def test_operator_isCallable(self): - b = "operator.isCallable(x)" - a = "callable(x)" - self.check(b, a) - - def test_operator_sequenceIncludes(self): - b = "operator.sequenceIncludes(x, y)" - a = "operator.contains(x, y)" - self.check(b, a) - - b = "operator .sequenceIncludes(x, y)" - a = "operator .contains(x, y)" - self.check(b, a) - - b = "operator. sequenceIncludes(x, y)" - a = "operator. contains(x, y)" - self.check(b, a) - - def test_operator_isSequenceType(self): - b = "operator.isSequenceType(x)" - a = "import collections.abc\nisinstance(x, collections.abc.Sequence)" - self.check(b, a) - - def test_operator_isMappingType(self): - b = "operator.isMappingType(x)" - a = "import collections.abc\nisinstance(x, collections.abc.Mapping)" - self.check(b, a) - - def test_operator_isNumberType(self): - b = "operator.isNumberType(x)" - a = "import numbers\nisinstance(x, numbers.Number)" - self.check(b, a) - - def test_operator_repeat(self): - b = "operator.repeat(x, n)" - a = "operator.mul(x, n)" - self.check(b, a) - - b = "operator .repeat(x, n)" - a = "operator .mul(x, n)" - self.check(b, a) - - b = "operator. repeat(x, n)" - a = "operator. mul(x, n)" - self.check(b, a) - - def test_operator_irepeat(self): - b = "operator.irepeat(x, n)" - a = "operator.imul(x, n)" - self.check(b, a) - - b = "operator .irepeat(x, n)" - a = "operator .imul(x, n)" - self.check(b, a) - - b = "operator. irepeat(x, n)" - a = "operator. imul(x, n)" - self.check(b, a) - - def test_bare_isCallable(self): - s = "isCallable(x)" - t = "You should use 'callable(x)' here." - self.warns_unchanged(s, t) - - def test_bare_sequenceIncludes(self): - s = "sequenceIncludes(x, y)" - t = "You should use 'operator.contains(x, y)' here." - self.warns_unchanged(s, t) - - def test_bare_operator_isSequenceType(self): - s = "isSequenceType(z)" - t = "You should use 'isinstance(z, collections.abc.Sequence)' here." - self.warns_unchanged(s, t) - - def test_bare_operator_isMappingType(self): - s = "isMappingType(x)" - t = "You should use 'isinstance(x, collections.abc.Mapping)' here." - self.warns_unchanged(s, t) - - def test_bare_operator_isNumberType(self): - s = "isNumberType(y)" - t = "You should use 'isinstance(y, numbers.Number)' here." - self.warns_unchanged(s, t) - - def test_bare_operator_repeat(self): - s = "repeat(x, n)" - t = "You should use 'operator.mul(x, n)' here." - self.warns_unchanged(s, t) - - def test_bare_operator_irepeat(self): - s = "irepeat(y, 187)" - t = "You should use 'operator.imul(y, 187)' here." - self.warns_unchanged(s, t) - - -class Test_exitfunc(FixerTestCase): - - fixer = "exitfunc" - - def test_simple(self): - b = """ - import sys - sys.exitfunc = my_atexit - """ - a = """ - import sys - import atexit - atexit.register(my_atexit) - """ - self.check(b, a) - - def test_names_import(self): - b = """ - import sys, crumbs - sys.exitfunc = my_func - """ - a = """ - import sys, crumbs, atexit - atexit.register(my_func) - """ - self.check(b, a) - - def test_complex_expression(self): - b = """ - import sys - sys.exitfunc = do(d)/a()+complex(f=23, g=23)*expression - """ - a = """ - import sys - import atexit - atexit.register(do(d)/a()+complex(f=23, g=23)*expression) - """ - self.check(b, a) - - def test_comments(self): - b = """ - import sys # Foo - sys.exitfunc = f # Blah - """ - a = """ - import sys - import atexit # Foo - atexit.register(f) # Blah - """ - self.check(b, a) - - b = """ - import apples, sys, crumbs, larry # Pleasant comments - sys.exitfunc = func - """ - a = """ - import apples, sys, crumbs, larry, atexit # Pleasant comments - atexit.register(func) - """ - self.check(b, a) - - def test_in_a_function(self): - b = """ - import sys - def f(): - sys.exitfunc = func - """ - a = """ - import sys - import atexit - def f(): - atexit.register(func) - """ - self.check(b, a) - - def test_no_sys_import(self): - b = """sys.exitfunc = f""" - a = """atexit.register(f)""" - msg = ("Can't find sys import; Please add an atexit import at the " - "top of your file.") - self.warns(b, a, msg) - - - def test_unchanged(self): - s = """f(sys.exitfunc)""" - self.unchanged(s) - - -class Test_asserts(FixerTestCase): - - fixer = "asserts" - - def test_deprecated_names(self): - tests = [ - ('self.assert_(True)', 'self.assertTrue(True)'), - ('self.assertEquals(2, 2)', 'self.assertEqual(2, 2)'), - ('self.assertNotEquals(2, 3)', 'self.assertNotEqual(2, 3)'), - ('self.assertAlmostEquals(2, 3)', 'self.assertAlmostEqual(2, 3)'), - ('self.assertNotAlmostEquals(2, 8)', 'self.assertNotAlmostEqual(2, 8)'), - ('self.failUnlessEqual(2, 2)', 'self.assertEqual(2, 2)'), - ('self.failIfEqual(2, 3)', 'self.assertNotEqual(2, 3)'), - ('self.failUnlessAlmostEqual(2, 3)', 'self.assertAlmostEqual(2, 3)'), - ('self.failIfAlmostEqual(2, 8)', 'self.assertNotAlmostEqual(2, 8)'), - ('self.failUnless(True)', 'self.assertTrue(True)'), - ('self.failUnlessRaises(foo)', 'self.assertRaises(foo)'), - ('self.failIf(False)', 'self.assertFalse(False)'), - ] - for b, a in tests: - self.check(b, a) - - def test_variants(self): - b = 'eq = self.assertEquals' - a = 'eq = self.assertEqual' - self.check(b, a) - b = 'self.assertEquals(2, 3, msg="fail")' - a = 'self.assertEqual(2, 3, msg="fail")' - self.check(b, a) - b = 'self.assertEquals(2, 3, msg="fail") # foo' - a = 'self.assertEqual(2, 3, msg="fail") # foo' - self.check(b, a) - b = 'self.assertEquals (2, 3)' - a = 'self.assertEqual (2, 3)' - self.check(b, a) - b = ' self.assertEquals (2, 3)' - a = ' self.assertEqual (2, 3)' - self.check(b, a) - b = 'with self.failUnlessRaises(Explosion): explode()' - a = 'with self.assertRaises(Explosion): explode()' - self.check(b, a) - b = 'with self.failUnlessRaises(Explosion) as cm: explode()' - a = 'with self.assertRaises(Explosion) as cm: explode()' - self.check(b, a) - - def test_unchanged(self): - self.unchanged('self.assertEqualsOnSaturday') - self.unchanged('self.assertEqualsOnSaturday(3, 5)') diff --git a/Lib/test/test_lib2to3/test_main.py b/Lib/test/test_lib2to3/test_main.py deleted file mode 100644 index a33c45c50a0de2..00000000000000 --- a/Lib/test/test_lib2to3/test_main.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -import codecs -import io -import logging -import os -import re -import shutil -import sys -import tempfile -import unittest - -from lib2to3 import main - - -TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") -PY2_TEST_MODULE = os.path.join(TEST_DATA_DIR, "py2_test_grammar.py") - - -class TestMain(unittest.TestCase): - - def setUp(self): - self.temp_dir = None # tearDown() will rmtree this directory if set. - - def tearDown(self): - # Clean up logging configuration down by main. - del logging.root.handlers[:] - if self.temp_dir: - shutil.rmtree(self.temp_dir) - - def run_2to3_capture(self, args, in_capture, out_capture, err_capture): - save_stdin = sys.stdin - save_stdout = sys.stdout - save_stderr = sys.stderr - sys.stdin = in_capture - sys.stdout = out_capture - sys.stderr = err_capture - try: - return main.main("lib2to3.fixes", args) - finally: - sys.stdin = save_stdin - sys.stdout = save_stdout - sys.stderr = save_stderr - - def test_unencodable_diff(self): - input_stream = io.StringIO("print 'nothing'\nprint u'über'\n") - out = io.BytesIO() - out_enc = codecs.getwriter("ascii")(out) - err = io.StringIO() - ret = self.run_2to3_capture(["-"], input_stream, out_enc, err) - self.assertEqual(ret, 0) - output = out.getvalue().decode("ascii") - self.assertIn("-print 'nothing'", output) - self.assertIn("WARNING: couldn't encode 's diff for " - "your terminal", err.getvalue()) - - def setup_test_source_trees(self): - """Setup a test source tree and output destination tree.""" - self.temp_dir = tempfile.mkdtemp() # tearDown() cleans this up. - self.py2_src_dir = os.path.join(self.temp_dir, "python2_project") - self.py3_dest_dir = os.path.join(self.temp_dir, "python3_project") - os.mkdir(self.py2_src_dir) - os.mkdir(self.py3_dest_dir) - # Turn it into a package with a few files. - self.setup_files = [] - open(os.path.join(self.py2_src_dir, "__init__.py"), "w").close() - self.setup_files.append("__init__.py") - shutil.copy(PY2_TEST_MODULE, self.py2_src_dir) - self.setup_files.append(os.path.basename(PY2_TEST_MODULE)) - self.trivial_py2_file = os.path.join(self.py2_src_dir, "trivial.py") - self.init_py2_file = os.path.join(self.py2_src_dir, "__init__.py") - with open(self.trivial_py2_file, "w") as trivial: - trivial.write("print 'I need a simple conversion.'") - self.setup_files.append("trivial.py") - - def test_filename_changing_on_output_single_dir(self): - """2to3 a single directory with a new output dir and suffix.""" - self.setup_test_source_trees() - out = io.StringIO() - err = io.StringIO() - suffix = "TEST" - ret = self.run_2to3_capture( - ["-n", "--add-suffix", suffix, "--write-unchanged-files", - "--no-diffs", "--output-dir", - self.py3_dest_dir, self.py2_src_dir], - io.StringIO(""), out, err) - self.assertEqual(ret, 0) - stderr = err.getvalue() - self.assertIn(" implies -w.", stderr) - self.assertIn( - "Output in %r will mirror the input directory %r layout" % ( - self.py3_dest_dir, self.py2_src_dir), stderr) - self.assertEqual(set(name+suffix for name in self.setup_files), - set(os.listdir(self.py3_dest_dir))) - for name in self.setup_files: - self.assertIn("Writing converted %s to %s" % ( - os.path.join(self.py2_src_dir, name), - os.path.join(self.py3_dest_dir, name+suffix)), stderr) - sep = re.escape(os.sep) - self.assertRegex( - stderr, r"No changes to .*/__init__\.py".replace("/", sep)) - self.assertNotRegex( - stderr, r"No changes to .*/trivial\.py".replace("/", sep)) - - def test_filename_changing_on_output_two_files(self): - """2to3 two files in one directory with a new output dir.""" - self.setup_test_source_trees() - err = io.StringIO() - py2_files = [self.trivial_py2_file, self.init_py2_file] - expected_files = set(os.path.basename(name) for name in py2_files) - ret = self.run_2to3_capture( - ["-n", "-w", "--write-unchanged-files", - "--no-diffs", "--output-dir", self.py3_dest_dir] + py2_files, - io.StringIO(""), io.StringIO(), err) - self.assertEqual(ret, 0) - stderr = err.getvalue() - self.assertIn( - "Output in %r will mirror the input directory %r layout" % ( - self.py3_dest_dir, self.py2_src_dir), stderr) - self.assertEqual(expected_files, set(os.listdir(self.py3_dest_dir))) - - def test_filename_changing_on_output_single_file(self): - """2to3 a single file with a new output dir.""" - self.setup_test_source_trees() - err = io.StringIO() - ret = self.run_2to3_capture( - ["-n", "-w", "--no-diffs", "--output-dir", self.py3_dest_dir, - self.trivial_py2_file], - io.StringIO(""), io.StringIO(), err) - self.assertEqual(ret, 0) - stderr = err.getvalue() - self.assertIn( - "Output in %r will mirror the input directory %r layout" % ( - self.py3_dest_dir, self.py2_src_dir), stderr) - self.assertEqual(set([os.path.basename(self.trivial_py2_file)]), - set(os.listdir(self.py3_dest_dir))) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_lib2to3/test_parser.py b/Lib/test/test_lib2to3/test_parser.py deleted file mode 100644 index 2c798b181fdbda..00000000000000 --- a/Lib/test/test_lib2to3/test_parser.py +++ /dev/null @@ -1,718 +0,0 @@ -"""Test suite for 2to3's parser and grammar files. - -This is the place to add tests for changes to 2to3's grammar, such as those -merging the grammars for Python 2 and 3. In addition to specific tests for -parts of the grammar we've changed, we also make sure we can parse the -test_grammar.py files from both Python 2 and Python 3. -""" - -# Testing imports -from . import support -from .support import driver, driver_no_print_statement - -# Python imports -import difflib -import importlib -import operator -import os -import pickle -import shutil -import subprocess -import sys -import tempfile -import test.support -import unittest - -# Local imports -from lib2to3.pgen2 import driver as pgen2_driver -from lib2to3.pgen2 import tokenize -from lib2to3.pgen2.parse import ParseError -from lib2to3.pygram import python_symbols as syms - - -class TestDriver(support.TestCase): - - def test_formfeed(self): - s = """print 1\n\x0Cprint 2\n""" - t = driver.parse_string(s) - self.assertEqual(t.children[0].children[0].type, syms.print_stmt) - self.assertEqual(t.children[1].children[0].type, syms.print_stmt) - - -class TestPgen2Caching(support.TestCase): - def test_load_grammar_from_txt_file(self): - pgen2_driver.load_grammar(support.grammar_path, save=False, force=True) - - def test_load_grammar_from_pickle(self): - # Make a copy of the grammar file in a temp directory we are - # guaranteed to be able to write to. - tmpdir = tempfile.mkdtemp() - try: - grammar_copy = os.path.join( - tmpdir, os.path.basename(support.grammar_path)) - shutil.copy(support.grammar_path, grammar_copy) - pickle_name = pgen2_driver._generate_pickle_name(grammar_copy) - - pgen2_driver.load_grammar(grammar_copy, save=True, force=True) - self.assertTrue(os.path.exists(pickle_name)) - - os.unlink(grammar_copy) # Only the pickle remains... - pgen2_driver.load_grammar(grammar_copy, save=False, force=False) - finally: - shutil.rmtree(tmpdir) - - @unittest.skipIf(sys.executable is None, 'sys.executable required') - @unittest.skipIf( - sys.platform in {'emscripten', 'wasi'}, 'requires working subprocess' - ) - def test_load_grammar_from_subprocess(self): - tmpdir = tempfile.mkdtemp() - tmpsubdir = os.path.join(tmpdir, 'subdir') - try: - os.mkdir(tmpsubdir) - grammar_base = os.path.basename(support.grammar_path) - grammar_copy = os.path.join(tmpdir, grammar_base) - grammar_sub_copy = os.path.join(tmpsubdir, grammar_base) - shutil.copy(support.grammar_path, grammar_copy) - shutil.copy(support.grammar_path, grammar_sub_copy) - pickle_name = pgen2_driver._generate_pickle_name(grammar_copy) - pickle_sub_name = pgen2_driver._generate_pickle_name( - grammar_sub_copy) - self.assertNotEqual(pickle_name, pickle_sub_name) - - # Generate a pickle file from this process. - pgen2_driver.load_grammar(grammar_copy, save=True, force=True) - self.assertTrue(os.path.exists(pickle_name)) - - # Generate a new pickle file in a subprocess with a most likely - # different hash randomization seed. - sub_env = dict(os.environ) - sub_env['PYTHONHASHSEED'] = 'random' - code = """ -from lib2to3.pgen2 import driver as pgen2_driver -pgen2_driver.load_grammar(%r, save=True, force=True) - """ % (grammar_sub_copy,) - cmd = [sys.executable, - '-Wignore:lib2to3:DeprecationWarning', - '-c', code] - subprocess.check_call( cmd, env=sub_env) - self.assertTrue(os.path.exists(pickle_sub_name)) - - with open(pickle_name, 'rb') as pickle_f_1, \ - open(pickle_sub_name, 'rb') as pickle_f_2: - self.assertEqual( - pickle_f_1.read(), pickle_f_2.read(), - msg='Grammar caches generated using different hash seeds' - ' were not identical.') - finally: - shutil.rmtree(tmpdir) - - def test_load_packaged_grammar(self): - modname = __name__ + '.load_test' - class MyLoader: - def get_data(self, where): - return pickle.dumps({'elephant': 19}) - class MyModule: - __file__ = 'parsertestmodule' - __spec__ = importlib.util.spec_from_loader(modname, MyLoader()) - sys.modules[modname] = MyModule() - self.addCleanup(operator.delitem, sys.modules, modname) - g = pgen2_driver.load_packaged_grammar(modname, 'Grammar.txt') - self.assertEqual(g.elephant, 19) - - -class GrammarTest(support.TestCase): - def validate(self, code): - support.parse_string(code) - - def invalid_syntax(self, code): - try: - self.validate(code) - except ParseError: - pass - else: - raise AssertionError("Syntax shouldn't have been valid") - - -class TestMatrixMultiplication(GrammarTest): - def test_matrix_multiplication_operator(self): - self.validate("a @ b") - self.validate("a @= b") - - -class TestYieldFrom(GrammarTest): - def test_yield_from(self): - self.validate("yield from x") - self.validate("(yield from x) + y") - self.invalid_syntax("yield from") - - -class TestAsyncAwait(GrammarTest): - def test_await_expr(self): - self.validate("""async def foo(): - await x - """) - - self.validate("""async def foo(): - [i async for i in b] - """) - - self.validate("""async def foo(): - {i for i in b - async for i in a if await i - for b in i} - """) - - self.validate("""async def foo(): - [await i for i in b if await c] - """) - - self.validate("""async def foo(): - [ i for i in b if c] - """) - - self.validate("""async def foo(): - - def foo(): pass - - def foo(): pass - - await x - """) - - self.validate("""async def foo(): return await a""") - - self.validate("""def foo(): - def foo(): pass - async def foo(): await x - """) - - self.invalid_syntax("await x") - self.invalid_syntax("""def foo(): - await x""") - - self.invalid_syntax("""def foo(): - def foo(): pass - async def foo(): pass - await x - """) - - def test_async_var(self): - self.validate("""async = 1""") - self.validate("""await = 1""") - self.validate("""def async(): pass""") - - def test_async_for(self): - self.validate("""async def foo(): - async for a in b: pass""") - - def test_async_with(self): - self.validate("""async def foo(): - async with a: pass""") - - self.invalid_syntax("""def foo(): - async with a: pass""") - - def test_async_generator(self): - self.validate( - """async def foo(): - return (i * 2 async for i in arange(42))""" - ) - self.validate( - """def foo(): - return (i * 2 async for i in arange(42))""" - ) - - -class TestRaiseChanges(GrammarTest): - def test_2x_style_1(self): - self.validate("raise") - - def test_2x_style_2(self): - self.validate("raise E, V") - - def test_2x_style_3(self): - self.validate("raise E, V, T") - - def test_2x_style_invalid_1(self): - self.invalid_syntax("raise E, V, T, Z") - - def test_3x_style(self): - self.validate("raise E1 from E2") - - def test_3x_style_invalid_1(self): - self.invalid_syntax("raise E, V from E1") - - def test_3x_style_invalid_2(self): - self.invalid_syntax("raise E from E1, E2") - - def test_3x_style_invalid_3(self): - self.invalid_syntax("raise from E1, E2") - - def test_3x_style_invalid_4(self): - self.invalid_syntax("raise E from") - - -# Modelled after Lib/test/test_grammar.py:TokenTests.test_funcdef issue2292 -# and Lib/test/text_parser.py test_list_displays, test_set_displays, -# test_dict_displays, test_argument_unpacking, ... changes. -class TestUnpackingGeneralizations(GrammarTest): - def test_mid_positional_star(self): - self.validate("""func(1, *(2, 3), 4)""") - - def test_double_star_dict_literal(self): - self.validate("""func(**{'eggs':'scrambled', 'spam':'fried'})""") - - def test_double_star_dict_literal_after_keywords(self): - self.validate("""func(spam='fried', **{'eggs':'scrambled'})""") - - def test_double_star_expression(self): - self.validate("""func(**{'a':2} or {})""") - self.validate("""func(**() or {})""") - - def test_star_expression(self): - self.validate("""func(*[] or [2])""") - - def test_list_display(self): - self.validate("""[*{2}, 3, *[4]]""") - - def test_set_display(self): - self.validate("""{*{2}, 3, *[4]}""") - - def test_dict_display_1(self): - self.validate("""{**{}}""") - - def test_dict_display_2(self): - self.validate("""{**{}, 3:4, **{5:6, 7:8}}""") - - def test_complex_star_expression(self): - self.validate("func(* [] or [1])") - - def test_complex_double_star_expression(self): - self.validate("func(**{1: 3} if False else {x: x for x in range(3)})") - - def test_argument_unpacking_1(self): - self.validate("""f(a, *b, *c, d)""") - - def test_argument_unpacking_2(self): - self.validate("""f(**a, **b)""") - - def test_argument_unpacking_3(self): - self.validate("""f(2, *a, *b, **b, **c, **d)""") - - def test_trailing_commas_1(self): - self.validate("def f(a, b): call(a, b)") - self.validate("def f(a, b,): call(a, b,)") - - def test_trailing_commas_2(self): - self.validate("def f(a, *b): call(a, *b)") - self.validate("def f(a, *b,): call(a, *b,)") - - def test_trailing_commas_3(self): - self.validate("def f(a, b=1): call(a, b=1)") - self.validate("def f(a, b=1,): call(a, b=1,)") - - def test_trailing_commas_4(self): - self.validate("def f(a, **b): call(a, **b)") - self.validate("def f(a, **b,): call(a, **b,)") - - def test_trailing_commas_5(self): - self.validate("def f(*a, b=1): call(*a, b=1)") - self.validate("def f(*a, b=1,): call(*a, b=1,)") - - def test_trailing_commas_6(self): - self.validate("def f(*a, **b): call(*a, **b)") - self.validate("def f(*a, **b,): call(*a, **b,)") - - def test_trailing_commas_7(self): - self.validate("def f(*, b=1): call(*b)") - self.validate("def f(*, b=1,): call(*b,)") - - def test_trailing_commas_8(self): - self.validate("def f(a=1, b=2): call(a=1, b=2)") - self.validate("def f(a=1, b=2,): call(a=1, b=2,)") - - def test_trailing_commas_9(self): - self.validate("def f(a=1, **b): call(a=1, **b)") - self.validate("def f(a=1, **b,): call(a=1, **b,)") - - def test_trailing_commas_lambda_1(self): - self.validate("f = lambda a, b: call(a, b)") - self.validate("f = lambda a, b,: call(a, b,)") - - def test_trailing_commas_lambda_2(self): - self.validate("f = lambda a, *b: call(a, *b)") - self.validate("f = lambda a, *b,: call(a, *b,)") - - def test_trailing_commas_lambda_3(self): - self.validate("f = lambda a, b=1: call(a, b=1)") - self.validate("f = lambda a, b=1,: call(a, b=1,)") - - def test_trailing_commas_lambda_4(self): - self.validate("f = lambda a, **b: call(a, **b)") - self.validate("f = lambda a, **b,: call(a, **b,)") - - def test_trailing_commas_lambda_5(self): - self.validate("f = lambda *a, b=1: call(*a, b=1)") - self.validate("f = lambda *a, b=1,: call(*a, b=1,)") - - def test_trailing_commas_lambda_6(self): - self.validate("f = lambda *a, **b: call(*a, **b)") - self.validate("f = lambda *a, **b,: call(*a, **b,)") - - def test_trailing_commas_lambda_7(self): - self.validate("f = lambda *, b=1: call(*b)") - self.validate("f = lambda *, b=1,: call(*b,)") - - def test_trailing_commas_lambda_8(self): - self.validate("f = lambda a=1, b=2: call(a=1, b=2)") - self.validate("f = lambda a=1, b=2,: call(a=1, b=2,)") - - def test_trailing_commas_lambda_9(self): - self.validate("f = lambda a=1, **b: call(a=1, **b)") - self.validate("f = lambda a=1, **b,: call(a=1, **b,)") - - -# Adapted from Python 3's Lib/test/test_grammar.py:GrammarTests.testFuncdef -class TestFunctionAnnotations(GrammarTest): - def test_1(self): - self.validate("""def f(x) -> list: pass""") - - def test_2(self): - self.validate("""def f(x:int): pass""") - - def test_3(self): - self.validate("""def f(*x:str): pass""") - - def test_4(self): - self.validate("""def f(**x:float): pass""") - - def test_5(self): - self.validate("""def f(x, y:1+2): pass""") - - def test_6(self): - self.validate("""def f(a, (b:1, c:2, d)): pass""") - - def test_7(self): - self.validate("""def f(a, (b:1, c:2, d), e:3=4, f=5, *g:6): pass""") - - def test_8(self): - s = """def f(a, (b:1, c:2, d), e:3=4, f=5, - *g:6, h:7, i=8, j:9=10, **k:11) -> 12: pass""" - self.validate(s) - - def test_9(self): - s = """def f( - a: str, - b: int, - *, - c: bool = False, - **kwargs, - ) -> None: - call(c=c, **kwargs,)""" - self.validate(s) - - def test_10(self): - s = """def f( - a: str, - ) -> None: - call(a,)""" - self.validate(s) - - def test_11(self): - s = """def f( - a: str = '', - ) -> None: - call(a=a,)""" - self.validate(s) - - def test_12(self): - s = """def f( - *args: str, - ) -> None: - call(*args,)""" - self.validate(s) - - def test_13(self): - self.validate("def f(a: str, b: int) -> None: call(a, b)") - self.validate("def f(a: str, b: int,) -> None: call(a, b,)") - - def test_14(self): - self.validate("def f(a: str, *b: int) -> None: call(a, *b)") - self.validate("def f(a: str, *b: int,) -> None: call(a, *b,)") - - def test_15(self): - self.validate("def f(a: str, b: int=1) -> None: call(a, b=1)") - self.validate("def f(a: str, b: int=1,) -> None: call(a, b=1,)") - - def test_16(self): - self.validate("def f(a: str, **b: int) -> None: call(a, **b)") - self.validate("def f(a: str, **b: int,) -> None: call(a, **b,)") - - def test_17(self): - self.validate("def f(*a: str, b: int=1) -> None: call(*a, b=1)") - self.validate("def f(*a: str, b: int=1,) -> None: call(*a, b=1,)") - - def test_18(self): - self.validate("def f(*a: str, **b: int) -> None: call(*a, **b)") - self.validate("def f(*a: str, **b: int,) -> None: call(*a, **b,)") - - def test_19(self): - self.validate("def f(*, b: int=1) -> None: call(*b)") - self.validate("def f(*, b: int=1,) -> None: call(*b,)") - - def test_20(self): - self.validate("def f(a: str='', b: int=2) -> None: call(a=a, b=2)") - self.validate("def f(a: str='', b: int=2,) -> None: call(a=a, b=2,)") - - def test_21(self): - self.validate("def f(a: str='', **b: int) -> None: call(a=a, **b)") - self.validate("def f(a: str='', **b: int,) -> None: call(a=a, **b,)") - - -# Adapted from Python 3's Lib/test/test_grammar.py:GrammarTests.test_var_annot -class TestVarAnnotations(GrammarTest): - def test_1(self): - self.validate("var1: int = 5") - - def test_2(self): - self.validate("var2: [int, str]") - - def test_3(self): - self.validate("def f():\n" - " st: str = 'Hello'\n" - " a.b: int = (1, 2)\n" - " return st\n") - - def test_4(self): - self.validate("def fbad():\n" - " x: int\n" - " print(x)\n") - - def test_5(self): - self.validate("class C:\n" - " x: int\n" - " s: str = 'attr'\n" - " z = 2\n" - " def __init__(self, x):\n" - " self.x: int = x\n") - - def test_6(self): - self.validate("lst: List[int] = []") - - -class TestExcept(GrammarTest): - def test_new(self): - s = """ - try: - x - except E as N: - y""" - self.validate(s) - - def test_old(self): - s = """ - try: - x - except E, N: - y""" - self.validate(s) - - -class TestStringLiterals(GrammarTest): - prefixes = ("'", '"', - "r'", 'r"', "R'", 'R"', - "u'", 'u"', "U'", 'U"', - "b'", 'b"', "B'", 'B"', - "f'", 'f"', "F'", 'F"', - "ur'", 'ur"', "Ur'", 'Ur"', - "uR'", 'uR"', "UR'", 'UR"', - "br'", 'br"', "Br'", 'Br"', - "bR'", 'bR"', "BR'", 'BR"', - "rb'", 'rb"', "Rb'", 'Rb"', - "rB'", 'rB"', "RB'", 'RB"',) - - def test_lit(self): - for pre in self.prefixes: - single = "{p}spamspamspam{s}".format(p=pre, s=pre[-1]) - self.validate(single) - triple = "{p}{s}{s}eggs{s}{s}{s}".format(p=pre, s=pre[-1]) - self.validate(triple) - - -# Adapted from Python 3's Lib/test/test_grammar.py:GrammarTests.testAtoms -class TestSetLiteral(GrammarTest): - def test_1(self): - self.validate("""x = {'one'}""") - - def test_2(self): - self.validate("""x = {'one', 1,}""") - - def test_3(self): - self.validate("""x = {'one', 'two', 'three'}""") - - def test_4(self): - self.validate("""x = {2, 3, 4,}""") - - -# Adapted from Python 3's Lib/test/test_unicode_identifiers.py and -# Lib/test/test_tokenize.py:TokenizeTest.test_non_ascii_identifiers -class TestIdentifier(GrammarTest): - def test_non_ascii_identifiers(self): - self.validate("Örter = 'places'\ngrün = 'green'") - self.validate("蟒 = a蟒 = 锦蛇 = 1") - self.validate("µ = aµ = µµ = 1") - self.validate("𝔘𝔫𝔦𝔠𝔬𝔡𝔢 = a_𝔘𝔫𝔦𝔠𝔬𝔡𝔢 = 1") - - -class TestNumericLiterals(GrammarTest): - def test_new_octal_notation(self): - self.validate("""0o7777777777777""") - self.invalid_syntax("""0o7324528887""") - - def test_new_binary_notation(self): - self.validate("""0b101010""") - self.invalid_syntax("""0b0101021""") - - -class TestClassDef(GrammarTest): - def test_new_syntax(self): - self.validate("class B(t=7): pass") - self.validate("class B(t, *args): pass") - self.validate("class B(t, **kwargs): pass") - self.validate("class B(t, *args, **kwargs): pass") - self.validate("class B(t, y=9, *args, **kwargs,): pass") - - -class TestParserIdempotency(support.TestCase): - - """A cut-down version of pytree_idempotency.py.""" - - def parse_file(self, filepath): - if test.support.verbose: - print(f"Parse file: {filepath}") - with open(filepath, "rb") as fp: - encoding = tokenize.detect_encoding(fp.readline)[0] - self.assertIsNotNone(encoding, - "can't detect encoding for %s" % filepath) - with open(filepath, "r", encoding=encoding) as fp: - source = fp.read() - try: - tree = driver.parse_string(source) - except ParseError: - try: - tree = driver_no_print_statement.parse_string(source) - except ParseError as err: - self.fail('ParseError on file %s (%s)' % (filepath, err)) - new = str(tree) - if new != source: - print(diff_texts(source, new, filepath)) - self.fail("Idempotency failed: %s" % filepath) - - def test_all_project_files(self): - for filepath in support.all_project_files(): - with self.subTest(filepath=filepath): - self.parse_file(filepath) - - def test_extended_unpacking(self): - driver.parse_string("a, *b, c = x\n") - driver.parse_string("[*a, b] = x\n") - driver.parse_string("(z, *y, w) = m\n") - driver.parse_string("for *z, m in d: pass\n") - - -class TestLiterals(GrammarTest): - - def validate(self, s): - driver.parse_string(support.dedent(s) + "\n\n") - - def test_multiline_bytes_literals(self): - s = """ - md5test(b"\xaa" * 80, - (b"Test Using Larger Than Block-Size Key " - b"and Larger Than One Block-Size Data"), - "6f630fad67cda0ee1fb1f562db3aa53e") - """ - self.validate(s) - - def test_multiline_bytes_tripquote_literals(self): - s = ''' - b""" - - - """ - ''' - self.validate(s) - - def test_multiline_str_literals(self): - s = """ - md5test("\xaa" * 80, - ("Test Using Larger Than Block-Size Key " - "and Larger Than One Block-Size Data"), - "6f630fad67cda0ee1fb1f562db3aa53e") - """ - self.validate(s) - - -class TestNamedAssignments(GrammarTest): - """Also known as the walrus operator.""" - - def test_named_assignment_if(self): - driver.parse_string("if f := x(): pass\n") - - def test_named_assignment_while(self): - driver.parse_string("while f := x(): pass\n") - - def test_named_assignment_generator(self): - driver.parse_string("any((lastNum := num) == 1 for num in [1, 2, 3])\n") - - def test_named_assignment_listcomp(self): - driver.parse_string("[(lastNum := num) == 1 for num in [1, 2, 3]]\n") - - -class TestPositionalOnlyArgs(GrammarTest): - - def test_one_pos_only_arg(self): - driver.parse_string("def one_pos_only_arg(a, /): pass\n") - - def test_all_markers(self): - driver.parse_string( - "def all_markers(a, b=2, /, c, d=4, *, e=5, f): pass\n") - - def test_all_with_args_and_kwargs(self): - driver.parse_string( - """def all_markers_with_args_and_kwargs( - aa, b, /, _cc, d, *args, e, f_f, **kwargs, - ): - pass\n""") - - def test_lambda_soup(self): - driver.parse_string( - "lambda a, b, /, c, d, *args, e, f, **kw: kw\n") - - def test_only_positional_or_keyword(self): - driver.parse_string("def func(a,b,/,*,g,e=3): pass\n") - - -class TestPickleableException(unittest.TestCase): - def test_ParseError(self): - err = ParseError('msg', 2, None, (1, 'context')) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - err2 = pickle.loads(pickle.dumps(err, protocol=proto)) - self.assertEqual(err.args, err2.args) - self.assertEqual(err.msg, err2.msg) - self.assertEqual(err.type, err2.type) - self.assertEqual(err.value, err2.value) - self.assertEqual(err.context, err2.context) - - -def diff_texts(a, b, filename): - a = a.splitlines() - b = b.splitlines() - return difflib.unified_diff(a, b, filename, filename, - "(original)", "(reserialized)", - lineterm="") - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_lib2to3/test_pytree.py b/Lib/test/test_lib2to3/test_pytree.py deleted file mode 100644 index 177126d5452910..00000000000000 --- a/Lib/test/test_lib2to3/test_pytree.py +++ /dev/null @@ -1,472 +0,0 @@ -# Copyright 2006 Google, Inc. All Rights Reserved. -# Licensed to PSF under a Contributor Agreement. - -"""Unit tests for pytree.py. - -NOTE: Please *don't* add doc strings to individual test methods! -In verbose mode, printing of the module, class and method name is much -more helpful than printing of (the first line of) the docstring, -especially when debugging a test. -""" - -# Testing imports -from . import support - -from lib2to3 import pytree - -try: - sorted -except NameError: - def sorted(lst): - l = list(lst) - l.sort() - return l - -class TestNodes(support.TestCase): - - """Unit tests for nodes (Base, Leaf, Node).""" - - def test_instantiate_base(self): - if __debug__: - # Test that instantiating Base() raises an AssertionError - self.assertRaises(AssertionError, pytree.Base) - - def test_leaf(self): - l1 = pytree.Leaf(100, "foo") - self.assertEqual(l1.type, 100) - self.assertEqual(l1.value, "foo") - - def test_leaf_repr(self): - l1 = pytree.Leaf(100, "foo") - self.assertEqual(repr(l1), "Leaf(100, 'foo')") - - def test_leaf_str(self): - l1 = pytree.Leaf(100, "foo") - self.assertEqual(str(l1), "foo") - l2 = pytree.Leaf(100, "foo", context=(" ", (10, 1))) - self.assertEqual(str(l2), " foo") - - def test_leaf_str_numeric_value(self): - # Make sure that the Leaf's value is stringified. Failing to - # do this can cause a TypeError in certain situations. - l1 = pytree.Leaf(2, 5) - l1.prefix = "foo_" - self.assertEqual(str(l1), "foo_5") - - def test_leaf_equality(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "foo", context=(" ", (1, 0))) - self.assertEqual(l1, l2) - l3 = pytree.Leaf(101, "foo") - l4 = pytree.Leaf(100, "bar") - self.assertNotEqual(l1, l3) - self.assertNotEqual(l1, l4) - - def test_leaf_prefix(self): - l1 = pytree.Leaf(100, "foo") - self.assertEqual(l1.prefix, "") - self.assertFalse(l1.was_changed) - l1.prefix = " ##\n\n" - self.assertEqual(l1.prefix, " ##\n\n") - self.assertTrue(l1.was_changed) - - def test_node(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(200, "bar") - n1 = pytree.Node(1000, [l1, l2]) - self.assertEqual(n1.type, 1000) - self.assertEqual(n1.children, [l1, l2]) - - def test_node_repr(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar", context=(" ", (1, 0))) - n1 = pytree.Node(1000, [l1, l2]) - self.assertEqual(repr(n1), - "Node(1000, [%s, %s])" % (repr(l1), repr(l2))) - - def test_node_str(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar", context=(" ", (1, 0))) - n1 = pytree.Node(1000, [l1, l2]) - self.assertEqual(str(n1), "foo bar") - - def test_node_prefix(self): - l1 = pytree.Leaf(100, "foo") - self.assertEqual(l1.prefix, "") - n1 = pytree.Node(1000, [l1]) - self.assertEqual(n1.prefix, "") - n1.prefix = " " - self.assertEqual(n1.prefix, " ") - self.assertEqual(l1.prefix, " ") - - def test_get_suffix(self): - l1 = pytree.Leaf(100, "foo", prefix="a") - l2 = pytree.Leaf(100, "bar", prefix="b") - n1 = pytree.Node(1000, [l1, l2]) - - self.assertEqual(l1.get_suffix(), l2.prefix) - self.assertEqual(l2.get_suffix(), "") - self.assertEqual(n1.get_suffix(), "") - - l3 = pytree.Leaf(100, "bar", prefix="c") - n2 = pytree.Node(1000, [n1, l3]) - - self.assertEqual(n1.get_suffix(), l3.prefix) - self.assertEqual(l3.get_suffix(), "") - self.assertEqual(n2.get_suffix(), "") - - def test_node_equality(self): - n1 = pytree.Node(1000, ()) - n2 = pytree.Node(1000, [], context=(" ", (1, 0))) - self.assertEqual(n1, n2) - n3 = pytree.Node(1001, ()) - self.assertNotEqual(n1, n3) - - def test_node_recursive_equality(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "foo") - n1 = pytree.Node(1000, [l1]) - n2 = pytree.Node(1000, [l2]) - self.assertEqual(n1, n2) - l3 = pytree.Leaf(100, "bar") - n3 = pytree.Node(1000, [l3]) - self.assertNotEqual(n1, n3) - - def test_replace(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "+") - l3 = pytree.Leaf(100, "bar") - n1 = pytree.Node(1000, [l1, l2, l3]) - self.assertEqual(n1.children, [l1, l2, l3]) - self.assertIsInstance(n1.children, list) - self.assertFalse(n1.was_changed) - l2new = pytree.Leaf(100, "-") - l2.replace(l2new) - self.assertEqual(n1.children, [l1, l2new, l3]) - self.assertIsInstance(n1.children, list) - self.assertTrue(n1.was_changed) - - def test_replace_with_list(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "+") - l3 = pytree.Leaf(100, "bar") - n1 = pytree.Node(1000, [l1, l2, l3]) - - l2.replace([pytree.Leaf(100, "*"), pytree.Leaf(100, "*")]) - self.assertEqual(str(n1), "foo**bar") - self.assertIsInstance(n1.children, list) - - def test_leaves(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar") - l3 = pytree.Leaf(100, "fooey") - n2 = pytree.Node(1000, [l1, l2]) - n3 = pytree.Node(1000, [l3]) - n1 = pytree.Node(1000, [n2, n3]) - - self.assertEqual(list(n1.leaves()), [l1, l2, l3]) - - def test_depth(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar") - n2 = pytree.Node(1000, [l1, l2]) - n3 = pytree.Node(1000, []) - n1 = pytree.Node(1000, [n2, n3]) - - self.assertEqual(l1.depth(), 2) - self.assertEqual(n3.depth(), 1) - self.assertEqual(n1.depth(), 0) - - def test_post_order(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar") - l3 = pytree.Leaf(100, "fooey") - c1 = pytree.Node(1000, [l1, l2]) - n1 = pytree.Node(1000, [c1, l3]) - self.assertEqual(list(n1.post_order()), [l1, l2, c1, l3, n1]) - - def test_pre_order(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar") - l3 = pytree.Leaf(100, "fooey") - c1 = pytree.Node(1000, [l1, l2]) - n1 = pytree.Node(1000, [c1, l3]) - self.assertEqual(list(n1.pre_order()), [n1, c1, l1, l2, l3]) - - def test_changed(self): - l1 = pytree.Leaf(100, "f") - self.assertFalse(l1.was_changed) - l1.changed() - self.assertTrue(l1.was_changed) - - l1 = pytree.Leaf(100, "f") - n1 = pytree.Node(1000, [l1]) - self.assertFalse(n1.was_changed) - n1.changed() - self.assertTrue(n1.was_changed) - - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "+") - l3 = pytree.Leaf(100, "bar") - n1 = pytree.Node(1000, [l1, l2, l3]) - n2 = pytree.Node(1000, [n1]) - self.assertFalse(l1.was_changed) - self.assertFalse(n1.was_changed) - self.assertFalse(n2.was_changed) - - n1.changed() - self.assertTrue(n1.was_changed) - self.assertTrue(n2.was_changed) - self.assertFalse(l1.was_changed) - - def test_leaf_constructor_prefix(self): - for prefix in ("xyz_", ""): - l1 = pytree.Leaf(100, "self", prefix=prefix) - self.assertTrue(str(l1), prefix + "self") - self.assertEqual(l1.prefix, prefix) - - def test_node_constructor_prefix(self): - for prefix in ("xyz_", ""): - l1 = pytree.Leaf(100, "self") - l2 = pytree.Leaf(100, "foo", prefix="_") - n1 = pytree.Node(1000, [l1, l2], prefix=prefix) - self.assertTrue(str(n1), prefix + "self_foo") - self.assertEqual(n1.prefix, prefix) - self.assertEqual(l1.prefix, prefix) - self.assertEqual(l2.prefix, "_") - - def test_remove(self): - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "foo") - n1 = pytree.Node(1000, [l1, l2]) - n2 = pytree.Node(1000, [n1]) - - self.assertEqual(n1.remove(), 0) - self.assertEqual(n2.children, []) - self.assertEqual(l1.parent, n1) - self.assertEqual(n1.parent, None) - self.assertEqual(n2.parent, None) - self.assertFalse(n1.was_changed) - self.assertTrue(n2.was_changed) - - self.assertEqual(l2.remove(), 1) - self.assertEqual(l1.remove(), 0) - self.assertEqual(n1.children, []) - self.assertEqual(l1.parent, None) - self.assertEqual(n1.parent, None) - self.assertEqual(n2.parent, None) - self.assertTrue(n1.was_changed) - self.assertTrue(n2.was_changed) - - def test_remove_parentless(self): - n1 = pytree.Node(1000, []) - n1.remove() - self.assertEqual(n1.parent, None) - - l1 = pytree.Leaf(100, "foo") - l1.remove() - self.assertEqual(l1.parent, None) - - def test_node_set_child(self): - l1 = pytree.Leaf(100, "foo") - n1 = pytree.Node(1000, [l1]) - - l2 = pytree.Leaf(100, "bar") - n1.set_child(0, l2) - self.assertEqual(l1.parent, None) - self.assertEqual(l2.parent, n1) - self.assertEqual(n1.children, [l2]) - - n2 = pytree.Node(1000, [l1]) - n2.set_child(0, n1) - self.assertEqual(l1.parent, None) - self.assertEqual(n1.parent, n2) - self.assertEqual(n2.parent, None) - self.assertEqual(n2.children, [n1]) - - self.assertRaises(IndexError, n1.set_child, 4, l2) - # I don't care what it raises, so long as it's an exception - self.assertRaises(Exception, n1.set_child, 0, list) - - def test_node_insert_child(self): - l1 = pytree.Leaf(100, "foo") - n1 = pytree.Node(1000, [l1]) - - l2 = pytree.Leaf(100, "bar") - n1.insert_child(0, l2) - self.assertEqual(l2.parent, n1) - self.assertEqual(n1.children, [l2, l1]) - - l3 = pytree.Leaf(100, "abc") - n1.insert_child(2, l3) - self.assertEqual(n1.children, [l2, l1, l3]) - - # I don't care what it raises, so long as it's an exception - self.assertRaises(Exception, n1.insert_child, 0, list) - - def test_node_append_child(self): - n1 = pytree.Node(1000, []) - - l1 = pytree.Leaf(100, "foo") - n1.append_child(l1) - self.assertEqual(l1.parent, n1) - self.assertEqual(n1.children, [l1]) - - l2 = pytree.Leaf(100, "bar") - n1.append_child(l2) - self.assertEqual(l2.parent, n1) - self.assertEqual(n1.children, [l1, l2]) - - # I don't care what it raises, so long as it's an exception - self.assertRaises(Exception, n1.append_child, list) - - def test_node_next_sibling(self): - n1 = pytree.Node(1000, []) - n2 = pytree.Node(1000, []) - p1 = pytree.Node(1000, [n1, n2]) - - self.assertIs(n1.next_sibling, n2) - self.assertEqual(n2.next_sibling, None) - self.assertEqual(p1.next_sibling, None) - - def test_leaf_next_sibling(self): - l1 = pytree.Leaf(100, "a") - l2 = pytree.Leaf(100, "b") - p1 = pytree.Node(1000, [l1, l2]) - - self.assertIs(l1.next_sibling, l2) - self.assertEqual(l2.next_sibling, None) - self.assertEqual(p1.next_sibling, None) - - def test_node_prev_sibling(self): - n1 = pytree.Node(1000, []) - n2 = pytree.Node(1000, []) - p1 = pytree.Node(1000, [n1, n2]) - - self.assertIs(n2.prev_sibling, n1) - self.assertEqual(n1.prev_sibling, None) - self.assertEqual(p1.prev_sibling, None) - - def test_leaf_prev_sibling(self): - l1 = pytree.Leaf(100, "a") - l2 = pytree.Leaf(100, "b") - p1 = pytree.Node(1000, [l1, l2]) - - self.assertIs(l2.prev_sibling, l1) - self.assertEqual(l1.prev_sibling, None) - self.assertEqual(p1.prev_sibling, None) - - -class TestPatterns(support.TestCase): - - """Unit tests for tree matching patterns.""" - - def test_basic_patterns(self): - # Build a tree - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar") - l3 = pytree.Leaf(100, "foo") - n1 = pytree.Node(1000, [l1, l2]) - n2 = pytree.Node(1000, [l3]) - root = pytree.Node(1000, [n1, n2]) - # Build a pattern matching a leaf - pl = pytree.LeafPattern(100, "foo", name="pl") - r = {} - self.assertFalse(pl.match(root, results=r)) - self.assertEqual(r, {}) - self.assertFalse(pl.match(n1, results=r)) - self.assertEqual(r, {}) - self.assertFalse(pl.match(n2, results=r)) - self.assertEqual(r, {}) - self.assertTrue(pl.match(l1, results=r)) - self.assertEqual(r, {"pl": l1}) - r = {} - self.assertFalse(pl.match(l2, results=r)) - self.assertEqual(r, {}) - # Build a pattern matching a node - pn = pytree.NodePattern(1000, [pl], name="pn") - self.assertFalse(pn.match(root, results=r)) - self.assertEqual(r, {}) - self.assertFalse(pn.match(n1, results=r)) - self.assertEqual(r, {}) - self.assertTrue(pn.match(n2, results=r)) - self.assertEqual(r, {"pn": n2, "pl": l3}) - r = {} - self.assertFalse(pn.match(l1, results=r)) - self.assertEqual(r, {}) - self.assertFalse(pn.match(l2, results=r)) - self.assertEqual(r, {}) - - def test_wildcard(self): - # Build a tree for testing - l1 = pytree.Leaf(100, "foo") - l2 = pytree.Leaf(100, "bar") - l3 = pytree.Leaf(100, "foo") - n1 = pytree.Node(1000, [l1, l2]) - n2 = pytree.Node(1000, [l3]) - root = pytree.Node(1000, [n1, n2]) - # Build a pattern - pl = pytree.LeafPattern(100, "foo", name="pl") - pn = pytree.NodePattern(1000, [pl], name="pn") - pw = pytree.WildcardPattern([[pn], [pl, pl]], name="pw") - r = {} - self.assertFalse(pw.match_seq([root], r)) - self.assertEqual(r, {}) - self.assertFalse(pw.match_seq([n1], r)) - self.assertEqual(r, {}) - self.assertTrue(pw.match_seq([n2], r)) - # These are easier to debug - self.assertEqual(sorted(r.keys()), ["pl", "pn", "pw"]) - self.assertEqual(r["pl"], l1) - self.assertEqual(r["pn"], n2) - self.assertEqual(r["pw"], [n2]) - # But this is equivalent - self.assertEqual(r, {"pl": l1, "pn": n2, "pw": [n2]}) - r = {} - self.assertTrue(pw.match_seq([l1, l3], r)) - self.assertEqual(r, {"pl": l3, "pw": [l1, l3]}) - self.assertIs(r["pl"], l3) - r = {} - - def test_generate_matches(self): - la = pytree.Leaf(1, "a") - lb = pytree.Leaf(1, "b") - lc = pytree.Leaf(1, "c") - ld = pytree.Leaf(1, "d") - le = pytree.Leaf(1, "e") - lf = pytree.Leaf(1, "f") - leaves = [la, lb, lc, ld, le, lf] - root = pytree.Node(1000, leaves) - pa = pytree.LeafPattern(1, "a", "pa") - pb = pytree.LeafPattern(1, "b", "pb") - pc = pytree.LeafPattern(1, "c", "pc") - pd = pytree.LeafPattern(1, "d", "pd") - pe = pytree.LeafPattern(1, "e", "pe") - pf = pytree.LeafPattern(1, "f", "pf") - pw = pytree.WildcardPattern([[pa, pb, pc], [pd, pe], - [pa, pb], [pc, pd], [pe, pf]], - min=1, max=4, name="pw") - self.assertEqual([x[0] for x in pw.generate_matches(leaves)], - [3, 5, 2, 4, 6]) - pr = pytree.NodePattern(type=1000, content=[pw], name="pr") - matches = list(pytree.generate_matches([pr], [root])) - self.assertEqual(len(matches), 1) - c, r = matches[0] - self.assertEqual(c, 1) - self.assertEqual(str(r["pr"]), "abcdef") - self.assertEqual(r["pw"], [la, lb, lc, ld, le, lf]) - for c in "abcdef": - self.assertEqual(r["p" + c], pytree.Leaf(1, c)) - - def test_has_key_example(self): - pattern = pytree.NodePattern(331, - (pytree.LeafPattern(7), - pytree.WildcardPattern(name="args"), - pytree.LeafPattern(8))) - l1 = pytree.Leaf(7, "(") - l2 = pytree.Leaf(3, "x") - l3 = pytree.Leaf(8, ")") - node = pytree.Node(331, [l1, l2, l3]) - r = {} - self.assertTrue(pattern.match(node, r)) - self.assertEqual(r["args"], [l2]) diff --git a/Lib/test/test_lib2to3/test_refactor.py b/Lib/test/test_lib2to3/test_refactor.py deleted file mode 100644 index be705679f06dba..00000000000000 --- a/Lib/test/test_lib2to3/test_refactor.py +++ /dev/null @@ -1,337 +0,0 @@ -""" -Unit tests for refactor.py. -""" - -import sys -import os -import codecs -import io -import re -import tempfile -import shutil -import unittest - -from lib2to3 import refactor, pygram, fixer_base -from lib2to3.pgen2 import token - - -TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") -FIXER_DIR = os.path.join(TEST_DATA_DIR, "fixers") - -sys.path.append(FIXER_DIR) -try: - _DEFAULT_FIXERS = refactor.get_fixers_from_package("myfixes") -finally: - sys.path.pop() - -_2TO3_FIXERS = refactor.get_fixers_from_package("lib2to3.fixes") - -class TestRefactoringTool(unittest.TestCase): - - def setUp(self): - sys.path.append(FIXER_DIR) - - def tearDown(self): - sys.path.pop() - - def check_instances(self, instances, classes): - for inst, cls in zip(instances, classes): - if not isinstance(inst, cls): - self.fail("%s are not instances of %s" % instances, classes) - - def rt(self, options=None, fixers=_DEFAULT_FIXERS, explicit=None): - return refactor.RefactoringTool(fixers, options, explicit) - - def test_print_function_option(self): - rt = self.rt({"print_function" : True}) - self.assertNotIn("print", rt.grammar.keywords) - self.assertNotIn("print", rt.driver.grammar.keywords) - - def test_exec_function_option(self): - rt = self.rt({"exec_function" : True}) - self.assertNotIn("exec", rt.grammar.keywords) - self.assertNotIn("exec", rt.driver.grammar.keywords) - - def test_write_unchanged_files_option(self): - rt = self.rt() - self.assertFalse(rt.write_unchanged_files) - rt = self.rt({"write_unchanged_files" : True}) - self.assertTrue(rt.write_unchanged_files) - - def test_fixer_loading_helpers(self): - contents = ["explicit", "first", "last", "parrot", "preorder"] - non_prefixed = refactor.get_all_fix_names("myfixes") - prefixed = refactor.get_all_fix_names("myfixes", False) - full_names = refactor.get_fixers_from_package("myfixes") - self.assertEqual(prefixed, ["fix_" + name for name in contents]) - self.assertEqual(non_prefixed, contents) - self.assertEqual(full_names, - ["myfixes.fix_" + name for name in contents]) - - def test_detect_future_features(self): - run = refactor._detect_future_features - fs = frozenset - empty = fs() - self.assertEqual(run(""), empty) - self.assertEqual(run("from __future__ import print_function"), - fs(("print_function",))) - self.assertEqual(run("from __future__ import generators"), - fs(("generators",))) - self.assertEqual(run("from __future__ import generators, feature"), - fs(("generators", "feature"))) - inp = "from __future__ import generators, print_function" - self.assertEqual(run(inp), fs(("generators", "print_function"))) - inp ="from __future__ import print_function, generators" - self.assertEqual(run(inp), fs(("print_function", "generators"))) - inp = "from __future__ import (print_function,)" - self.assertEqual(run(inp), fs(("print_function",))) - inp = "from __future__ import (generators, print_function)" - self.assertEqual(run(inp), fs(("generators", "print_function"))) - inp = "from __future__ import (generators, nested_scopes)" - self.assertEqual(run(inp), fs(("generators", "nested_scopes"))) - inp = """from __future__ import generators -from __future__ import print_function""" - self.assertEqual(run(inp), fs(("generators", "print_function"))) - invalid = ("from", - "from 4", - "from x", - "from x 5", - "from x im", - "from x import", - "from x import 4", - ) - for inp in invalid: - self.assertEqual(run(inp), empty) - inp = "'docstring'\nfrom __future__ import print_function" - self.assertEqual(run(inp), fs(("print_function",))) - inp = "'docstring'\n'somng'\nfrom __future__ import print_function" - self.assertEqual(run(inp), empty) - inp = "# comment\nfrom __future__ import print_function" - self.assertEqual(run(inp), fs(("print_function",))) - inp = "# comment\n'doc'\nfrom __future__ import print_function" - self.assertEqual(run(inp), fs(("print_function",))) - inp = "class x: pass\nfrom __future__ import print_function" - self.assertEqual(run(inp), empty) - - def test_get_headnode_dict(self): - class NoneFix(fixer_base.BaseFix): - pass - - class FileInputFix(fixer_base.BaseFix): - PATTERN = "file_input< any * >" - - class SimpleFix(fixer_base.BaseFix): - PATTERN = "'name'" - - no_head = NoneFix({}, []) - with_head = FileInputFix({}, []) - simple = SimpleFix({}, []) - d = refactor._get_headnode_dict([no_head, with_head, simple]) - top_fixes = d.pop(pygram.python_symbols.file_input) - self.assertEqual(top_fixes, [with_head, no_head]) - name_fixes = d.pop(token.NAME) - self.assertEqual(name_fixes, [simple, no_head]) - for fixes in d.values(): - self.assertEqual(fixes, [no_head]) - - def test_fixer_loading(self): - from myfixes.fix_first import FixFirst - from myfixes.fix_last import FixLast - from myfixes.fix_parrot import FixParrot - from myfixes.fix_preorder import FixPreorder - - rt = self.rt() - pre, post = rt.get_fixers() - - self.check_instances(pre, [FixPreorder]) - self.check_instances(post, [FixFirst, FixParrot, FixLast]) - - def test_naughty_fixers(self): - self.assertRaises(ImportError, self.rt, fixers=["not_here"]) - self.assertRaises(refactor.FixerError, self.rt, fixers=["no_fixer_cls"]) - self.assertRaises(refactor.FixerError, self.rt, fixers=["bad_order"]) - - def test_refactor_string(self): - rt = self.rt() - input = "def parrot(): pass\n\n" - tree = rt.refactor_string(input, "") - self.assertNotEqual(str(tree), input) - - input = "def f(): pass\n\n" - tree = rt.refactor_string(input, "") - self.assertEqual(str(tree), input) - - def test_refactor_stdin(self): - - class MyRT(refactor.RefactoringTool): - - def print_output(self, old_text, new_text, filename, equal): - results.extend([old_text, new_text, filename, equal]) - - results = [] - rt = MyRT(_DEFAULT_FIXERS) - save = sys.stdin - sys.stdin = io.StringIO("def parrot(): pass\n\n") - try: - rt.refactor_stdin() - finally: - sys.stdin = save - expected = ["def parrot(): pass\n\n", - "def cheese(): pass\n\n", - "", False] - self.assertEqual(results, expected) - - def check_file_refactoring(self, test_file, fixers=_2TO3_FIXERS, - options=None, mock_log_debug=None, - actually_write=True): - test_file = self.init_test_file(test_file) - old_contents = self.read_file(test_file) - rt = self.rt(fixers=fixers, options=options) - if mock_log_debug: - rt.log_debug = mock_log_debug - - rt.refactor_file(test_file) - self.assertEqual(old_contents, self.read_file(test_file)) - - if not actually_write: - return - rt.refactor_file(test_file, True) - new_contents = self.read_file(test_file) - self.assertNotEqual(old_contents, new_contents) - return new_contents - - def init_test_file(self, test_file): - tmpdir = tempfile.mkdtemp(prefix="2to3-test_refactor") - self.addCleanup(shutil.rmtree, tmpdir) - shutil.copy(test_file, tmpdir) - test_file = os.path.join(tmpdir, os.path.basename(test_file)) - os.chmod(test_file, 0o644) - return test_file - - def read_file(self, test_file): - with open(test_file, "rb") as fp: - return fp.read() - - def refactor_file(self, test_file, fixers=_2TO3_FIXERS): - test_file = self.init_test_file(test_file) - old_contents = self.read_file(test_file) - rt = self.rt(fixers=fixers) - rt.refactor_file(test_file, True) - new_contents = self.read_file(test_file) - return old_contents, new_contents - - def test_refactor_file(self): - test_file = os.path.join(FIXER_DIR, "parrot_example.py") - self.check_file_refactoring(test_file, _DEFAULT_FIXERS) - - def test_refactor_file_write_unchanged_file(self): - test_file = os.path.join(FIXER_DIR, "parrot_example.py") - debug_messages = [] - def recording_log_debug(msg, *args): - debug_messages.append(msg % args) - self.check_file_refactoring(test_file, fixers=(), - options={"write_unchanged_files": True}, - mock_log_debug=recording_log_debug, - actually_write=False) - # Testing that it logged this message when write=False was passed is - # sufficient to see that it did not bail early after "No changes". - message_regex = r"Not writing changes to .*%s" % \ - re.escape(os.sep + os.path.basename(test_file)) - for message in debug_messages: - if "Not writing changes" in message: - self.assertRegex(message, message_regex) - break - else: - self.fail("%r not matched in %r" % (message_regex, debug_messages)) - - def test_refactor_dir(self): - def check(structure, expected): - def mock_refactor_file(self, f, *args): - got.append(f) - save_func = refactor.RefactoringTool.refactor_file - refactor.RefactoringTool.refactor_file = mock_refactor_file - rt = self.rt() - got = [] - dir = tempfile.mkdtemp(prefix="2to3-test_refactor") - try: - os.mkdir(os.path.join(dir, "a_dir")) - for fn in structure: - open(os.path.join(dir, fn), "wb").close() - rt.refactor_dir(dir) - finally: - refactor.RefactoringTool.refactor_file = save_func - shutil.rmtree(dir) - self.assertEqual(got, - [os.path.join(dir, path) for path in expected]) - check([], []) - tree = ["nothing", - "hi.py", - ".dumb", - ".after.py", - "notpy.npy", - "sappy"] - expected = ["hi.py"] - check(tree, expected) - tree = ["hi.py", - os.path.join("a_dir", "stuff.py")] - check(tree, tree) - - def test_file_encoding(self): - fn = os.path.join(TEST_DATA_DIR, "different_encoding.py") - self.check_file_refactoring(fn) - - def test_false_file_encoding(self): - fn = os.path.join(TEST_DATA_DIR, "false_encoding.py") - data = self.check_file_refactoring(fn) - - def test_bom(self): - fn = os.path.join(TEST_DATA_DIR, "bom.py") - data = self.check_file_refactoring(fn) - self.assertTrue(data.startswith(codecs.BOM_UTF8)) - - def test_crlf_newlines(self): - old_sep = os.linesep - os.linesep = "\r\n" - try: - fn = os.path.join(TEST_DATA_DIR, "crlf.py") - fixes = refactor.get_fixers_from_package("lib2to3.fixes") - self.check_file_refactoring(fn, fixes) - finally: - os.linesep = old_sep - - def test_crlf_unchanged(self): - fn = os.path.join(TEST_DATA_DIR, "crlf.py") - old, new = self.refactor_file(fn) - self.assertIn(b"\r\n", old) - self.assertIn(b"\r\n", new) - self.assertNotIn(b"\r\r\n", new) - - def test_refactor_docstring(self): - rt = self.rt() - - doc = """ ->>> example() -42 -""" - out = rt.refactor_docstring(doc, "") - self.assertEqual(out, doc) - - doc = """ ->>> def parrot(): -... return 43 -""" - out = rt.refactor_docstring(doc, "") - self.assertNotEqual(out, doc) - - def test_explicit(self): - from myfixes.fix_explicit import FixExplicit - - rt = self.rt(fixers=["myfixes.fix_explicit"]) - self.assertEqual(len(rt.post_order), 0) - - rt = self.rt(explicit=["myfixes.fix_explicit"]) - for fix in rt.post_order: - if isinstance(fix, FixExplicit): - break - else: - self.fail("explicit fixer not loaded") diff --git a/Lib/test/test_lib2to3/test_util.py b/Lib/test/test_lib2to3/test_util.py deleted file mode 100644 index c6c613972dac7e..00000000000000 --- a/Lib/test/test_lib2to3/test_util.py +++ /dev/null @@ -1,591 +0,0 @@ -""" Test suite for the code in fixer_util """ - -# Testing imports -from . import support - -# Local imports -from lib2to3.pytree import Node, Leaf -from lib2to3 import fixer_util -from lib2to3.fixer_util import Attr, Name, Call, Comma -from lib2to3.pgen2 import token - -def parse(code, strip_levels=0): - # The topmost node is file_input, which we don't care about. - # The next-topmost node is a *_stmt node, which we also don't care about - tree = support.parse_string(code) - for i in range(strip_levels): - tree = tree.children[0] - tree.parent = None - return tree - -class MacroTestCase(support.TestCase): - def assertStr(self, node, string): - if isinstance(node, (tuple, list)): - node = Node(fixer_util.syms.simple_stmt, node) - self.assertEqual(str(node), string) - - -class Test_is_tuple(support.TestCase): - def is_tuple(self, string): - return fixer_util.is_tuple(parse(string, strip_levels=2)) - - def test_valid(self): - self.assertTrue(self.is_tuple("(a, b)")) - self.assertTrue(self.is_tuple("(a, (b, c))")) - self.assertTrue(self.is_tuple("((a, (b, c)),)")) - self.assertTrue(self.is_tuple("(a,)")) - self.assertTrue(self.is_tuple("()")) - - def test_invalid(self): - self.assertFalse(self.is_tuple("(a)")) - self.assertFalse(self.is_tuple("('foo') % (b, c)")) - - -class Test_is_list(support.TestCase): - def is_list(self, string): - return fixer_util.is_list(parse(string, strip_levels=2)) - - def test_valid(self): - self.assertTrue(self.is_list("[]")) - self.assertTrue(self.is_list("[a]")) - self.assertTrue(self.is_list("[a, b]")) - self.assertTrue(self.is_list("[a, [b, c]]")) - self.assertTrue(self.is_list("[[a, [b, c]],]")) - - def test_invalid(self): - self.assertFalse(self.is_list("[]+[]")) - - -class Test_Attr(MacroTestCase): - def test(self): - call = parse("foo()", strip_levels=2) - - self.assertStr(Attr(Name("a"), Name("b")), "a.b") - self.assertStr(Attr(call, Name("b")), "foo().b") - - def test_returns(self): - attr = Attr(Name("a"), Name("b")) - self.assertEqual(type(attr), list) - - -class Test_Name(MacroTestCase): - def test(self): - self.assertStr(Name("a"), "a") - self.assertStr(Name("foo.foo().bar"), "foo.foo().bar") - self.assertStr(Name("a", prefix="b"), "ba") - - -class Test_Call(MacroTestCase): - def _Call(self, name, args=None, prefix=None): - """Help the next test""" - children = [] - if isinstance(args, list): - for arg in args: - children.append(arg) - children.append(Comma()) - children.pop() - return Call(Name(name), children, prefix) - - def test(self): - kids = [None, - [Leaf(token.NUMBER, 1), Leaf(token.NUMBER, 2), - Leaf(token.NUMBER, 3)], - [Leaf(token.NUMBER, 1), Leaf(token.NUMBER, 3), - Leaf(token.NUMBER, 2), Leaf(token.NUMBER, 4)], - [Leaf(token.STRING, "b"), Leaf(token.STRING, "j", prefix=" ")] - ] - self.assertStr(self._Call("A"), "A()") - self.assertStr(self._Call("b", kids[1]), "b(1,2,3)") - self.assertStr(self._Call("a.b().c", kids[2]), "a.b().c(1,3,2,4)") - self.assertStr(self._Call("d", kids[3], prefix=" "), " d(b, j)") - - -class Test_does_tree_import(support.TestCase): - def _find_bind_rec(self, name, node): - # Search a tree for a binding -- used to find the starting - # point for these tests. - c = fixer_util.find_binding(name, node) - if c: return c - for child in node.children: - c = self._find_bind_rec(name, child) - if c: return c - - def does_tree_import(self, package, name, string): - node = parse(string) - # Find the binding of start -- that's what we'll go from - node = self._find_bind_rec('start', node) - return fixer_util.does_tree_import(package, name, node) - - def try_with(self, string): - failing_tests = (("a", "a", "from a import b"), - ("a.d", "a", "from a.d import b"), - ("d.a", "a", "from d.a import b"), - (None, "a", "import b"), - (None, "a", "import b, c, d")) - for package, name, import_ in failing_tests: - n = self.does_tree_import(package, name, import_ + "\n" + string) - self.assertFalse(n) - n = self.does_tree_import(package, name, string + "\n" + import_) - self.assertFalse(n) - - passing_tests = (("a", "a", "from a import a"), - ("x", "a", "from x import a"), - ("x", "a", "from x import b, c, a, d"), - ("x.b", "a", "from x.b import a"), - ("x.b", "a", "from x.b import b, c, a, d"), - (None, "a", "import a"), - (None, "a", "import b, c, a, d")) - for package, name, import_ in passing_tests: - n = self.does_tree_import(package, name, import_ + "\n" + string) - self.assertTrue(n) - n = self.does_tree_import(package, name, string + "\n" + import_) - self.assertTrue(n) - - def test_in_function(self): - self.try_with("def foo():\n\tbar.baz()\n\tstart=3") - -class Test_find_binding(support.TestCase): - def find_binding(self, name, string, package=None): - return fixer_util.find_binding(name, parse(string), package) - - def test_simple_assignment(self): - self.assertTrue(self.find_binding("a", "a = b")) - self.assertTrue(self.find_binding("a", "a = [b, c, d]")) - self.assertTrue(self.find_binding("a", "a = foo()")) - self.assertTrue(self.find_binding("a", "a = foo().foo.foo[6][foo]")) - self.assertFalse(self.find_binding("a", "foo = a")) - self.assertFalse(self.find_binding("a", "foo = (a, b, c)")) - - def test_tuple_assignment(self): - self.assertTrue(self.find_binding("a", "(a,) = b")) - self.assertTrue(self.find_binding("a", "(a, b, c) = [b, c, d]")) - self.assertTrue(self.find_binding("a", "(c, (d, a), b) = foo()")) - self.assertTrue(self.find_binding("a", "(a, b) = foo().foo[6][foo]")) - self.assertFalse(self.find_binding("a", "(foo, b) = (b, a)")) - self.assertFalse(self.find_binding("a", "(foo, (b, c)) = (a, b, c)")) - - def test_list_assignment(self): - self.assertTrue(self.find_binding("a", "[a] = b")) - self.assertTrue(self.find_binding("a", "[a, b, c] = [b, c, d]")) - self.assertTrue(self.find_binding("a", "[c, [d, a], b] = foo()")) - self.assertTrue(self.find_binding("a", "[a, b] = foo().foo[a][foo]")) - self.assertFalse(self.find_binding("a", "[foo, b] = (b, a)")) - self.assertFalse(self.find_binding("a", "[foo, [b, c]] = (a, b, c)")) - - def test_invalid_assignments(self): - self.assertFalse(self.find_binding("a", "foo.a = 5")) - self.assertFalse(self.find_binding("a", "foo[a] = 5")) - self.assertFalse(self.find_binding("a", "foo(a) = 5")) - self.assertFalse(self.find_binding("a", "foo(a, b) = 5")) - - def test_simple_import(self): - self.assertTrue(self.find_binding("a", "import a")) - self.assertTrue(self.find_binding("a", "import b, c, a, d")) - self.assertFalse(self.find_binding("a", "import b")) - self.assertFalse(self.find_binding("a", "import b, c, d")) - - def test_from_import(self): - self.assertTrue(self.find_binding("a", "from x import a")) - self.assertTrue(self.find_binding("a", "from a import a")) - self.assertTrue(self.find_binding("a", "from x import b, c, a, d")) - self.assertTrue(self.find_binding("a", "from x.b import a")) - self.assertTrue(self.find_binding("a", "from x.b import b, c, a, d")) - self.assertFalse(self.find_binding("a", "from a import b")) - self.assertFalse(self.find_binding("a", "from a.d import b")) - self.assertFalse(self.find_binding("a", "from d.a import b")) - - def test_import_as(self): - self.assertTrue(self.find_binding("a", "import b as a")) - self.assertTrue(self.find_binding("a", "import b as a, c, a as f, d")) - self.assertFalse(self.find_binding("a", "import a as f")) - self.assertFalse(self.find_binding("a", "import b, c as f, d as e")) - - def test_from_import_as(self): - self.assertTrue(self.find_binding("a", "from x import b as a")) - self.assertTrue(self.find_binding("a", "from x import g as a, d as b")) - self.assertTrue(self.find_binding("a", "from x.b import t as a")) - self.assertTrue(self.find_binding("a", "from x.b import g as a, d")) - self.assertFalse(self.find_binding("a", "from a import b as t")) - self.assertFalse(self.find_binding("a", "from a.d import b as t")) - self.assertFalse(self.find_binding("a", "from d.a import b as t")) - - def test_simple_import_with_package(self): - self.assertTrue(self.find_binding("b", "import b")) - self.assertTrue(self.find_binding("b", "import b, c, d")) - self.assertFalse(self.find_binding("b", "import b", "b")) - self.assertFalse(self.find_binding("b", "import b, c, d", "c")) - - def test_from_import_with_package(self): - self.assertTrue(self.find_binding("a", "from x import a", "x")) - self.assertTrue(self.find_binding("a", "from a import a", "a")) - self.assertTrue(self.find_binding("a", "from x import *", "x")) - self.assertTrue(self.find_binding("a", "from x import b, c, a, d", "x")) - self.assertTrue(self.find_binding("a", "from x.b import a", "x.b")) - self.assertTrue(self.find_binding("a", "from x.b import *", "x.b")) - self.assertTrue(self.find_binding("a", "from x.b import b, c, a, d", "x.b")) - self.assertFalse(self.find_binding("a", "from a import b", "a")) - self.assertFalse(self.find_binding("a", "from a.d import b", "a.d")) - self.assertFalse(self.find_binding("a", "from d.a import b", "a.d")) - self.assertFalse(self.find_binding("a", "from x.y import *", "a.b")) - - def test_import_as_with_package(self): - self.assertFalse(self.find_binding("a", "import b.c as a", "b.c")) - self.assertFalse(self.find_binding("a", "import a as f", "f")) - self.assertFalse(self.find_binding("a", "import a as f", "a")) - - def test_from_import_as_with_package(self): - # Because it would take a lot of special-case code in the fixers - # to deal with from foo import bar as baz, we'll simply always - # fail if there is an "from ... import ... as ..." - self.assertFalse(self.find_binding("a", "from x import b as a", "x")) - self.assertFalse(self.find_binding("a", "from x import g as a, d as b", "x")) - self.assertFalse(self.find_binding("a", "from x.b import t as a", "x.b")) - self.assertFalse(self.find_binding("a", "from x.b import g as a, d", "x.b")) - self.assertFalse(self.find_binding("a", "from a import b as t", "a")) - self.assertFalse(self.find_binding("a", "from a import b as t", "b")) - self.assertFalse(self.find_binding("a", "from a import b as t", "t")) - - def test_function_def(self): - self.assertTrue(self.find_binding("a", "def a(): pass")) - self.assertTrue(self.find_binding("a", "def a(b, c, d): pass")) - self.assertTrue(self.find_binding("a", "def a(): b = 7")) - self.assertFalse(self.find_binding("a", "def d(b, (c, a), e): pass")) - self.assertFalse(self.find_binding("a", "def d(a=7): pass")) - self.assertFalse(self.find_binding("a", "def d(a): pass")) - self.assertFalse(self.find_binding("a", "def d(): a = 7")) - - s = """ - def d(): - def a(): - pass""" - self.assertFalse(self.find_binding("a", s)) - - def test_class_def(self): - self.assertTrue(self.find_binding("a", "class a: pass")) - self.assertTrue(self.find_binding("a", "class a(): pass")) - self.assertTrue(self.find_binding("a", "class a(b): pass")) - self.assertTrue(self.find_binding("a", "class a(b, c=8): pass")) - self.assertFalse(self.find_binding("a", "class d: pass")) - self.assertFalse(self.find_binding("a", "class d(a): pass")) - self.assertFalse(self.find_binding("a", "class d(b, a=7): pass")) - self.assertFalse(self.find_binding("a", "class d(b, *a): pass")) - self.assertFalse(self.find_binding("a", "class d(b, **a): pass")) - self.assertFalse(self.find_binding("a", "class d: a = 7")) - - s = """ - class d(): - class a(): - pass""" - self.assertFalse(self.find_binding("a", s)) - - def test_for(self): - self.assertTrue(self.find_binding("a", "for a in r: pass")) - self.assertTrue(self.find_binding("a", "for a, b in r: pass")) - self.assertTrue(self.find_binding("a", "for (a, b) in r: pass")) - self.assertTrue(self.find_binding("a", "for c, (a,) in r: pass")) - self.assertTrue(self.find_binding("a", "for c, (a, b) in r: pass")) - self.assertTrue(self.find_binding("a", "for c in r: a = c")) - self.assertFalse(self.find_binding("a", "for c in a: pass")) - - def test_for_nested(self): - s = """ - for b in r: - for a in b: - pass""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - for b in r: - for a, c in b: - pass""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - for b in r: - for (a, c) in b: - pass""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - for b in r: - for (a,) in b: - pass""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - for b in r: - for c, (a, d) in b: - pass""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - for b in r: - for c in b: - a = 7""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - for b in r: - for c in b: - d = a""" - self.assertFalse(self.find_binding("a", s)) - - s = """ - for b in r: - for c in a: - d = 7""" - self.assertFalse(self.find_binding("a", s)) - - def test_if(self): - self.assertTrue(self.find_binding("a", "if b in r: a = c")) - self.assertFalse(self.find_binding("a", "if a in r: d = e")) - - def test_if_nested(self): - s = """ - if b in r: - if c in d: - a = c""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - if b in r: - if c in d: - c = a""" - self.assertFalse(self.find_binding("a", s)) - - def test_while(self): - self.assertTrue(self.find_binding("a", "while b in r: a = c")) - self.assertFalse(self.find_binding("a", "while a in r: d = e")) - - def test_while_nested(self): - s = """ - while b in r: - while c in d: - a = c""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - while b in r: - while c in d: - c = a""" - self.assertFalse(self.find_binding("a", s)) - - def test_try_except(self): - s = """ - try: - a = 6 - except: - b = 8""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - except: - a = 6""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - except KeyError: - pass - except: - a = 6""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - except: - b = 6""" - self.assertFalse(self.find_binding("a", s)) - - def test_try_except_nested(self): - s = """ - try: - try: - a = 6 - except: - pass - except: - b = 8""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - except: - try: - a = 6 - except: - pass""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - except: - try: - pass - except: - a = 6""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - try: - b = 8 - except KeyError: - pass - except: - a = 6 - except: - pass""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - pass - except: - try: - b = 8 - except KeyError: - pass - except: - a = 6""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - except: - b = 6""" - self.assertFalse(self.find_binding("a", s)) - - s = """ - try: - try: - b = 8 - except: - c = d - except: - try: - b = 6 - except: - t = 8 - except: - o = y""" - self.assertFalse(self.find_binding("a", s)) - - def test_try_except_finally(self): - s = """ - try: - c = 6 - except: - b = 8 - finally: - a = 9""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - finally: - a = 6""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - finally: - b = 6""" - self.assertFalse(self.find_binding("a", s)) - - s = """ - try: - b = 8 - except: - b = 9 - finally: - b = 6""" - self.assertFalse(self.find_binding("a", s)) - - def test_try_except_finally_nested(self): - s = """ - try: - c = 6 - except: - b = 8 - finally: - try: - a = 9 - except: - b = 9 - finally: - c = 9""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - finally: - try: - pass - finally: - a = 6""" - self.assertTrue(self.find_binding("a", s)) - - s = """ - try: - b = 8 - finally: - try: - b = 6 - finally: - b = 7""" - self.assertFalse(self.find_binding("a", s)) - -class Test_touch_import(support.TestCase): - - def test_after_docstring(self): - node = parse('"""foo"""\nbar()') - fixer_util.touch_import(None, "foo", node) - self.assertEqual(str(node), '"""foo"""\nimport foo\nbar()\n\n') - - def test_after_imports(self): - node = parse('"""foo"""\nimport bar\nbar()') - fixer_util.touch_import(None, "foo", node) - self.assertEqual(str(node), '"""foo"""\nimport bar\nimport foo\nbar()\n\n') - - def test_beginning(self): - node = parse('bar()') - fixer_util.touch_import(None, "foo", node) - self.assertEqual(str(node), 'import foo\nbar()\n\n') - - def test_from_import(self): - node = parse('bar()') - fixer_util.touch_import("html", "escape", node) - self.assertEqual(str(node), 'from html import escape\nbar()\n\n') - - def test_name_import(self): - node = parse('bar()') - fixer_util.touch_import(None, "cgi", node) - self.assertEqual(str(node), 'import cgi\nbar()\n\n') - -class Test_find_indentation(support.TestCase): - - def test_nothing(self): - fi = fixer_util.find_indentation - node = parse("node()") - self.assertEqual(fi(node), "") - node = parse("") - self.assertEqual(fi(node), "") - - def test_simple(self): - fi = fixer_util.find_indentation - node = parse("def f():\n x()") - self.assertEqual(fi(node), "") - self.assertEqual(fi(node.children[0].children[4].children[2]), " ") - node = parse("def f():\n x()\n y()") - self.assertEqual(fi(node.children[0].children[4].children[4]), " ") diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py index 23e1b8c1ce3193..c2cf058c321fa5 100644 --- a/Lib/test/test_listcomps.py +++ b/Lib/test/test_listcomps.py @@ -200,7 +200,8 @@ def f(): y = [g for x in [1]] """ outputs = {"y": [2]} - self._check_in_scopes(code, outputs) + self._check_in_scopes(code, outputs, scopes=["module", "function"]) + self._check_in_scopes(code, scopes=["class"], raises=NameError) def test_inner_cell_shadows_outer_redefined(self): code = """ @@ -328,7 +329,8 @@ def test_nested_2(self): y = [x for [x ** x for x in range(x)][x - 1] in l] """ outputs = {"y": [3, 3, 3]} - self._check_in_scopes(code, outputs) + self._check_in_scopes(code, outputs, scopes=["module", "function"]) + self._check_in_scopes(code, scopes=["class"], raises=NameError) def test_nested_3(self): code = """ @@ -379,6 +381,164 @@ def f(): with self.assertRaises(UnboundLocalError): f() + def test_global_outside_cellvar_inside_plus_freevar(self): + code = """ + a = 1 + def f(): + func, = [(lambda: b) for b in [a]] + return b, func() + x = f() + """ + self._check_in_scopes( + code, {"x": (2, 1)}, ns={"b": 2}, scopes=["function", "module"]) + # inside a class, the `a = 1` assignment is not visible + self._check_in_scopes(code, raises=NameError, scopes=["class"]) + + def test_cell_in_nested_comprehension(self): + code = """ + a = 1 + def f(): + (func, inner_b), = [[lambda: b for b in c] + [b] for c in [[a]]] + return b, inner_b, func() + x = f() + """ + self._check_in_scopes( + code, {"x": (2, 2, 1)}, ns={"b": 2}, scopes=["function", "module"]) + # inside a class, the `a = 1` assignment is not visible + self._check_in_scopes(code, raises=NameError, scopes=["class"]) + + def test_name_error_in_class_scope(self): + code = """ + y = 1 + [x + y for x in range(2)] + """ + self._check_in_scopes(code, raises=NameError, scopes=["class"]) + + def test_global_in_class_scope(self): + code = """ + y = 2 + vals = [(x, y) for x in range(2)] + """ + outputs = {"vals": [(0, 1), (1, 1)]} + self._check_in_scopes(code, outputs, ns={"y": 1}, scopes=["class"]) + + def test_in_class_scope_inside_function_1(self): + code = """ + class C: + y = 2 + vals = [(x, y) for x in range(2)] + vals = C.vals + """ + outputs = {"vals": [(0, 1), (1, 1)]} + self._check_in_scopes(code, outputs, ns={"y": 1}, scopes=["function"]) + + def test_in_class_scope_inside_function_2(self): + code = """ + y = 1 + class C: + y = 2 + vals = [(x, y) for x in range(2)] + vals = C.vals + """ + outputs = {"vals": [(0, 1), (1, 1)]} + self._check_in_scopes(code, outputs, scopes=["function"]) + + def test_in_class_scope_with_global(self): + code = """ + y = 1 + class C: + global y + y = 2 + # Ensure the listcomp uses the global, not the value in the + # class namespace + locals()['y'] = 3 + vals = [(x, y) for x in range(2)] + vals = C.vals + """ + outputs = {"vals": [(0, 2), (1, 2)]} + self._check_in_scopes(code, outputs, scopes=["module", "class"]) + outputs = {"vals": [(0, 1), (1, 1)]} + self._check_in_scopes(code, outputs, scopes=["function"]) + + def test_in_class_scope_with_nonlocal(self): + code = """ + y = 1 + class C: + nonlocal y + y = 2 + # Ensure the listcomp uses the global, not the value in the + # class namespace + locals()['y'] = 3 + vals = [(x, y) for x in range(2)] + vals = C.vals + """ + outputs = {"vals": [(0, 2), (1, 2)]} + self._check_in_scopes(code, outputs, scopes=["function"]) + + def test_nested_has_free_var(self): + code = """ + items = [a for a in [1] if [a for _ in [0]]] + """ + outputs = {"items": [1]} + self._check_in_scopes(code, outputs, scopes=["class"]) + + def test_nested_free_var_not_bound_in_outer_comp(self): + code = """ + z = 1 + items = [a for a in [1] if [x for x in [1] if z]] + """ + self._check_in_scopes(code, {"items": [1]}, scopes=["module", "function"]) + self._check_in_scopes(code, {"items": []}, ns={"z": 0}, scopes=["class"]) + + def test_nested_free_var_in_iter(self): + code = """ + items = [_C for _C in [1] for [0, 1][[x for x in [1] if _C][0]] in [2]] + """ + self._check_in_scopes(code, {"items": [1]}) + + def test_nested_free_var_in_expr(self): + code = """ + items = [(_C, [x for x in [1] if _C]) for _C in [0, 1]] + """ + self._check_in_scopes(code, {"items": [(0, []), (1, [1])]}) + + def test_nested_listcomp_in_lambda(self): + code = """ + f = [(z, lambda y: [(x, y, z) for x in [3]]) for z in [1]] + (z, func), = f + out = func(2) + """ + self._check_in_scopes(code, {"z": 1, "out": [(3, 2, 1)]}) + + def test_lambda_in_iter(self): + code = """ + (func, c), = [(a, b) for b in [1] for a in [lambda : a]] + d = func() + assert d is func + # must use "a" in this scope + e = a if False else None + """ + self._check_in_scopes(code, {"c": 1, "e": None}) + + def test_assign_to_comp_iter_var_in_outer_function(self): + code = """ + a = [1 for a in [0]] + """ + self._check_in_scopes(code, {"a": [1]}, scopes=["function"]) + + def test_no_leakage_to_locals(self): + code = """ + def b(): + [a for b in [1] for _ in []] + return b, locals() + r, s = b() + x = r is b + y = list(s.keys()) + """ + self._check_in_scopes(code, {"x": True, "y": []}, scopes=["module"]) + self._check_in_scopes(code, {"x": True, "y": ["b"]}, scopes=["function"]) + self._check_in_scopes(code, raises=NameError, scopes=["class"]) + __test__ = {'doctests' : doctests} diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 9176d8eeb56d01..18258c22874ae0 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1756,6 +1756,42 @@ def test_config_set_handler_names(self): self.apply_config(test_config) self.assertEqual(logging.getLogger().handlers[0].name, 'hand1') + def test_exception_if_confg_file_is_invalid(self): + test_config = """ + [loggers] + keys=root + + [handlers] + keys=hand1 + + [formatters] + keys=form1 + + [logger_root] + handlers=hand1 + + [handler_hand1] + class=StreamHandler + formatter=form1 + + [formatter_form1] + format=%(levelname)s ++ %(message)s + + prince + """ + + file = io.StringIO(textwrap.dedent(test_config)) + self.assertRaises(RuntimeError, logging.config.fileConfig, file) + + def test_exception_if_confg_file_is_empty(self): + fd, fn = tempfile.mkstemp(prefix='test_empty_', suffix='.ini') + os.close(fd) + self.assertRaises(RuntimeError, logging.config.fileConfig, fn) + os.remove(fn) + + def test_exception_if_config_file_does_not_exist(self): + self.assertRaises(FileNotFoundError, logging.config.fileConfig, 'filenotfound') + def test_defaults_do_no_interpolation(self): """bpo-33802 defaults should not get interpolated""" ini = textwrap.dedent(""" diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index f282434c9a3359..2bda61012164d1 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -2296,11 +2296,20 @@ def test_nextafter(self): float.fromhex('0x1.fffffffffffffp-1')) self.assertEqual(math.nextafter(1.0, INF), float.fromhex('0x1.0000000000001p+0')) + self.assertEqual(math.nextafter(1.0, -INF, steps=1), + float.fromhex('0x1.fffffffffffffp-1')) + self.assertEqual(math.nextafter(1.0, INF, steps=1), + float.fromhex('0x1.0000000000001p+0')) + self.assertEqual(math.nextafter(1.0, -INF, steps=3), + float.fromhex('0x1.ffffffffffffdp-1')) + self.assertEqual(math.nextafter(1.0, INF, steps=3), + float.fromhex('0x1.0000000000003p+0')) # x == y: y is returned - self.assertEqual(math.nextafter(2.0, 2.0), 2.0) - self.assertEqualSign(math.nextafter(-0.0, +0.0), +0.0) - self.assertEqualSign(math.nextafter(+0.0, -0.0), -0.0) + for steps in range(1, 5): + self.assertEqual(math.nextafter(2.0, 2.0, steps=steps), 2.0) + self.assertEqualSign(math.nextafter(-0.0, +0.0, steps=steps), +0.0) + self.assertEqualSign(math.nextafter(+0.0, -0.0, steps=steps), -0.0) # around 0.0 smallest_subnormal = sys.float_info.min * sys.float_info.epsilon @@ -2325,6 +2334,11 @@ def test_nextafter(self): self.assertIsNaN(math.nextafter(1.0, NAN)) self.assertIsNaN(math.nextafter(NAN, NAN)) + self.assertEqual(1.0, math.nextafter(1.0, INF, steps=0)) + with self.assertRaises(ValueError): + math.nextafter(1.0, INF, steps=-1) + + @requires_IEEE_754 def test_ulp(self): self.assertEqual(math.ulp(1.0), sys.float_info.epsilon) diff --git a/Lib/test/test_math_property.py b/Lib/test/test_math_property.py new file mode 100644 index 00000000000000..7d51aa17b4cc27 --- /dev/null +++ b/Lib/test/test_math_property.py @@ -0,0 +1,41 @@ +import functools +import unittest +from math import isnan, nextafter +from test.support import requires_IEEE_754 +from test.support.hypothesis_helper import hypothesis + +floats = hypothesis.strategies.floats +integers = hypothesis.strategies.integers + + +def assert_equal_float(x, y): + assert isnan(x) and isnan(y) or x == y + + +def via_reduce(x, y, steps): + return functools.reduce(nextafter, [y] * steps, x) + + +class NextafterTests(unittest.TestCase): + @requires_IEEE_754 + @hypothesis.given( + x=floats(), + y=floats(), + steps=integers(min_value=0, max_value=2**16)) + def test_count(self, x, y, steps): + assert_equal_float(via_reduce(x, y, steps), + nextafter(x, y, steps=steps)) + + @requires_IEEE_754 + @hypothesis.given( + x=floats(), + y=floats(), + a=integers(min_value=0), + b=integers(min_value=0)) + def test_addition_commutes(self, x, y, a, b): + first = nextafter(x, y, steps=a) + second = nextafter(first, y, steps=b) + combined = nextafter(x, y, steps=a+b) + hypothesis.note(f"{first} -> {second} == {combined}") + + assert_equal_float(second, combined) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index 213a44d56f37b3..517cbe0cb115ab 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -407,7 +407,6 @@ def test_move(self): m.move(0, 0, 1) m.move(0, 0, 0) - def test_anonymous(self): # anonymous mmap.mmap(-1, PAGE) m = mmap.mmap(-1, PAGESIZE) @@ -887,6 +886,92 @@ def test_resize_succeeds_with_error_for_second_named_mapping(self): self.assertEqual(m1[:data_length], data) self.assertEqual(m2[:data_length], data) + def test_mmap_closed_by_int_scenarios(self): + """ + gh-103987: Test that mmap objects raise ValueError + for closed mmap files + """ + + class MmapClosedByIntContext: + def __init__(self, access) -> None: + self.access = access + + def __enter__(self): + self.f = open(TESTFN, "w+b") + self.f.write(random.randbytes(100)) + self.f.flush() + + m = mmap.mmap(self.f.fileno(), 100, access=self.access) + + class X: + def __index__(self): + m.close() + return 10 + + return (m, X) + + def __exit__(self, exc_type, exc_value, traceback): + self.f.close() + + read_access_modes = [ + mmap.ACCESS_READ, + mmap.ACCESS_WRITE, + mmap.ACCESS_COPY, + mmap.ACCESS_DEFAULT, + ] + + write_access_modes = [ + mmap.ACCESS_WRITE, + mmap.ACCESS_COPY, + mmap.ACCESS_DEFAULT, + ] + + for access in read_access_modes: + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m[X()] + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m[X() : 20] + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m[X() : 20 : 2] + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m[20 : X() : -2] + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m.read(X()) + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m.find(b"1", 1, X()) + + for access in write_access_modes: + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m[X() : 20] = b"1" * 10 + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m[X() : 20 : 2] = b"1" * 5 + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m[20 : X() : -2] = b"1" * 5 + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m.move(1, 2, X()) + + with MmapClosedByIntContext(access) as (m, X): + with self.assertRaisesRegex(ValueError, "mmap closed or invalid"): + m.write_byte(X()) + class LargeMmapTests(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 06e54fa2965f0a..46b817d74f092f 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1,9 +1,11 @@ """Test suite for the sys.monitoring.""" import collections +import dis import functools import operator import sys +import textwrap import types import unittest @@ -506,7 +508,7 @@ def test_lines_single(self): sys.monitoring.set_events(TEST_TOOL, 0) sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) start = LineMonitoringTest.test_lines_single.__code__.co_firstlineno - self.assertEqual(events, [start+7, 14, start+8]) + self.assertEqual(events, [start+7, 16, start+8]) finally: sys.monitoring.set_events(TEST_TOOL, 0) sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) @@ -524,7 +526,7 @@ def test_lines_loop(self): sys.monitoring.set_events(TEST_TOOL, 0) sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) start = LineMonitoringTest.test_lines_loop.__code__.co_firstlineno - self.assertEqual(events, [start+7, 21, 22, 21, 22, 21, start+8]) + self.assertEqual(events, [start+7, 23, 24, 23, 24, 23, start+8]) finally: sys.monitoring.set_events(TEST_TOOL, 0) sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) @@ -546,7 +548,7 @@ def test_lines_two(self): sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) sys.monitoring.register_callback(TEST_TOOL2, E.LINE, None) start = LineMonitoringTest.test_lines_two.__code__.co_firstlineno - expected = [start+10, 14, start+11] + expected = [start+10, 16, start+11] self.assertEqual(events, expected) self.assertEqual(events2, expected) finally: @@ -1177,6 +1179,221 @@ def func(): ('return', None), ('line', 'check_events', 11)]) +class TestLoadSuperAttr(CheckEvents): + RECORDERS = CallRecorder, LineRecorder, CRaiseRecorder, CReturnRecorder + + def _exec(self, co): + d = {} + exec(co, d, d) + return d + + def _exec_super(self, codestr, optimized=False): + # The compiler checks for statically visible shadowing of the name + # `super`, and declines to emit `LOAD_SUPER_ATTR` if shadowing is found. + # So inserting `super = super` prevents the compiler from emitting + # `LOAD_SUPER_ATTR`, and allows us to test that monitoring events for + # `LOAD_SUPER_ATTR` are equivalent to those we'd get from the + # un-optimized `LOAD_GLOBAL super; CALL; LOAD_ATTR` form. + assignment = "x = 1" if optimized else "super = super" + codestr = f"{assignment}\n{textwrap.dedent(codestr)}" + co = compile(codestr, "", "exec") + # validate that we really do have a LOAD_SUPER_ATTR, only when optimized + self.assertEqual(self._has_load_super_attr(co), optimized) + return self._exec(co) + + def _has_load_super_attr(self, co): + has = any(instr.opname == "LOAD_SUPER_ATTR" for instr in dis.get_instructions(co)) + if not has: + has = any( + isinstance(c, types.CodeType) and self._has_load_super_attr(c) + for c in co.co_consts + ) + return has + + def _super_method_call(self, optimized=False): + codestr = """ + class A: + def method(self, x): + return x + + class B(A): + def method(self, x): + return super( + ).method( + x + ) + + b = B() + def f(): + return b.method(1) + """ + d = self._exec_super(codestr, optimized) + expected = [ + ('line', 'check_events', 10), + ('call', 'f', sys.monitoring.MISSING), + ('line', 'f', 1), + ('call', 'method', d["b"]), + ('line', 'method', 1), + ('call', 'super', sys.monitoring.MISSING), + ('C return', 'super', sys.monitoring.MISSING), + ('line', 'method', 2), + ('line', 'method', 3), + ('line', 'method', 2), + ('call', 'method', 1), + ('line', 'method', 1), + ('line', 'method', 1), + ('line', 'check_events', 11), + ('call', 'set_events', 2), + ] + return d["f"], expected + + def test_method_call(self): + nonopt_func, nonopt_expected = self._super_method_call(optimized=False) + opt_func, opt_expected = self._super_method_call(optimized=True) + + self.check_events(nonopt_func, recorders=self.RECORDERS, expected=nonopt_expected) + self.check_events(opt_func, recorders=self.RECORDERS, expected=opt_expected) + + def _super_method_call_error(self, optimized=False): + codestr = """ + class A: + def method(self, x): + return x + + class B(A): + def method(self, x): + return super( + x, + self, + ).method( + x + ) + + b = B() + def f(): + try: + return b.method(1) + except TypeError: + pass + else: + assert False, "should have raised TypeError" + """ + d = self._exec_super(codestr, optimized) + expected = [ + ('line', 'check_events', 10), + ('call', 'f', sys.monitoring.MISSING), + ('line', 'f', 1), + ('line', 'f', 2), + ('call', 'method', d["b"]), + ('line', 'method', 1), + ('line', 'method', 2), + ('line', 'method', 3), + ('line', 'method', 1), + ('call', 'super', 1), + ('C raise', 'super', 1), + ('line', 'f', 3), + ('line', 'f', 4), + ('line', 'check_events', 11), + ('call', 'set_events', 2), + ] + return d["f"], expected + + def test_method_call_error(self): + nonopt_func, nonopt_expected = self._super_method_call_error(optimized=False) + opt_func, opt_expected = self._super_method_call_error(optimized=True) + + self.check_events(nonopt_func, recorders=self.RECORDERS, expected=nonopt_expected) + self.check_events(opt_func, recorders=self.RECORDERS, expected=opt_expected) + + def _super_attr(self, optimized=False): + codestr = """ + class A: + x = 1 + + class B(A): + def method(self): + return super( + ).x + + b = B() + def f(): + return b.method() + """ + d = self._exec_super(codestr, optimized) + expected = [ + ('line', 'check_events', 10), + ('call', 'f', sys.monitoring.MISSING), + ('line', 'f', 1), + ('call', 'method', d["b"]), + ('line', 'method', 1), + ('call', 'super', sys.monitoring.MISSING), + ('C return', 'super', sys.monitoring.MISSING), + ('line', 'method', 2), + ('line', 'method', 1), + ('line', 'check_events', 11), + ('call', 'set_events', 2) + ] + return d["f"], expected + + def test_attr(self): + nonopt_func, nonopt_expected = self._super_attr(optimized=False) + opt_func, opt_expected = self._super_attr(optimized=True) + + self.check_events(nonopt_func, recorders=self.RECORDERS, expected=nonopt_expected) + self.check_events(opt_func, recorders=self.RECORDERS, expected=opt_expected) + + def test_vs_other_type_call(self): + code_template = textwrap.dedent(""" + class C: + def method(self): + return {cls}().__repr__{call} + c = C() + def f(): + return c.method() + """) + + def get_expected(name, call_method, ns): + repr_arg = 0 if name == "int" else sys.monitoring.MISSING + return [ + ('line', 'check_events', 10), + ('call', 'f', sys.monitoring.MISSING), + ('line', 'f', 1), + ('call', 'method', ns["c"]), + ('line', 'method', 1), + ('call', name, sys.monitoring.MISSING), + ('C return', name, sys.monitoring.MISSING), + *( + [ + ('call', '__repr__', repr_arg), + ('C return', '__repr__', repr_arg), + ] if call_method else [] + ), + ('line', 'check_events', 11), + ('call', 'set_events', 2), + ] + + for call_method in [True, False]: + with self.subTest(call_method=call_method): + call_str = "()" if call_method else "" + code_super = code_template.format(cls="super", call=call_str) + code_int = code_template.format(cls="int", call=call_str) + co_super = compile(code_super, '', 'exec') + self.assertTrue(self._has_load_super_attr(co_super)) + ns_super = self._exec(co_super) + ns_int = self._exec(code_int) + + self.check_events( + ns_super["f"], + recorders=self.RECORDERS, + expected=get_expected("super", call_method, ns_super) + ) + self.check_events( + ns_int["f"], + recorders=self.RECORDERS, + expected=get_expected("int", call_method, ns_int) + ) + + class TestSetGetEvents(MonitoringTestBase, unittest.TestCase): def test_global(self): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 3eeff98cb380bf..e27d9dbb6e55dc 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -312,6 +312,11 @@ def test_match_common(self): # Multi-part glob-style pattern. self.assertFalse(P('/a/b/c.py').match('/**/*.py')) self.assertTrue(P('/a/b/c.py').match('/a/**/*.py')) + # Case-sensitive flag + self.assertFalse(P('A.py').match('a.PY', case_sensitive=True)) + self.assertTrue(P('A.py').match('a.PY', case_sensitive=False)) + self.assertFalse(P('c:/a/B.Py').match('C:/A/*.pY', case_sensitive=True)) + self.assertTrue(P('/a/b/c.py').match('/A/*/*.Py', case_sensitive=False)) def test_ordering_common(self): # Ordering is tuple-alike. @@ -916,7 +921,7 @@ def test_as_uri(self): self.assertEqual(P('//some/share/a/b%#c\xe9').as_uri(), 'file://some/share/a/b%25%23c%C3%A9') - def test_match_common(self): + def test_match(self): P = self.cls # Absolute patterns. self.assertTrue(P('c:/b.py').match('*:/*.py')) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index bf7fc421a9df0a..255e9280421423 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -971,13 +971,14 @@ def trace(frame, event, arg): self.assertNotInBytecode(f, "LOAD_FAST_CHECK") -class DirectiCfgOptimizerTests(CfgOptimizationTestCase): +class DirectCfgOptimizerTests(CfgOptimizationTestCase): def cfg_optimization_test(self, insts, expected_insts, - consts=None, expected_consts=None): + consts=None, expected_consts=None, + nlocals=0): if expected_consts is None: expected_consts = consts - opt_insts, opt_consts = self.get_optimized(insts, consts) + opt_insts, opt_consts = self.get_optimized(insts, consts, nlocals) expected_insts = self.normalize_insts(expected_insts) self.assertInstructionsMatch(opt_insts, expected_insts) self.assertEqual(opt_consts, expected_consts) @@ -1058,6 +1059,19 @@ def test_conditional_jump_backward_const_condition(self): ] self.cfg_optimization_test(insts, expected_insts, consts=list(range(5))) + def test_no_unsafe_static_swap(self): + # We can't change order of two stores to the same location + insts = [ + ('LOAD_CONST', 0, 1), + ('LOAD_CONST', 1, 2), + ('LOAD_CONST', 2, 3), + ('SWAP', 3, 4), + ('STORE_FAST', 1, 4), + ('STORE_FAST', 1, 4), + ('POP_TOP', 0, 4), + ('RETURN_VALUE', 5) + ] + self.cfg_optimization_test(insts, insts, consts=list(range(3)), nlocals=1) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_perfmaps.py b/Lib/test/test_perfmaps.py new file mode 100644 index 00000000000000..a17adb89f55360 --- /dev/null +++ b/Lib/test/test_perfmaps.py @@ -0,0 +1,19 @@ +import os +import sys +import unittest + +from _testinternalcapi import perf_map_state_teardown, write_perf_map_entry + +if sys.platform != 'linux': + raise unittest.SkipTest('Linux only') + + +class TestPerfMapWriting(unittest.TestCase): + def test_write_perf_map_entry(self): + self.assertEqual(write_perf_map_entry(0x1234, 5678, "entry1"), 0) + self.assertEqual(write_perf_map_entry(0x2345, 6789, "entry2"), 0) + with open(f"/tmp/perf-{os.getpid()}.map") as f: + perf_file_contents = f.read() + self.assertIn("1234 162e entry1", perf_file_contents) + self.assertIn("2345 1a85 entry2", perf_file_contents) + perf_map_state_teardown() diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index c723bb362c5d87..c9c2b42861c6f4 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -312,8 +312,8 @@ def setUp(self): self.orig_pty_waitpid = pty.waitpid self.fds = [] # A list of file descriptors to close. self.files = [] - self.select_rfds_lengths = [] - self.select_rfds_results = [] + self.select_input = [] + self.select_output = [] self.tcsetattr_mode_setting = None def tearDown(self): @@ -350,8 +350,8 @@ def _socketpair(self): def _mock_select(self, rfds, wfds, xfds): # This will raise IndexError when no more expected calls exist. - self.assertEqual(self.select_rfds_lengths.pop(0), len(rfds)) - return self.select_rfds_results.pop(0), [], [] + self.assertEqual((rfds, wfds, xfds), self.select_input.pop(0)) + return self.select_output.pop(0) def _make_mock_fork(self, pid): def mock_fork(): @@ -374,11 +374,13 @@ def test__copy_to_each(self): os.write(masters[1], b'from master') os.write(write_to_stdin_fd, b'from stdin') - # Expect two select calls, the last one will cause IndexError + # Expect three select calls, the last one will cause IndexError pty.select = self._mock_select - self.select_rfds_lengths.append(2) - self.select_rfds_results.append([mock_stdin_fd, masters[0]]) - self.select_rfds_lengths.append(2) + self.select_input.append(([mock_stdin_fd, masters[0]], [], [])) + self.select_output.append(([mock_stdin_fd, masters[0]], [], [])) + self.select_input.append(([mock_stdin_fd, masters[0]], [mock_stdout_fd, masters[0]], [])) + self.select_output.append(([], [mock_stdout_fd, masters[0]], [])) + self.select_input.append(([mock_stdin_fd, masters[0]], [], [])) with self.assertRaises(IndexError): pty._copy(masters[0]) diff --git a/Lib/test/test_unicode.py b/Lib/test/test_str.py similarity index 99% rename from Lib/test/test_unicode.py rename to Lib/test/test_str.py index 4ebbb9d32a3d75..a6bcc2455de15e 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_str.py @@ -55,8 +55,7 @@ def duplicate_string(text): class StrSubclass(str): pass -class UnicodeTest(string_tests.CommonTest, - string_tests.MixinStrUnicodeUserStringTest, +class StrTest(string_tests.StringLikeTest, string_tests.MixinStrUnicodeTest, unittest.TestCase): @@ -213,7 +212,7 @@ def test_pickle_iterator(self): self.assertEqual(case, pickled) def test_count(self): - string_tests.CommonTest.test_count(self) + string_tests.StringLikeTest.test_count(self) # check mixed argument types self.checkequalnofix(3, 'aaa', 'count', 'a') self.checkequalnofix(0, 'aaa', 'count', 'b') @@ -243,7 +242,7 @@ class MyStr(str): self.checkequal(3, MyStr('aaa'), 'count', 'a') def test_find(self): - string_tests.CommonTest.test_find(self) + string_tests.StringLikeTest.test_find(self) # test implementation details of the memchr fast path self.checkequal(100, 'a' * 100 + '\u0102', 'find', '\u0102') self.checkequal(-1, 'a' * 100 + '\u0102', 'find', '\u0201') @@ -288,7 +287,7 @@ def test_find(self): self.checkequal(-1, '\u0102' * 100, 'find', '\u0102\U00100304') def test_rfind(self): - string_tests.CommonTest.test_rfind(self) + string_tests.StringLikeTest.test_rfind(self) # test implementation details of the memrchr fast path self.checkequal(0, '\u0102' + 'a' * 100 , 'rfind', '\u0102') self.checkequal(-1, '\u0102' + 'a' * 100 , 'rfind', '\u0201') @@ -329,7 +328,7 @@ def test_rfind(self): self.checkequal(-1, '\u0102' * 100, 'rfind', '\U00100304\u0102') def test_index(self): - string_tests.CommonTest.test_index(self) + string_tests.StringLikeTest.test_index(self) self.checkequalnofix(0, 'abcdefghiabc', 'index', '') self.checkequalnofix(3, 'abcdefghiabc', 'index', 'def') self.checkequalnofix(0, 'abcdefghiabc', 'index', 'abc') @@ -353,7 +352,7 @@ def test_index(self): self.assertRaises(ValueError, ('\u0102' * 100).index, '\u0102\U00100304') def test_rindex(self): - string_tests.CommonTest.test_rindex(self) + string_tests.StringLikeTest.test_rindex(self) self.checkequalnofix(12, 'abcdefghiabc', 'rindex', '') self.checkequalnofix(3, 'abcdefghiabc', 'rindex', 'def') self.checkequalnofix(9, 'abcdefghiabc', 'rindex', 'abc') @@ -449,7 +448,7 @@ def test_maketrans_translate(self): self.assertRaises(TypeError, 'abababc'.translate, 'abc', 'xyz') def test_split(self): - string_tests.CommonTest.test_split(self) + string_tests.StringLikeTest.test_split(self) # test mixed kinds for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'): @@ -466,7 +465,7 @@ def test_split(self): left + delim * 2 + right, 'split', delim *2) def test_rsplit(self): - string_tests.CommonTest.test_rsplit(self) + string_tests.StringLikeTest.test_rsplit(self) # test mixed kinds for left, right in ('ba', 'юё', '\u0101\u0100', '\U00010301\U00010300'): left *= 9 @@ -486,7 +485,7 @@ def test_rsplit(self): left + right, 'rsplit', None) def test_partition(self): - string_tests.MixinStrUnicodeUserStringTest.test_partition(self) + string_tests.StringLikeTest.test_partition(self) # test mixed kinds self.checkequal(('ABCDEFGH', '', ''), 'ABCDEFGH', 'partition', '\u4200') for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'): @@ -503,7 +502,7 @@ def test_partition(self): left + delim * 2 + right, 'partition', delim * 2) def test_rpartition(self): - string_tests.MixinStrUnicodeUserStringTest.test_rpartition(self) + string_tests.StringLikeTest.test_rpartition(self) # test mixed kinds self.checkequal(('', '', 'ABCDEFGH'), 'ABCDEFGH', 'rpartition', '\u4200') for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'): @@ -520,7 +519,7 @@ def test_rpartition(self): left + delim * 2 + right, 'rpartition', delim * 2) def test_join(self): - string_tests.MixinStrUnicodeUserStringTest.test_join(self) + string_tests.StringLikeTest.test_join(self) class MyWrapper: def __init__(self, sval): self.sval = sval @@ -547,7 +546,7 @@ def test_join_overflow(self): self.assertRaises(OverflowError, ''.join, seq) def test_replace(self): - string_tests.CommonTest.test_replace(self) + string_tests.StringLikeTest.test_replace(self) # method call forwarded from str implementation because of unicode argument self.checkequalnofix('one@two!three!', 'one!two!three!', 'replace', '!', '@', 1) @@ -866,7 +865,7 @@ def test_surrogates(self): def test_lower(self): - string_tests.CommonTest.test_lower(self) + string_tests.StringLikeTest.test_lower(self) self.assertEqual('\U00010427'.lower(), '\U0001044F') self.assertEqual('\U00010427\U00010427'.lower(), '\U0001044F\U0001044F') @@ -897,7 +896,7 @@ def test_casefold(self): self.assertEqual('\u00b5'.casefold(), '\u03bc') def test_upper(self): - string_tests.CommonTest.test_upper(self) + string_tests.StringLikeTest.test_upper(self) self.assertEqual('\U0001044F'.upper(), '\U00010427') self.assertEqual('\U0001044F\U0001044F'.upper(), '\U00010427\U00010427') @@ -914,7 +913,7 @@ def test_upper(self): self.assertEqual('\u2177'.upper(), '\u2167') def test_capitalize(self): - string_tests.CommonTest.test_capitalize(self) + string_tests.StringLikeTest.test_capitalize(self) self.assertEqual('\U0001044F'.capitalize(), '\U00010427') self.assertEqual('\U0001044F\U0001044F'.capitalize(), '\U00010427\U0001044F') @@ -948,7 +947,7 @@ def test_title(self): self.assertEqual('A\u03a3A'.title(), 'A\u03c3a') def test_swapcase(self): - string_tests.CommonTest.test_swapcase(self) + string_tests.StringLikeTest.test_swapcase(self) self.assertEqual('\U0001044F'.swapcase(), '\U00010427') self.assertEqual('\U00010427'.swapcase(), '\U0001044F') self.assertEqual('\U0001044F\U0001044F'.swapcase(), @@ -974,7 +973,7 @@ def test_swapcase(self): self.assertEqual('\u1fd2'.swapcase(), '\u0399\u0308\u0300') def test_center(self): - string_tests.CommonTest.test_center(self) + string_tests.StringLikeTest.test_center(self) self.assertEqual('x'.center(2, '\U0010FFFF'), 'x\U0010FFFF') self.assertEqual('x'.center(3, '\U0010FFFF'), @@ -1475,7 +1474,7 @@ def __format__(self, spec): self.assertEqual('{f:{}}{}{g}'.format(2, 4, f=1, g='g'), ' 14g') def test_formatting(self): - string_tests.MixinStrUnicodeUserStringTest.test_formatting(self) + string_tests.StringLikeTest.test_formatting(self) # Testing Unicode formatting strings... self.assertEqual("%s, %s" % ("abc", "abc"), 'abc, abc') self.assertEqual("%s, %s, %i, %f, %5.2f" % ("abc", "abc", 1, 2, 3), 'abc, abc, 1, 2.000000, 3.00') diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 3880125807f235..92f81eaafb1c93 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1,6 +1,7 @@ import unittest from unittest import mock from test import support +from test.support import check_sanitizer from test.support import import_helper from test.support import os_helper from test.support import warnings_helper @@ -790,6 +791,8 @@ def test_env(self): @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') == 1, 'The Python shared library cannot be loaded ' 'with an empty environment.') + @unittest.skipIf(check_sanitizer(address=True), + 'AddressSanitizer adds to the environment.') def test_empty_env(self): """Verify that env={} is as empty as possible.""" diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index f959bbb4400702..477879db2fd493 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -1877,6 +1877,68 @@ def f(x: *b) ^^^^^^^^^^^ SyntaxError: bytes can only contain ASCII literal characters +Invalid expressions in type scopes: + + >>> type A[T: (x:=3)] = int + Traceback (most recent call last): + ... + SyntaxError: named expression cannot be used within a TypeVar bound + + >>> type A[T: (yield 3)] = int + Traceback (most recent call last): + ... + SyntaxError: yield expression cannot be used within a TypeVar bound + + >>> type A[T: (await 3)] = int + Traceback (most recent call last): + ... + SyntaxError: await expression cannot be used within a TypeVar bound + + >>> type A[T: (yield from [])] = int + Traceback (most recent call last): + ... + SyntaxError: yield expression cannot be used within a TypeVar bound + + >>> type A = (x := 3) + Traceback (most recent call last): + ... + SyntaxError: named expression cannot be used within a type alias + + >>> type A = (yield 3) + Traceback (most recent call last): + ... + SyntaxError: yield expression cannot be used within a type alias + + >>> type A = (await 3) + Traceback (most recent call last): + ... + SyntaxError: await expression cannot be used within a type alias + + >>> type A = (yield from []) + Traceback (most recent call last): + ... + SyntaxError: yield expression cannot be used within a type alias + + >>> class A[T]((x := 3)): ... + Traceback (most recent call last): + ... + SyntaxError: named expression cannot be used within the definition of a generic + + >>> class A[T]((yield 3)): ... + Traceback (most recent call last): + ... + SyntaxError: yield expression cannot be used within the definition of a generic + + >>> class A[T]((await 3)): ... + Traceback (most recent call last): + ... + SyntaxError: await expression cannot be used within the definition of a generic + + >>> class A[T]((yield from [])): ... + Traceback (most recent call last): + ... + SyntaxError: yield expression cannot be used within the definition of a generic + """ import re diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index e1db450bf8a2ef..d81501f6f1df6a 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1449,7 +1449,7 @@ def func(): check(x, size('3Pi3c7P2ic??2P')) # function def func(): pass - check(func, size('14Pi')) + check(func, size('15Pi')) class c(): @staticmethod def foo(): diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index 4411603af18cd3..5603c3cdbf3c5e 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -1524,6 +1524,52 @@ def __init__(self): (3, 'return'), (1, 'return')]) + def test_class_creation_with_decorator(self): + def func(): + def decorator(arg): + def _dec(c): + return c + return _dec + + @decorator(6) + @decorator( + len([8]), + ) + class MyObject: + pass + + self.run_and_compare(func, [ + (0, 'call'), + (1, 'line'), + (6, 'line'), + (1, 'call'), + (2, 'line'), + (4, 'line'), + (4, 'return'), + (7, 'line'), + (8, 'line'), + (7, 'line'), + (1, 'call'), + (2, 'line'), + (4, 'line'), + (4, 'return'), + (10, 'line'), + (6, 'call'), + (6, 'line'), + (11, 'line'), + (11, 'return'), + (7, 'line'), + (2, 'call'), + (3, 'line'), + (3, 'return'), + (6, 'line'), + (2, 'call'), + (3, 'line'), + (3, 'return'), + (10, 'line'), + (10, 'return'), + ]) + @support.cpython_only def test_no_line_event_after_creating_generator(self): # Spurious line events before call events only show up with C tracer @@ -1568,6 +1614,62 @@ def func(): self.run_and_compare(func, EXPECTED_EVENTS) + def test_settrace_error(self): + + raised = False + def error_once(frame, event, arg): + nonlocal raised + if not raised: + raised = True + raise Exception + return error + + try: + sys._getframe().f_trace = error_once + sys.settrace(error_once) + len([]) + except Exception as ex: + count = 0 + tb = ex.__traceback__ + print(tb) + while tb: + if tb.tb_frame.f_code.co_name == "test_settrace_error": + count += 1 + tb = tb.tb_next + if count == 0: + self.fail("Traceback is missing frame") + elif count > 1: + self.fail("Traceback has frame more than once") + else: + self.fail("No exception raised") + finally: + sys.settrace(None) + + @support.cpython_only + def test_testcapi_settrace_error(self): + + # Skip this test if the _testcapi module isn't available. + _testcapi = import_helper.import_module('_testcapi') + + try: + _testcapi.settrace_to_error([]) + len([]) + except Exception as ex: + count = 0 + tb = ex.__traceback__ + while tb: + if tb.tb_frame.f_code.co_name == "test_testcapi_settrace_error": + count += 1 + tb = tb.tb_next + if count == 0: + self.fail("Traceback is missing frame") + elif count > 1: + self.fail("Traceback has frame more than once") + else: + self.fail("No exception raised") + finally: + sys.settrace(None) + def test_very_large_function(self): # There is a separate code path when the number of lines > (1 << 15). d = {} diff --git a/Lib/test/test_tabnanny.py b/Lib/test/test_tabnanny.py index afb8da719b0eed..aa700118f735d9 100644 --- a/Lib/test/test_tabnanny.py +++ b/Lib/test/test_tabnanny.py @@ -223,7 +223,7 @@ def test_when_nannynag_error_verbose(self): with TemporaryPyFile(SOURCE_CODES["nannynag_errored"]) as file_path: out = f"{file_path!r}: *** Line 3: trouble in tab city! ***\n" out += "offending line: '\\tprint(\"world\")\\n'\n" - out += "indent not equal e.g. at tab size 1\n" + out += "inconsistent use of tabs and spaces in indentation\n" tabnanny.verbose = 1 self.verify_tabnanny_check(file_path, out=out) @@ -315,9 +315,9 @@ def validate_cmd(self, *args, stdout="", stderr="", partial=False, expect_failur def test_with_errored_file(self): """Should displays error when errored python file is given.""" with TemporaryPyFile(SOURCE_CODES["wrong_indented"]) as file_path: - stderr = f"{file_path!r}: Indentation Error: " + stderr = f"{file_path!r}: Token Error: " stderr += ('unindent does not match any outer indentation level' - ' (, line 3)') + ' (, line 3)') self.validate_cmd(file_path, stderr=stderr, expect_failure=True) def test_with_error_free_file(self): diff --git a/Lib/test/test_telnetlib.py b/Lib/test/test_telnetlib.py deleted file mode 100644 index a9cade2ee466f9..00000000000000 --- a/Lib/test/test_telnetlib.py +++ /dev/null @@ -1,405 +0,0 @@ -import socket -import selectors -import threading -import contextlib - -from test import support -from test.support import socket_helper, warnings_helper -import unittest - -support.requires_working_socket(module=True) - -telnetlib = warnings_helper.import_deprecated('telnetlib') - -HOST = socket_helper.HOST - -def server(evt, serv): - serv.listen() - evt.set() - try: - conn, addr = serv.accept() - conn.close() - except TimeoutError: - pass - finally: - serv.close() - -class GeneralTests(unittest.TestCase): - - def setUp(self): - self.evt = threading.Event() - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.settimeout(60) # Safety net. Look issue 11812 - self.port = socket_helper.bind_port(self.sock) - self.thread = threading.Thread(target=server, args=(self.evt,self.sock)) - self.thread.daemon = True - self.thread.start() - self.evt.wait() - - def tearDown(self): - self.thread.join() - del self.thread # Clear out any dangling Thread objects. - - def testBasic(self): - # connects - telnet = telnetlib.Telnet(HOST, self.port) - telnet.sock.close() - - def testContextManager(self): - with telnetlib.Telnet(HOST, self.port) as tn: - self.assertIsNotNone(tn.get_socket()) - self.assertIsNone(tn.get_socket()) - - def testTimeoutDefault(self): - self.assertTrue(socket.getdefaulttimeout() is None) - socket.setdefaulttimeout(30) - try: - telnet = telnetlib.Telnet(HOST, self.port) - finally: - socket.setdefaulttimeout(None) - self.assertEqual(telnet.sock.gettimeout(), 30) - telnet.sock.close() - - def testTimeoutNone(self): - # None, having other default - self.assertTrue(socket.getdefaulttimeout() is None) - socket.setdefaulttimeout(30) - try: - telnet = telnetlib.Telnet(HOST, self.port, timeout=None) - finally: - socket.setdefaulttimeout(None) - self.assertTrue(telnet.sock.gettimeout() is None) - telnet.sock.close() - - def testTimeoutValue(self): - telnet = telnetlib.Telnet(HOST, self.port, timeout=30) - self.assertEqual(telnet.sock.gettimeout(), 30) - telnet.sock.close() - - def testTimeoutOpen(self): - telnet = telnetlib.Telnet() - telnet.open(HOST, self.port, timeout=30) - self.assertEqual(telnet.sock.gettimeout(), 30) - telnet.sock.close() - - def testGetters(self): - # Test telnet getter methods - telnet = telnetlib.Telnet(HOST, self.port, timeout=30) - t_sock = telnet.sock - self.assertEqual(telnet.get_socket(), t_sock) - self.assertEqual(telnet.fileno(), t_sock.fileno()) - telnet.sock.close() - -class SocketStub(object): - ''' a socket proxy that re-defines sendall() ''' - def __init__(self, reads=()): - self.reads = list(reads) # Intentionally make a copy. - self.writes = [] - self.block = False - def sendall(self, data): - self.writes.append(data) - def recv(self, size): - out = b'' - while self.reads and len(out) < size: - out += self.reads.pop(0) - if len(out) > size: - self.reads.insert(0, out[size:]) - out = out[:size] - return out - -class TelnetAlike(telnetlib.Telnet): - def fileno(self): - raise NotImplementedError() - def close(self): pass - def sock_avail(self): - return (not self.sock.block) - def msg(self, msg, *args): - with support.captured_stdout() as out: - telnetlib.Telnet.msg(self, msg, *args) - self._messages += out.getvalue() - return - -class MockSelector(selectors.BaseSelector): - - def __init__(self): - self.keys = {} - - @property - def resolution(self): - return 1e-3 - - def register(self, fileobj, events, data=None): - key = selectors.SelectorKey(fileobj, 0, events, data) - self.keys[fileobj] = key - return key - - def unregister(self, fileobj): - return self.keys.pop(fileobj) - - def select(self, timeout=None): - block = False - for fileobj in self.keys: - if isinstance(fileobj, TelnetAlike): - block = fileobj.sock.block - break - if block: - return [] - else: - return [(key, key.events) for key in self.keys.values()] - - def get_map(self): - return self.keys - - -@contextlib.contextmanager -def test_socket(reads): - def new_conn(*ignored): - return SocketStub(reads) - try: - old_conn = socket.create_connection - socket.create_connection = new_conn - yield None - finally: - socket.create_connection = old_conn - return - -def test_telnet(reads=(), cls=TelnetAlike): - ''' return a telnetlib.Telnet object that uses a SocketStub with - reads queued up to be read ''' - for x in reads: - assert type(x) is bytes, x - with test_socket(reads): - telnet = cls('dummy', 0) - telnet._messages = '' # debuglevel output - return telnet - -class ExpectAndReadTestCase(unittest.TestCase): - def setUp(self): - self.old_selector = telnetlib._TelnetSelector - telnetlib._TelnetSelector = MockSelector - def tearDown(self): - telnetlib._TelnetSelector = self.old_selector - -class ReadTests(ExpectAndReadTestCase): - def test_read_until(self): - """ - read_until(expected, timeout=None) - test the blocking version of read_util - """ - want = [b'xxxmatchyyy'] - telnet = test_telnet(want) - data = telnet.read_until(b'match') - self.assertEqual(data, b'xxxmatch', msg=(telnet.cookedq, telnet.rawq, telnet.sock.reads)) - - reads = [b'x' * 50, b'match', b'y' * 50] - expect = b''.join(reads[:-1]) - telnet = test_telnet(reads) - data = telnet.read_until(b'match') - self.assertEqual(data, expect) - - - def test_read_all(self): - """ - read_all() - Read all data until EOF; may block. - """ - reads = [b'x' * 500, b'y' * 500, b'z' * 500] - expect = b''.join(reads) - telnet = test_telnet(reads) - data = telnet.read_all() - self.assertEqual(data, expect) - return - - def test_read_some(self): - """ - read_some() - Read at least one byte or EOF; may block. - """ - # test 'at least one byte' - telnet = test_telnet([b'x' * 500]) - data = telnet.read_some() - self.assertTrue(len(data) >= 1) - # test EOF - telnet = test_telnet() - data = telnet.read_some() - self.assertEqual(b'', data) - - def _read_eager(self, func_name): - """ - read_*_eager() - Read all data available already queued or on the socket, - without blocking. - """ - want = b'x' * 100 - telnet = test_telnet([want]) - func = getattr(telnet, func_name) - telnet.sock.block = True - self.assertEqual(b'', func()) - telnet.sock.block = False - data = b'' - while True: - try: - data += func() - except EOFError: - break - self.assertEqual(data, want) - - def test_read_eager(self): - # read_eager and read_very_eager make the same guarantees - # (they behave differently but we only test the guarantees) - self._read_eager('read_eager') - self._read_eager('read_very_eager') - # NB -- we need to test the IAC block which is mentioned in the - # docstring but not in the module docs - - def read_very_lazy(self): - want = b'x' * 100 - telnet = test_telnet([want]) - self.assertEqual(b'', telnet.read_very_lazy()) - while telnet.sock.reads: - telnet.fill_rawq() - data = telnet.read_very_lazy() - self.assertEqual(want, data) - self.assertRaises(EOFError, telnet.read_very_lazy) - - def test_read_lazy(self): - want = b'x' * 100 - telnet = test_telnet([want]) - self.assertEqual(b'', telnet.read_lazy()) - data = b'' - while True: - try: - read_data = telnet.read_lazy() - data += read_data - if not read_data: - telnet.fill_rawq() - except EOFError: - break - self.assertTrue(want.startswith(data)) - self.assertEqual(data, want) - -class nego_collector(object): - def __init__(self, sb_getter=None): - self.seen = b'' - self.sb_getter = sb_getter - self.sb_seen = b'' - - def do_nego(self, sock, cmd, opt): - self.seen += cmd + opt - if cmd == tl.SE and self.sb_getter: - sb_data = self.sb_getter() - self.sb_seen += sb_data - -tl = telnetlib - -class WriteTests(unittest.TestCase): - '''The only thing that write does is replace each tl.IAC for - tl.IAC+tl.IAC''' - - def test_write(self): - data_sample = [b'data sample without IAC', - b'data sample with' + tl.IAC + b' one IAC', - b'a few' + tl.IAC + tl.IAC + b' iacs' + tl.IAC, - tl.IAC, - b''] - for data in data_sample: - telnet = test_telnet() - telnet.write(data) - written = b''.join(telnet.sock.writes) - self.assertEqual(data.replace(tl.IAC,tl.IAC+tl.IAC), written) - -class OptionTests(unittest.TestCase): - # RFC 854 commands - cmds = [tl.AO, tl.AYT, tl.BRK, tl.EC, tl.EL, tl.GA, tl.IP, tl.NOP] - - def _test_command(self, data): - """ helper for testing IAC + cmd """ - telnet = test_telnet(data) - data_len = len(b''.join(data)) - nego = nego_collector() - telnet.set_option_negotiation_callback(nego.do_nego) - txt = telnet.read_all() - cmd = nego.seen - self.assertTrue(len(cmd) > 0) # we expect at least one command - self.assertIn(cmd[:1], self.cmds) - self.assertEqual(cmd[1:2], tl.NOOPT) - self.assertEqual(data_len, len(txt + cmd)) - nego.sb_getter = None # break the nego => telnet cycle - - def test_IAC_commands(self): - for cmd in self.cmds: - self._test_command([tl.IAC, cmd]) - self._test_command([b'x' * 100, tl.IAC, cmd, b'y'*100]) - self._test_command([b'x' * 10, tl.IAC, cmd, b'y'*10]) - # all at once - self._test_command([tl.IAC + cmd for (cmd) in self.cmds]) - - def test_SB_commands(self): - # RFC 855, subnegotiations portion - send = [tl.IAC + tl.SB + tl.IAC + tl.SE, - tl.IAC + tl.SB + tl.IAC + tl.IAC + tl.IAC + tl.SE, - tl.IAC + tl.SB + tl.IAC + tl.IAC + b'aa' + tl.IAC + tl.SE, - tl.IAC + tl.SB + b'bb' + tl.IAC + tl.IAC + tl.IAC + tl.SE, - tl.IAC + tl.SB + b'cc' + tl.IAC + tl.IAC + b'dd' + tl.IAC + tl.SE, - ] - telnet = test_telnet(send) - nego = nego_collector(telnet.read_sb_data) - telnet.set_option_negotiation_callback(nego.do_nego) - txt = telnet.read_all() - self.assertEqual(txt, b'') - want_sb_data = tl.IAC + tl.IAC + b'aabb' + tl.IAC + b'cc' + tl.IAC + b'dd' - self.assertEqual(nego.sb_seen, want_sb_data) - self.assertEqual(b'', telnet.read_sb_data()) - nego.sb_getter = None # break the nego => telnet cycle - - def test_debuglevel_reads(self): - # test all the various places that self.msg(...) is called - given_a_expect_b = [ - # Telnet.fill_rawq - (b'a', ": recv b''\n"), - # Telnet.process_rawq - (tl.IAC + bytes([88]), ": IAC 88 not recognized\n"), - (tl.IAC + tl.DO + bytes([1]), ": IAC DO 1\n"), - (tl.IAC + tl.DONT + bytes([1]), ": IAC DONT 1\n"), - (tl.IAC + tl.WILL + bytes([1]), ": IAC WILL 1\n"), - (tl.IAC + tl.WONT + bytes([1]), ": IAC WONT 1\n"), - ] - for a, b in given_a_expect_b: - telnet = test_telnet([a]) - telnet.set_debuglevel(1) - txt = telnet.read_all() - self.assertIn(b, telnet._messages) - return - - def test_debuglevel_write(self): - telnet = test_telnet() - telnet.set_debuglevel(1) - telnet.write(b'xxx') - expected = "send b'xxx'\n" - self.assertIn(expected, telnet._messages) - - def test_debug_accepts_str_port(self): - # Issue 10695 - with test_socket([]): - telnet = TelnetAlike('dummy', '0') - telnet._messages = '' - telnet.set_debuglevel(1) - telnet.msg('test') - self.assertRegex(telnet._messages, r'0.*test') - - -class ExpectTests(ExpectAndReadTestCase): - def test_expect(self): - """ - expect(expected, [timeout]) - Read until the expected string has been seen, or a timeout is - hit (default is no timeout); may block. - """ - want = [b'x' * 10, b'match', b'y' * 10] - telnet = test_telnet(want) - (_,_,data) = telnet.expect([b'match']) - self.assertEqual(data, b''.join(want[:-1])) - - -if __name__ == '__main__': - unittest.main() diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py index ba4ef49078c5a7..76cc16e5b977de 100644 --- a/Lib/test/test_tkinter/test_widgets.py +++ b/Lib/test/test_tkinter/test_widgets.py @@ -76,6 +76,8 @@ def test_configure_menu(self): def test_configure_screen(self): widget = self.create() + if widget._windowingsystem != 'x11': + self.skipTest('Not using Tk for X11') self.assertEqual(widget['screen'], '') try: display = os.environ['DISPLAY'] @@ -899,6 +901,12 @@ def test_coords(self): c.coords(i, [21, 31, 41, 51, 61, 11]) self.assertEqual(c.coords(i), [21.0, 31.0, 41.0, 51.0, 61.0, 11.0]) + c.coords(i, (22, 32), (42, 52), (62, 12)) + self.assertEqual(c.coords(i), [22.0, 32.0, 42.0, 52.0, 62.0, 12.0]) + + c.coords(i, [(23, 33), (43, 53), (63, 13)]) + self.assertEqual(c.coords(i), [23.0, 33.0, 43.0, 53.0, 63.0, 13.0]) + c.coords(i, 20, 30, 60, 10) self.assertEqual(c.coords(i), [20.0, 30.0, 60.0, 10.0]) self.assertEqual(c.bbox(i), (18, 8, 62, 32)) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py index 911b53e5816588..8e7ab3d4b7b578 100644 --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -3,7 +3,7 @@ from tokenize import (tokenize, _tokenize, untokenize, NUMBER, NAME, OP, STRING, ENDMARKER, ENCODING, tok_name, detect_encoding, open as tokenize_open, Untokenizer, generate_tokens, - NEWLINE, _generate_tokens_from_c_tokenizer, DEDENT) + NEWLINE, _generate_tokens_from_c_tokenizer, DEDENT, TokenInfo) from io import BytesIO, StringIO import unittest from textwrap import dedent @@ -82,7 +82,7 @@ def test_basic(self): NAME 'False' (4, 11) (4, 16) COMMENT '# NEWLINE' (4, 17) (4, 26) NEWLINE '\\n' (4, 26) (4, 27) - DEDENT '' (5, 0) (5, 0) + DEDENT '' (4, 27) (4, 27) """) indent_error_file = b"""\ def k(x): @@ -92,9 +92,18 @@ def k(x): readline = BytesIO(indent_error_file).readline with self.assertRaisesRegex(IndentationError, "unindent does not match any " - "outer indentation level"): + "outer indentation level") as e: for tok in tokenize(readline): pass + self.assertEqual(e.exception.lineno, 3) + self.assertEqual(e.exception.filename, '') + self.assertEqual(e.exception.end_lineno, None) + self.assertEqual(e.exception.end_offset, None) + self.assertEqual( + e.exception.msg, + 'unindent does not match any outer indentation level') + self.assertEqual(e.exception.offset, 9) + self.assertEqual(e.exception.text, ' x += 5\n') def test_int(self): # Ordinary integers and binary operators @@ -230,6 +239,10 @@ def number_token(s): continue self.assertEqual(number_token(lit), lit) for lit in INVALID_UNDERSCORE_LITERALS: + try: + number_token(lit) + except SyntaxError: + continue self.assertNotEqual(number_token(lit), lit) def test_string(self): @@ -381,21 +394,119 @@ def test_string(self): STRING 'rb"\""a\\\\\\nb\\\\\\nc"\""' (1, 0) (3, 4) """) self.check_tokenize('f"abc"', """\ - STRING 'f"abc"' (1, 0) (1, 6) + FSTRING_START 'f"' (1, 0) (1, 2) + FSTRING_MIDDLE 'abc' (1, 2) (1, 5) + FSTRING_END '"' (1, 5) (1, 6) """) self.check_tokenize('fR"a{b}c"', """\ - STRING 'fR"a{b}c"' (1, 0) (1, 9) + FSTRING_START 'fR"' (1, 0) (1, 3) + FSTRING_MIDDLE 'a' (1, 3) (1, 4) + OP '{' (1, 4) (1, 5) + NAME 'b' (1, 5) (1, 6) + OP '}' (1, 6) (1, 7) + FSTRING_MIDDLE 'c' (1, 7) (1, 8) + FSTRING_END '"' (1, 8) (1, 9) + """) + self.check_tokenize('fR"a{{{b!r}}}c"', """\ + FSTRING_START 'fR"' (1, 0) (1, 3) + FSTRING_MIDDLE 'a{' (1, 3) (1, 5) + OP '{' (1, 6) (1, 7) + NAME 'b' (1, 7) (1, 8) + OP '!' (1, 8) (1, 9) + NAME 'r' (1, 9) (1, 10) + OP '}' (1, 10) (1, 11) + FSTRING_MIDDLE '}' (1, 11) (1, 12) + FSTRING_MIDDLE 'c' (1, 13) (1, 14) + FSTRING_END '"' (1, 14) (1, 15) + """) + self.check_tokenize('f"{{{1+1}}}"', """\ + FSTRING_START 'f"' (1, 0) (1, 2) + FSTRING_MIDDLE '{' (1, 2) (1, 3) + OP '{' (1, 4) (1, 5) + NUMBER '1' (1, 5) (1, 6) + OP '+' (1, 6) (1, 7) + NUMBER '1' (1, 7) (1, 8) + OP '}' (1, 8) (1, 9) + FSTRING_MIDDLE '}' (1, 9) (1, 10) + FSTRING_END '"' (1, 11) (1, 12) + """) + self.check_tokenize('f"""{f\'\'\'{f\'{f"{1+1}"}\'}\'\'\'}"""', """\ + FSTRING_START 'f\"""' (1, 0) (1, 4) + OP '{' (1, 4) (1, 5) + FSTRING_START "f'''" (1, 5) (1, 9) + OP '{' (1, 9) (1, 10) + FSTRING_START "f'" (1, 10) (1, 12) + OP '{' (1, 12) (1, 13) + FSTRING_START 'f"' (1, 13) (1, 15) + OP '{' (1, 15) (1, 16) + NUMBER '1' (1, 16) (1, 17) + OP '+' (1, 17) (1, 18) + NUMBER '1' (1, 18) (1, 19) + OP '}' (1, 19) (1, 20) + FSTRING_END '"' (1, 20) (1, 21) + OP '}' (1, 21) (1, 22) + FSTRING_END "'" (1, 22) (1, 23) + OP '}' (1, 23) (1, 24) + FSTRING_END "'''" (1, 24) (1, 27) + OP '}' (1, 27) (1, 28) + FSTRING_END '\"""' (1, 28) (1, 31) + """) + self.check_tokenize('f""" x\nstr(data, encoding={invalid!r})\n"""', """\ + FSTRING_START 'f\"""' (1, 0) (1, 4) + FSTRING_MIDDLE ' x\\nstr(data, encoding=' (1, 4) (2, 19) + OP '{' (2, 19) (2, 20) + NAME 'invalid' (2, 20) (2, 27) + OP '!' (2, 27) (2, 28) + NAME 'r' (2, 28) (2, 29) + OP '}' (2, 29) (2, 30) + FSTRING_MIDDLE ')\\n' (2, 30) (3, 0) + FSTRING_END '\"""' (3, 0) (3, 3) + """) + self.check_tokenize('f"""123456789\nsomething{None}bad"""', """\ + FSTRING_START 'f\"""' (1, 0) (1, 4) + FSTRING_MIDDLE '123456789\\nsomething' (1, 4) (2, 9) + OP '{' (2, 9) (2, 10) + NAME 'None' (2, 10) (2, 14) + OP '}' (2, 14) (2, 15) + FSTRING_MIDDLE 'bad' (2, 15) (2, 18) + FSTRING_END '\"""' (2, 18) (2, 21) """) self.check_tokenize('f"""abc"""', """\ - STRING 'f\"\"\"abc\"\"\"' (1, 0) (1, 10) + FSTRING_START 'f\"""' (1, 0) (1, 4) + FSTRING_MIDDLE 'abc' (1, 4) (1, 7) + FSTRING_END '\"""' (1, 7) (1, 10) """) self.check_tokenize(r'f"abc\ def"', """\ - STRING 'f"abc\\\\\\ndef"' (1, 0) (2, 4) + FSTRING_START 'f"' (1, 0) (1, 2) + FSTRING_MIDDLE 'abc\\\\\\ndef' (1, 2) (2, 3) + FSTRING_END '"' (2, 3) (2, 4) """) self.check_tokenize(r'Rf"abc\ def"', """\ - STRING 'Rf"abc\\\\\\ndef"' (1, 0) (2, 4) + FSTRING_START 'Rf"' (1, 0) (1, 3) + FSTRING_MIDDLE 'abc\\\\\\ndef' (1, 3) (2, 3) + FSTRING_END '"' (2, 3) (2, 4) + """) + self.check_tokenize("f'some words {a+b:.3f} more words {c+d=} final words'", """\ + FSTRING_START "f'" (1, 0) (1, 2) + FSTRING_MIDDLE 'some words ' (1, 2) (1, 13) + OP '{' (1, 13) (1, 14) + NAME 'a' (1, 14) (1, 15) + OP '+' (1, 15) (1, 16) + NAME 'b' (1, 16) (1, 17) + OP ':' (1, 17) (1, 18) + FSTRING_MIDDLE '.3f' (1, 18) (1, 21) + OP '}' (1, 21) (1, 22) + FSTRING_MIDDLE ' more words ' (1, 22) (1, 34) + OP '{' (1, 34) (1, 35) + NAME 'c' (1, 35) (1, 36) + OP '+' (1, 36) (1, 37) + NAME 'd' (1, 37) (1, 38) + OP '=' (1, 38) (1, 39) + OP '}' (1, 39) (1, 40) + FSTRING_MIDDLE ' final words' (1, 40) (1, 52) + FSTRING_END "'" (1, 52) (1, 53) """) def test_function(self): @@ -644,8 +755,8 @@ def test_tabs(self): NEWLINE '\\n' (2, 5) (2, 6) INDENT ' \\t' (3, 0) (3, 9) NAME 'pass' (3, 9) (3, 13) - DEDENT '' (4, 0) (4, 0) - DEDENT '' (4, 0) (4, 0) + DEDENT '' (3, 14) (3, 14) + DEDENT '' (3, 14) (3, 14) """) def test_non_ascii_identifiers(self): @@ -857,7 +968,7 @@ async def foo(): NUMBER '1' (2, 17) (2, 18) OP ':' (2, 18) (2, 19) NAME 'pass' (2, 20) (2, 24) - DEDENT '' (3, 0) (3, 0) + DEDENT '' (2, 25) (2, 25) """) self.check_tokenize('''async def foo(async): await''', """\ @@ -905,7 +1016,7 @@ async def bar(): pass NAME 'await' (6, 2) (6, 7) OP '=' (6, 8) (6, 9) NUMBER '2' (6, 10) (6, 11) - DEDENT '' (7, 0) (7, 0) + DEDENT '' (6, 12) (6, 12) """) self.check_tokenize('''\ @@ -943,7 +1054,7 @@ async def bar(): pass NAME 'await' (6, 2) (6, 7) OP '=' (6, 8) (6, 9) NUMBER '2' (6, 10) (6, 11) - DEDENT '' (7, 0) (7, 0) + DEDENT '' (6, 12) (6, 12) """) class GenerateTokensTest(TokenizeTest): @@ -968,7 +1079,7 @@ def decistmt(s): ]) else: result.append((toknum, tokval)) - return untokenize(result).decode('utf-8') + return untokenize(result).decode('utf-8').strip() class TestMisc(TestCase): @@ -1040,33 +1151,16 @@ def readline(): nonlocal first if not first: first = True - return line + yield line else: - return b'' + yield b'' # skip the initial encoding token and the end tokens - tokens = list(_tokenize(readline, encoding='utf-8'))[1:-2] - expected_tokens = [(3, '"ЉЊЈЁЂ"', (1, 0), (1, 7), '"ЉЊЈЁЂ"')] + tokens = list(_tokenize(readline(), encoding='utf-8'))[:-2] + expected_tokens = [TokenInfo(3, '"ЉЊЈЁЂ"', (1, 0), (1, 7), '"ЉЊЈЁЂ"\n')] self.assertEqual(tokens, expected_tokens, "bytes not decoded with encoding") - def test__tokenize_does_not_decode_with_encoding_none(self): - literal = '"ЉЊЈЁЂ"' - first = False - def readline(): - nonlocal first - if not first: - first = True - return literal - else: - return b'' - - # skip the end tokens - tokens = list(_tokenize(readline, encoding=None))[:-2] - expected_tokens = [(3, '"ЉЊЈЁЂ"', (1, 0), (1, 7), '"ЉЊЈЁЂ"')] - self.assertEqual(tokens, expected_tokens, - "string not tokenized when encoding is None") - class TestDetectEncoding(TestCase): @@ -1326,7 +1420,7 @@ class TestTokenize(TestCase): def test_tokenize(self): import tokenize as tokenize_module - encoding = object() + encoding = "utf-8" encoding_used = None def mock_detect_encoding(readline): return encoding, [b'first', b'second'] @@ -1336,7 +1430,10 @@ def mock__tokenize(readline, encoding): encoding_used = encoding out = [] while True: - next_line = readline() + try: + next_line = next(readline) + except StopIteration: + return out if next_line: out.append(next_line) continue @@ -1356,7 +1453,7 @@ def mock_readline(): tokenize_module._tokenize = mock__tokenize try: results = tokenize(mock_readline) - self.assertEqual(list(results), + self.assertEqual(list(results)[1:], [b'first', b'second', b'1', b'2', b'3', b'4']) finally: tokenize_module.detect_encoding = orig_detect_encoding @@ -1652,8 +1749,8 @@ def test_random_files(self): if support.verbose >= 2: print('tokenize', testfile) with open(testfile, 'rb') as f: - with self.subTest(file=testfile): - self.check_roundtrip(f) + # with self.subTest(file=testfile): + self.check_roundtrip(f) def roundtrip(self, code): @@ -2496,13 +2593,13 @@ async def bar(): pass def test_unicode(self): self.check_tokenize("Örter = u'places'\ngrün = U'green'", """\ - NAME 'Örter' (1, 0) (1, 6) - EQUAL '=' (1, 7) (1, 8) - STRING "u'places'" (1, 9) (1, 18) - NEWLINE '' (1, 18) (1, 18) - NAME 'grün' (2, 0) (2, 5) - EQUAL '=' (2, 6) (2, 7) - STRING "U'green'" (2, 8) (2, 16) + NAME 'Örter' (1, 0) (1, 5) + EQUAL '=' (1, 6) (1, 7) + STRING "u'places'" (1, 8) (1, 17) + NEWLINE '' (1, 17) (1, 17) + NAME 'grün' (2, 0) (2, 4) + EQUAL '=' (2, 5) (2, 6) + STRING "U'green'" (2, 7) (2, 15) """) def test_invalid_syntax(self): @@ -2559,8 +2656,7 @@ def generate_source(indents): compile(valid, "", "exec") invalid = generate_source(MAXINDENT) - tokens = list(_generate_tokens_from_c_tokenizer(invalid)) - self.assertEqual(tokens[-1].type, NEWLINE) + self.assertRaises(SyntaxError, lambda: list(_generate_tokens_from_c_tokenizer(invalid))) self.assertRaises( IndentationError, compile, invalid, "", "exec" ) diff --git a/Lib/test/test_tools/test_sundry.py b/Lib/test/test_tools/test_sundry.py index 3177fafb84a65b..2f8ba272164d32 100644 --- a/Lib/test/test_tools/test_sundry.py +++ b/Lib/test/test_tools/test_sundry.py @@ -14,11 +14,6 @@ skip_if_missing() class TestSundryScripts(unittest.TestCase): - # At least make sure the rest don't have syntax errors. When tests are - # added for a script it should be added to the allowlist below. - - skiplist = ['2to3'] - # import logging registers "atfork" functions which keep indirectly the # logging module dictionary alive. Mock the function to be able to unload # cleanly the logging module. @@ -31,9 +26,6 @@ def test_sundry(self, mock_os): continue name = fn[:-3] - if name in self.skiplist: - continue - import_tool(name) finally: # Unload all modules loaded in this test diff --git a/Lib/test/test_type_aliases.py b/Lib/test/test_type_aliases.py new file mode 100644 index 00000000000000..56d150d67afb6f --- /dev/null +++ b/Lib/test/test_type_aliases.py @@ -0,0 +1,224 @@ +import pickle +import types +import unittest +from test.support import check_syntax_error, run_code +from test import mod_generics_cache + +from typing import Callable, TypeAliasType, TypeVar, get_args + + +class TypeParamsInvalidTest(unittest.TestCase): + def test_name_collision_01(self): + check_syntax_error(self, """type TA1[A, **A] = None""", "duplicate type parameter 'A'") + + def test_name_non_collision_02(self): + ns = run_code("""type TA1[A] = lambda A: A""") + self.assertIsInstance(ns["TA1"], TypeAliasType) + self.assertTrue(callable(ns["TA1"].__value__)) + self.assertEqual("arg", ns["TA1"].__value__("arg")) + + def test_name_non_collision_03(self): + ns = run_code(""" + class Outer[A]: + type TA1[A] = None + """ + ) + outer_A, = ns["Outer"].__type_params__ + inner_A, = ns["Outer"].TA1.__type_params__ + self.assertIsNot(outer_A, inner_A) + + +class TypeParamsAccessTest(unittest.TestCase): + def test_alias_access_01(self): + ns = run_code("type TA1[A, B] = dict[A, B]") + alias = ns["TA1"] + self.assertIsInstance(alias, TypeAliasType) + self.assertEqual(alias.__type_params__, get_args(alias.__value__)) + + def test_alias_access_02(self): + ns = run_code(""" + type TA1[A, B] = TA1[A, B] | int + """ + ) + alias = ns["TA1"] + self.assertIsInstance(alias, TypeAliasType) + A, B = alias.__type_params__ + self.assertEqual(alias.__value__, alias[A, B] | int) + + def test_alias_access_03(self): + ns = run_code(""" + class Outer[A]: + def inner[B](self): + type TA1[C] = TA1[A, B] | int + return TA1 + """ + ) + cls = ns["Outer"] + A, = cls.__type_params__ + B, = cls.inner.__type_params__ + alias = cls.inner(None) + self.assertIsInstance(alias, TypeAliasType) + alias2 = cls.inner(None) + self.assertIsNot(alias, alias2) + self.assertEqual(len(alias.__type_params__), 1) + + self.assertEqual(alias.__value__, alias[A, B] | int) + + +class TypeParamsAliasValueTest(unittest.TestCase): + def test_alias_value_01(self): + type TA1 = int + + self.assertIsInstance(TA1, TypeAliasType) + self.assertEqual(TA1.__value__, int) + self.assertEqual(TA1.__parameters__, ()) + self.assertEqual(TA1.__type_params__, ()) + + type TA2 = TA1 | str + + self.assertIsInstance(TA2, TypeAliasType) + a, b = TA2.__value__.__args__ + self.assertEqual(a, TA1) + self.assertEqual(b, str) + self.assertEqual(TA2.__parameters__, ()) + self.assertEqual(TA2.__type_params__, ()) + + def test_alias_value_02(self): + class Parent[A]: + type TA1[B] = dict[A, B] + + self.assertIsInstance(Parent.TA1, TypeAliasType) + self.assertEqual(len(Parent.TA1.__parameters__), 1) + self.assertEqual(len(Parent.__parameters__), 1) + a, = Parent.__parameters__ + b, = Parent.TA1.__parameters__ + self.assertEqual(Parent.__type_params__, (a,)) + self.assertEqual(Parent.TA1.__type_params__, (b,)) + self.assertEqual(Parent.TA1.__value__, dict[a, b]) + + def test_alias_value_03(self): + def outer[A](): + type TA1[B] = dict[A, B] + return TA1 + + o = outer() + self.assertIsInstance(o, TypeAliasType) + self.assertEqual(len(o.__parameters__), 1) + self.assertEqual(len(outer.__type_params__), 1) + b = o.__parameters__[0] + self.assertEqual(o.__type_params__, (b,)) + + def test_alias_value_04(self): + def more_generic[T, *Ts, **P](): + type TA[T2, *Ts2, **P2] = tuple[Callable[P, tuple[T, *Ts]], Callable[P2, tuple[T2, *Ts2]]] + return TA + + alias = more_generic() + self.assertIsInstance(alias, TypeAliasType) + T2, Ts2, P2 = alias.__type_params__ + self.assertEqual(alias.__parameters__, (T2, *Ts2, P2)) + T, Ts, P = more_generic.__type_params__ + self.assertEqual(alias.__value__, tuple[Callable[P, tuple[T, *Ts]], Callable[P2, tuple[T2, *Ts2]]]) + + def test_subscripting(self): + type NonGeneric = int + type Generic[A] = dict[A, A] + type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]] + + with self.assertRaises(TypeError): + NonGeneric[int] + + specialized = Generic[int] + self.assertIsInstance(specialized, types.GenericAlias) + self.assertIs(specialized.__origin__, Generic) + self.assertEqual(specialized.__args__, (int,)) + + specialized2 = VeryGeneric[int, str, float, [bool, range]] + self.assertIsInstance(specialized2, types.GenericAlias) + self.assertIs(specialized2.__origin__, VeryGeneric) + self.assertEqual(specialized2.__args__, (int, str, float, [bool, range])) + + def test_repr(self): + type Simple = int + self.assertEqual(repr(Simple), "Simple") + + def test_recursive_repr(self): + type Recursive = Recursive + self.assertEqual(repr(Recursive), "Recursive") + + type X = list[Y] + type Y = list[X] + self.assertEqual(repr(X), "X") + + +class TypeAliasConstructorTest(unittest.TestCase): + def test_basic(self): + TA = TypeAliasType("TA", int) + self.assertEqual(TA.__name__, "TA") + self.assertIs(TA.__value__, int) + self.assertEqual(TA.__type_params__, ()) + self.assertEqual(TA.__module__, __name__) + + def test_generic(self): + T = TypeVar("T") + TA = TypeAliasType("TA", list[T], type_params=(T,)) + self.assertEqual(TA.__name__, "TA") + self.assertEqual(TA.__value__, list[T]) + self.assertEqual(TA.__type_params__, (T,)) + self.assertEqual(TA.__module__, __name__) + + def test_keywords(self): + TA = TypeAliasType(name="TA", value=int) + self.assertEqual(TA.__name__, "TA") + self.assertIs(TA.__value__, int) + self.assertEqual(TA.__type_params__, ()) + self.assertEqual(TA.__module__, __name__) + + def test_errors(self): + with self.assertRaises(TypeError): + TypeAliasType() + with self.assertRaises(TypeError): + TypeAliasType("TA") + with self.assertRaises(TypeError): + TypeAliasType("TA", list, ()) + with self.assertRaises(TypeError): + TypeAliasType("TA", list, type_params=42) + + +class TypeAliasTypeTest(unittest.TestCase): + def test_immutable(self): + with self.assertRaises(TypeError): + TypeAliasType.whatever = "not allowed" + + def test_no_subclassing(self): + with self.assertRaisesRegex(TypeError, "not an acceptable base type"): + class MyAlias(TypeAliasType): + pass + + def test_union(self): + type Alias1 = int + type Alias2 = str + union = Alias1 | Alias2 + self.assertIsInstance(union, types.UnionType) + self.assertEqual(get_args(union), (Alias1, Alias2)) + union2 = Alias1 | list[float] + self.assertIsInstance(union2, types.UnionType) + self.assertEqual(get_args(union2), (Alias1, list[float])) + union3 = list[range] | Alias1 + self.assertIsInstance(union3, types.UnionType) + self.assertEqual(get_args(union3), (list[range], Alias1)) + + def test_module(self): + self.assertEqual(TypeAliasType.__module__, "typing") + type Alias = int + self.assertEqual(Alias.__module__, __name__) + self.assertEqual(mod_generics_cache.Alias.__module__, + mod_generics_cache.__name__) + self.assertEqual(mod_generics_cache.OldStyle.__module__, + mod_generics_cache.__name__) + + def test_pickling(self): + pickled = pickle.dumps(mod_generics_cache.Alias) + self.assertIs(pickle.loads(pickled), mod_generics_cache.Alias) + pickled = pickle.dumps(mod_generics_cache.OldStyle) + self.assertIs(pickle.loads(pickled), mod_generics_cache.OldStyle) diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py new file mode 100644 index 00000000000000..7b7b6122c028e5 --- /dev/null +++ b/Lib/test/test_type_params.py @@ -0,0 +1,851 @@ +import asyncio +import textwrap +import types +import unittest +from test.support import requires_working_socket, check_syntax_error, run_code + +from typing import Generic, Sequence, TypeVar, TypeVarTuple, ParamSpec, get_args + + +class TypeParamsInvalidTest(unittest.TestCase): + def test_name_collision_01(self): + check_syntax_error(self, """def func[**A, A](): ...""") + + def test_name_non_collision_02(self): + ns = run_code("""def func[A](A): return A""") + func = ns["func"] + self.assertEqual(func(1), 1) + A, = func.__type_params__ + self.assertEqual(A.__name__, "A") + + def test_name_non_collision_03(self): + ns = run_code("""def func[A](*A): return A""") + func = ns["func"] + self.assertEqual(func(1), (1,)) + A, = func.__type_params__ + self.assertEqual(A.__name__, "A") + + def test_name_non_collision_04(self): + # Mangled names should not cause a conflict. + ns = run_code(""" + class ClassA: + def func[__A](self, __A): return __A + """ + ) + cls = ns["ClassA"] + self.assertEqual(cls().func(1), 1) + A, = cls.func.__type_params__ + self.assertEqual(A.__name__, "__A") + + def test_name_non_collision_05(self): + ns = run_code(""" + class ClassA: + def func[_ClassA__A](self, __A): return __A + """ + ) + cls = ns["ClassA"] + self.assertEqual(cls().func(1), 1) + A, = cls.func.__type_params__ + self.assertEqual(A.__name__, "_ClassA__A") + + def test_name_non_collision_06(self): + ns = run_code(""" + class ClassA[X]: + def func(self, X): return X + """ + ) + cls = ns["ClassA"] + self.assertEqual(cls().func(1), 1) + X, = cls.__type_params__ + self.assertEqual(X.__name__, "X") + + def test_name_non_collision_07(self): + ns = run_code(""" + class ClassA[X]: + def func(self): + X = 1 + return X + """ + ) + cls = ns["ClassA"] + self.assertEqual(cls().func(), 1) + X, = cls.__type_params__ + self.assertEqual(X.__name__, "X") + + def test_name_non_collision_08(self): + ns = run_code(""" + class ClassA[X]: + def func(self): + return [X for X in [1, 2]] + """ + ) + cls = ns["ClassA"] + self.assertEqual(cls().func(), [1, 2]) + X, = cls.__type_params__ + self.assertEqual(X.__name__, "X") + + def test_name_non_collision_9(self): + ns = run_code(""" + class ClassA[X]: + def func[X](self): + ... + """ + ) + cls = ns["ClassA"] + outer_X, = cls.__type_params__ + inner_X, = cls.func.__type_params__ + self.assertEqual(outer_X.__name__, "X") + self.assertEqual(inner_X.__name__, "X") + self.assertIsNot(outer_X, inner_X) + + def test_name_non_collision_10(self): + ns = run_code(""" + class ClassA[X]: + X: int + """ + ) + cls = ns["ClassA"] + X, = cls.__type_params__ + self.assertEqual(X.__name__, "X") + self.assertIs(cls.__annotations__["X"], int) + + def test_name_non_collision_13(self): + ns = run_code(""" + X = 1 + def outer(): + def inner[X](): + global X + X = 2 + return inner + """ + ) + self.assertEqual(ns["X"], 1) + outer = ns["outer"] + outer()() + self.assertEqual(ns["X"], 2) + + def test_disallowed_expressions(self): + check_syntax_error(self, "type X = (yield)") + check_syntax_error(self, "type X = (yield from x)") + check_syntax_error(self, "type X = (await 42)") + check_syntax_error(self, "async def f(): type X = (yield)") + check_syntax_error(self, "type X = (y := 3)") + check_syntax_error(self, "class X[T: (yield)]: pass") + check_syntax_error(self, "class X[T: (yield from x)]: pass") + check_syntax_error(self, "class X[T: (await 42)]: pass") + check_syntax_error(self, "class X[T: (y := 3)]: pass") + check_syntax_error(self, "class X[T](y := Sequence[T]): pass") + check_syntax_error(self, "def f[T](y: (x := Sequence[T])): pass") + check_syntax_error(self, "class X[T]([(x := 3) for _ in range(2)] and B): pass") + check_syntax_error(self, "def f[T: [(x := 3) for _ in range(2)]](): pass") + check_syntax_error(self, "type T = [(x := 3) for _ in range(2)]") + + +class TypeParamsNonlocalTest(unittest.TestCase): + def test_nonlocal_disallowed_01(self): + code = """ + def outer(): + X = 1 + def inner[X](): + nonlocal X + return X + """ + check_syntax_error(self, code) + + def test_nonlocal_disallowed_02(self): + code = """ + def outer2[T](): + def inner1(): + nonlocal T + """ + check_syntax_error(self, textwrap.dedent(code)) + + def test_nonlocal_disallowed_03(self): + code = """ + class Cls[T]: + nonlocal T + """ + check_syntax_error(self, textwrap.dedent(code)) + + def test_nonlocal_allowed(self): + code = """ + def func[T](): + T = "func" + def inner(): + nonlocal T + T = "inner" + inner() + assert T == "inner" + """ + ns = run_code(code) + func = ns["func"] + T, = func.__type_params__ + self.assertEqual(T.__name__, "T") + + +class TypeParamsAccessTest(unittest.TestCase): + def test_class_access_01(self): + ns = run_code(""" + class ClassA[A, B](dict[A, B]): + ... + """ + ) + cls = ns["ClassA"] + A, B = cls.__type_params__ + self.assertEqual(types.get_original_bases(cls), (dict[A, B], Generic[A, B])) + + def test_class_access_02(self): + ns = run_code(""" + class MyMeta[A, B](type): ... + class ClassA[A, B](metaclass=MyMeta[A, B]): + ... + """ + ) + meta = ns["MyMeta"] + cls = ns["ClassA"] + A1, B1 = meta.__type_params__ + A2, B2 = cls.__type_params__ + self.assertIsNot(A1, A2) + self.assertIsNot(B1, B2) + self.assertIs(type(cls), meta) + + def test_class_access_03(self): + code = """ + def my_decorator(a): + ... + @my_decorator(A) + class ClassA[A, B](): + ... + """ + + with self.assertRaisesRegex(NameError, "name 'A' is not defined"): + run_code(code) + + def test_function_access_01(self): + ns = run_code(""" + def func[A, B](a: dict[A, B]): + ... + """ + ) + func = ns["func"] + A, B = func.__type_params__ + self.assertEqual(func.__annotations__["a"], dict[A, B]) + + def test_function_access_02(self): + code = """ + def func[A](a = list[A]()): + ... + """ + + with self.assertRaisesRegex(NameError, "name 'A' is not defined"): + run_code(code) + + def test_function_access_03(self): + code = """ + def my_decorator(a): + ... + @my_decorator(A) + def func[A](): + ... + """ + + with self.assertRaisesRegex(NameError, "name 'A' is not defined"): + run_code(code) + + def test_method_access_01(self): + ns = run_code(""" + class ClassA: + x = int + def func[T](self, a: x, b: T): + ... + """ + ) + cls = ns["ClassA"] + self.assertIs(cls.func.__annotations__["a"], int) + T, = cls.func.__type_params__ + self.assertIs(cls.func.__annotations__["b"], T) + + def test_nested_access_01(self): + ns = run_code(""" + class ClassA[A]: + def funcB[B](self): + class ClassC[C]: + def funcD[D](self): + return lambda: (A, B, C, D) + return ClassC + """ + ) + cls = ns["ClassA"] + A, = cls.__type_params__ + B, = cls.funcB.__type_params__ + classC = cls().funcB() + C, = classC.__type_params__ + D, = classC.funcD.__type_params__ + self.assertEqual(classC().funcD()(), (A, B, C, D)) + + def test_out_of_scope_01(self): + code = """ + class ClassA[T]: ... + x = T + """ + + with self.assertRaisesRegex(NameError, "name 'T' is not defined"): + run_code(code) + + def test_out_of_scope_02(self): + code = """ + class ClassA[A]: + def funcB[B](self): ... + + x = B + """ + + with self.assertRaisesRegex(NameError, "name 'B' is not defined"): + run_code(code) + + def test_class_scope_interaction_01(self): + ns = run_code(""" + class C: + x = 1 + def method[T](self, arg: x): pass + """) + cls = ns["C"] + self.assertEqual(cls.method.__annotations__["arg"], 1) + + def test_class_scope_interaction_02(self): + ns = run_code(""" + class C: + class Base: pass + class Child[T](Base): pass + """) + cls = ns["C"] + self.assertEqual(cls.Child.__bases__, (cls.Base, Generic)) + T, = cls.Child.__type_params__ + self.assertEqual(types.get_original_bases(cls.Child), (cls.Base, Generic[T])) + + def test_class_deref(self): + ns = run_code(""" + class C[T]: + T = "class" + type Alias = T + """) + cls = ns["C"] + self.assertEqual(cls.Alias.__value__, "class") + + def test_shadowing_nonlocal(self): + ns = run_code(""" + def outer[T](): + T = "outer" + def inner(): + nonlocal T + T = "inner" + return T + return lambda: T, inner + """) + outer = ns["outer"] + T, = outer.__type_params__ + self.assertEqual(T.__name__, "T") + getter, inner = outer() + self.assertEqual(getter(), "outer") + self.assertEqual(inner(), "inner") + self.assertEqual(getter(), "inner") + + def test_reference_previous_typevar(self): + def func[S, T: Sequence[S]](): + pass + + S, T = func.__type_params__ + self.assertEqual(T.__bound__, Sequence[S]) + + def test_super(self): + class Base: + def meth(self): + return "base" + + class Child(Base): + # Having int in the annotation ensures the class gets cells for both + # __class__ and __classdict__ + def meth[T](self, arg: int) -> T: + return super().meth() + "child" + + c = Child() + self.assertEqual(c.meth(1), "basechild") + + def test_type_alias_containing_lambda(self): + type Alias[T] = lambda: T + T, = Alias.__type_params__ + self.assertIs(Alias.__value__(), T) + + def test_class_base_containing_lambda(self): + # Test that scopes nested inside hidden functions work correctly + outer_var = "outer" + class Base[T]: ... + class Child[T](Base[lambda: (int, outer_var, T)]): ... + base, _ = types.get_original_bases(Child) + func, = get_args(base) + T, = Child.__type_params__ + self.assertEqual(func(), (int, "outer", T)) + + def test_comprehension_01(self): + type Alias[T: ([T for T in (T, [1])[1]], T)] = [T for T in T.__name__] + self.assertEqual(Alias.__value__, ["T"]) + T, = Alias.__type_params__ + self.assertEqual(T.__constraints__, ([1], T)) + + def test_comprehension_02(self): + type Alias[T: [lambda: T for T in (T, [1])[1]]] = [lambda: T for T in T.__name__] + func, = Alias.__value__ + self.assertEqual(func(), "T") + T, = Alias.__type_params__ + func, = T.__bound__ + self.assertEqual(func(), 1) + + +def global_generic_func[T](): + pass + +class GlobalGenericClass[T]: + pass + + +class TypeParamsLazyEvaluationTest(unittest.TestCase): + def test_qualname(self): + class Foo[T]: + pass + + def func[T](): + pass + + self.assertEqual(Foo.__qualname__, "TypeParamsLazyEvaluationTest.test_qualname..Foo") + self.assertEqual(func.__qualname__, "TypeParamsLazyEvaluationTest.test_qualname..func") + self.assertEqual(global_generic_func.__qualname__, "global_generic_func") + self.assertEqual(GlobalGenericClass.__qualname__, "GlobalGenericClass") + + def test_recursive_class(self): + class Foo[T: Foo, U: (Foo, Foo)]: + pass + + type_params = Foo.__type_params__ + self.assertEqual(len(type_params), 2) + self.assertEqual(type_params[0].__name__, "T") + self.assertIs(type_params[0].__bound__, Foo) + self.assertEqual(type_params[0].__constraints__, ()) + + self.assertEqual(type_params[1].__name__, "U") + self.assertIs(type_params[1].__bound__, None) + self.assertEqual(type_params[1].__constraints__, (Foo, Foo)) + + def test_evaluation_error(self): + class Foo[T: Undefined, U: (Undefined,)]: + pass + + type_params = Foo.__type_params__ + with self.assertRaises(NameError): + type_params[0].__bound__ + self.assertEqual(type_params[0].__constraints__, ()) + self.assertIs(type_params[1].__bound__, None) + with self.assertRaises(NameError): + type_params[1].__constraints__ + + Undefined = "defined" + self.assertEqual(type_params[0].__bound__, "defined") + self.assertEqual(type_params[0].__constraints__, ()) + + self.assertIs(type_params[1].__bound__, None) + self.assertEqual(type_params[1].__constraints__, ("defined",)) + + +class TypeParamsClassScopeTest(unittest.TestCase): + def test_alias(self): + class X: + T = int + type U = T + self.assertIs(X.U.__value__, int) + + ns = run_code(""" + glb = "global" + class X: + cls = "class" + type U = (glb, cls) + """) + cls = ns["X"] + self.assertEqual(cls.U.__value__, ("global", "class")) + + def test_bound(self): + class X: + T = int + def foo[U: T](self): ... + self.assertIs(X.foo.__type_params__[0].__bound__, int) + + ns = run_code(""" + glb = "global" + class X: + cls = "class" + def foo[T: glb, U: cls](self): ... + """) + cls = ns["X"] + T, U = cls.foo.__type_params__ + self.assertEqual(T.__bound__, "global") + self.assertEqual(U.__bound__, "class") + + def test_modified_later(self): + class X: + T = int + def foo[U: T](self): ... + type Alias = T + X.T = float + self.assertIs(X.foo.__type_params__[0].__bound__, float) + self.assertIs(X.Alias.__value__, float) + + def test_binding_uses_global(self): + ns = run_code(""" + x = "global" + def outer(): + x = "nonlocal" + class Cls: + type Alias = x + val = Alias.__value__ + def meth[T: x](self, arg: x): ... + bound = meth.__type_params__[0].__bound__ + annotation = meth.__annotations__["arg"] + x = "class" + return Cls + """) + cls = ns["outer"]() + self.assertEqual(cls.val, "global") + self.assertEqual(cls.bound, "global") + self.assertEqual(cls.annotation, "global") + + def test_no_binding_uses_nonlocal(self): + ns = run_code(""" + x = "global" + def outer(): + x = "nonlocal" + class Cls: + type Alias = x + val = Alias.__value__ + def meth[T: x](self, arg: x): ... + bound = meth.__type_params__[0].__bound__ + return Cls + """) + cls = ns["outer"]() + self.assertEqual(cls.val, "nonlocal") + self.assertEqual(cls.bound, "nonlocal") + self.assertEqual(cls.meth.__annotations__["arg"], "nonlocal") + + def test_explicit_global(self): + ns = run_code(""" + x = "global" + def outer(): + x = "nonlocal" + class Cls: + global x + type Alias = x + Cls.x = "class" + return Cls + """) + cls = ns["outer"]() + self.assertEqual(cls.Alias.__value__, "global") + + def test_explicit_global_with_no_static_bound(self): + ns = run_code(""" + def outer(): + class Cls: + global x + type Alias = x + Cls.x = "class" + return Cls + """) + ns["x"] = "global" + cls = ns["outer"]() + self.assertEqual(cls.Alias.__value__, "global") + + def test_explicit_global_with_assignment(self): + ns = run_code(""" + x = "global" + def outer(): + x = "nonlocal" + class Cls: + global x + type Alias = x + x = "global from class" + Cls.x = "class" + return Cls + """) + cls = ns["outer"]() + self.assertEqual(cls.Alias.__value__, "global from class") + + def test_explicit_nonlocal(self): + ns = run_code(""" + x = "global" + def outer(): + x = "nonlocal" + class Cls: + nonlocal x + type Alias = x + x = "class" + return Cls + """) + cls = ns["outer"]() + self.assertEqual(cls.Alias.__value__, "class") + + +class TypeParamsManglingTest(unittest.TestCase): + def test_mangling(self): + class Foo[__T]: + param = __T + def meth[__U](self, arg: __T, arg2: __U): + return (__T, __U) + type Alias[__V] = (__T, __V) + + T = Foo.__type_params__[0] + self.assertEqual(T.__name__, "__T") + U = Foo.meth.__type_params__[0] + self.assertEqual(U.__name__, "__U") + V = Foo.Alias.__type_params__[0] + self.assertEqual(V.__name__, "__V") + + anno = Foo.meth.__annotations__ + self.assertIs(anno["arg"], T) + self.assertIs(anno["arg2"], U) + self.assertEqual(Foo().meth(1, 2), (T, U)) + + self.assertEqual(Foo.Alias.__value__, (T, V)) + + +class TypeParamsComplexCallsTest(unittest.TestCase): + def test_defaults(self): + # Generic functions with both defaults and kwdefaults trigger a specific code path + # in the compiler. + def func[T](a: T = "a", *, b: T = "b"): + return (a, b) + + T, = func.__type_params__ + self.assertIs(func.__annotations__["a"], T) + self.assertIs(func.__annotations__["b"], T) + self.assertEqual(func(), ("a", "b")) + self.assertEqual(func(1), (1, "b")) + self.assertEqual(func(b=2), ("a", 2)) + + def test_complex_base(self): + class Base: + def __init_subclass__(cls, **kwargs) -> None: + cls.kwargs = kwargs + + kwargs = {"c": 3} + # Base classes with **kwargs trigger a different code path in the compiler. + class C[T](Base, a=1, b=2, **kwargs): + pass + + T, = C.__type_params__ + self.assertEqual(T.__name__, "T") + self.assertEqual(C.kwargs, {"a": 1, "b": 2, "c": 3}) + + bases = (Base,) + class C2[T](*bases, **kwargs): + pass + + T, = C2.__type_params__ + self.assertEqual(T.__name__, "T") + self.assertEqual(C2.kwargs, {"c": 3}) + + +class TypeParamsTraditionalTypeVarsTest(unittest.TestCase): + def test_traditional_01(self): + code = """ + from typing import Generic + class ClassA[T](Generic[T]): ... + """ + + with self.assertRaisesRegex(TypeError, r"Cannot inherit from Generic\[...\] multiple times."): + run_code(code) + + def test_traditional_02(self): + from typing import TypeVar + S = TypeVar("S") + with self.assertRaises(TypeError): + class ClassA[T](dict[T, S]): ... + + def test_traditional_03(self): + # This does not generate a runtime error, but it should be + # flagged as an error by type checkers. + from typing import TypeVar + S = TypeVar("S") + def func[T](a: T, b: S) -> T | S: + return a + + +class TypeParamsTypeVarTest(unittest.TestCase): + def test_typevar_01(self): + def func1[A: str, B: str | int, C: (int, str)](): + return (A, B, C) + + a, b, c = func1() + + self.assertIsInstance(a, TypeVar) + self.assertEqual(a.__bound__, str) + self.assertTrue(a.__infer_variance__) + self.assertFalse(a.__covariant__) + self.assertFalse(a.__contravariant__) + + self.assertIsInstance(b, TypeVar) + self.assertEqual(b.__bound__, str | int) + self.assertTrue(b.__infer_variance__) + self.assertFalse(b.__covariant__) + self.assertFalse(b.__contravariant__) + + self.assertIsInstance(c, TypeVar) + self.assertEqual(c.__bound__, None) + self.assertEqual(c.__constraints__, (int, str)) + self.assertTrue(c.__infer_variance__) + self.assertFalse(c.__covariant__) + self.assertFalse(c.__contravariant__) + + def test_typevar_generator(self): + def get_generator[A](): + def generator1[C](): + yield C + + def generator2[B](): + yield A + yield B + yield from generator1() + return generator2 + + gen = get_generator() + + a, b, c = [x for x in gen()] + + self.assertIsInstance(a, TypeVar) + self.assertEqual(a.__name__, "A") + self.assertIsInstance(b, TypeVar) + self.assertEqual(b.__name__, "B") + self.assertIsInstance(c, TypeVar) + self.assertEqual(c.__name__, "C") + + @requires_working_socket() + def test_typevar_coroutine(self): + def get_coroutine[A](): + async def coroutine[B](): + return (A, B) + return coroutine + + co = get_coroutine() + + self.addCleanup(asyncio.set_event_loop_policy, None) + a, b = asyncio.run(co()) + + self.assertIsInstance(a, TypeVar) + self.assertEqual(a.__name__, "A") + self.assertIsInstance(b, TypeVar) + self.assertEqual(b.__name__, "B") + + +class TypeParamsTypeVarTupleTest(unittest.TestCase): + def test_typevartuple_01(self): + code = """def func1[*A: str](): pass""" + check_syntax_error(self, code, "cannot use bound with TypeVarTuple") + code = """def func1[*A: (int, str)](): pass""" + check_syntax_error(self, code, "cannot use constraints with TypeVarTuple") + code = """class X[*A: str]: pass""" + check_syntax_error(self, code, "cannot use bound with TypeVarTuple") + code = """class X[*A: (int, str)]: pass""" + check_syntax_error(self, code, "cannot use constraints with TypeVarTuple") + code = """type X[*A: str] = int""" + check_syntax_error(self, code, "cannot use bound with TypeVarTuple") + code = """type X[*A: (int, str)] = int""" + check_syntax_error(self, code, "cannot use constraints with TypeVarTuple") + + def test_typevartuple_02(self): + def func1[*A](): + return A + + a = func1() + self.assertIsInstance(a, TypeVarTuple) + + +class TypeParamsTypeVarParamSpecTest(unittest.TestCase): + def test_paramspec_01(self): + code = """def func1[**A: str](): pass""" + check_syntax_error(self, code, "cannot use bound with ParamSpec") + code = """def func1[**A: (int, str)](): pass""" + check_syntax_error(self, code, "cannot use constraints with ParamSpec") + code = """class X[**A: str]: pass""" + check_syntax_error(self, code, "cannot use bound with ParamSpec") + code = """class X[**A: (int, str)]: pass""" + check_syntax_error(self, code, "cannot use constraints with ParamSpec") + code = """type X[**A: str] = int""" + check_syntax_error(self, code, "cannot use bound with ParamSpec") + code = """type X[**A: (int, str)] = int""" + check_syntax_error(self, code, "cannot use constraints with ParamSpec") + + def test_paramspec_02(self): + def func1[**A](): + return A + + a = func1() + self.assertIsInstance(a, ParamSpec) + self.assertTrue(a.__infer_variance__) + self.assertFalse(a.__covariant__) + self.assertFalse(a.__contravariant__) + + +class TypeParamsTypeParamsDunder(unittest.TestCase): + def test_typeparams_dunder_class_01(self): + class Outer[A, B]: + class Inner[C, D]: + @staticmethod + def get_typeparams(): + return A, B, C, D + + a, b, c, d = Outer.Inner.get_typeparams() + self.assertEqual(Outer.__type_params__, (a, b)) + self.assertEqual(Outer.Inner.__type_params__, (c, d)) + + self.assertEqual(Outer.__parameters__, (a, b)) + self.assertEqual(Outer.Inner.__parameters__, (c, d)) + + def test_typeparams_dunder_class_02(self): + class ClassA: + pass + + self.assertEqual(ClassA.__type_params__, ()) + + def test_typeparams_dunder_class_03(self): + code = """ + class ClassA[A](): + pass + ClassA.__type_params__ = () + params = ClassA.__type_params__ + """ + + ns = run_code(code) + self.assertEqual(ns["params"], ()) + + def test_typeparams_dunder_function_01(self): + def outer[A, B](): + def inner[C, D](): + return A, B, C, D + + return inner + + inner = outer() + a, b, c, d = inner() + self.assertEqual(outer.__type_params__, (a, b)) + self.assertEqual(inner.__type_params__, (c, d)) + + def test_typeparams_dunder_function_02(self): + def func1(): + pass + + self.assertEqual(func1.__type_params__, ()) + + def test_typeparams_dunder_function_03(self): + code = """ + def func[A](): + pass + func.__type_params__ = () + """ + + ns = run_code(code) + self.assertEqual(ns["func"].__type_params__, ()) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index e1c6a8a7f376eb..b4a5a68a2f7e4e 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -48,11 +48,8 @@ from test import _typed_dict_helper -py_typing = import_helper.import_fresh_module('typing', blocked=['_typing']) -c_typing = import_helper.import_fresh_module('typing', fresh=['_typing']) - - CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes' +NOT_A_BASE_TYPE = "type 'typing.%s' is not an acceptable base type" CANNOT_SUBCLASS_INSTANCE = 'Cannot subclass an instance of %s' @@ -370,6 +367,41 @@ def test_basic_plain(self): self.assertEqual(T, T) # T is an instance of TypeVar self.assertIsInstance(T, TypeVar) + self.assertEqual(T.__name__, 'T') + self.assertEqual(T.__constraints__, ()) + self.assertIs(T.__bound__, None) + self.assertIs(T.__covariant__, False) + self.assertIs(T.__contravariant__, False) + self.assertIs(T.__infer_variance__, False) + + def test_attributes(self): + T_bound = TypeVar('T_bound', bound=int) + self.assertEqual(T_bound.__name__, 'T_bound') + self.assertEqual(T_bound.__constraints__, ()) + self.assertIs(T_bound.__bound__, int) + + T_constraints = TypeVar('T_constraints', int, str) + self.assertEqual(T_constraints.__name__, 'T_constraints') + self.assertEqual(T_constraints.__constraints__, (int, str)) + self.assertIs(T_constraints.__bound__, None) + + T_co = TypeVar('T_co', covariant=True) + self.assertEqual(T_co.__name__, 'T_co') + self.assertIs(T_co.__covariant__, True) + self.assertIs(T_co.__contravariant__, False) + self.assertIs(T_co.__infer_variance__, False) + + T_contra = TypeVar('T_contra', contravariant=True) + self.assertEqual(T_contra.__name__, 'T_contra') + self.assertIs(T_contra.__covariant__, False) + self.assertIs(T_contra.__contravariant__, True) + self.assertIs(T_contra.__infer_variance__, False) + + T_infer = TypeVar('T_infer', infer_variance=True) + self.assertEqual(T_infer.__name__, 'T_infer') + self.assertIs(T_infer.__covariant__, False) + self.assertIs(T_infer.__contravariant__, False) + self.assertIs(T_infer.__infer_variance__, True) def test_typevar_instance_type_error(self): T = TypeVar('T') @@ -430,7 +462,7 @@ def test_no_redefinition(self): self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str)) def test_cannot_subclass(self): - with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): + with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVar'): class V(TypeVar): pass T = TypeVar("T") with self.assertRaisesRegex(TypeError, @@ -446,6 +478,9 @@ def test_bound_errors(self): TypeVar('X', bound=Union) with self.assertRaises(TypeError): TypeVar('X', str, float, bound=Employee) + with self.assertRaisesRegex(TypeError, + r"Bound must be a type\. Got \(1, 2\)\."): + TypeVar('X', bound=(1, 2)) def test_missing__name__(self): # See bpo-39942 @@ -458,6 +493,12 @@ def test_no_bivariant(self): with self.assertRaises(ValueError): TypeVar('T', covariant=True, contravariant=True) + def test_cannot_combine_explicit_and_infer(self): + with self.assertRaises(ValueError): + TypeVar('T', covariant=True, infer_variance=True) + with self.assertRaises(ValueError): + TypeVar('T', contravariant=True, infer_variance=True) + def test_var_substitution(self): T = TypeVar('T') subst = T.__typing_subst__ @@ -1161,7 +1202,7 @@ class A(Generic[Unpack[Ts]]): pass self.assertEndsWith(repr(K[float, str]), 'A[float, str, typing.Unpack[typing.Tuple[str, ...]]]') def test_cannot_subclass(self): - with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): + with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'TypeVarTuple'): class C(TypeVarTuple): pass Ts = TypeVarTuple('Ts') with self.assertRaisesRegex(TypeError, @@ -2654,6 +2695,82 @@ class D(PNonCall): ... with self.assertRaises(TypeError): issubclass(D, PNonCall) + def test_no_weird_caching_with_issubclass_after_isinstance(self): + @runtime_checkable + class Spam(Protocol): + x: int + + class Eggs: + def __init__(self) -> None: + self.x = 42 + + self.assertIsInstance(Eggs(), Spam) + + # gh-104555: If we didn't override ABCMeta.__subclasscheck__ in _ProtocolMeta, + # TypeError wouldn't be raised here, + # as the cached result of the isinstance() check immediately above + # would mean the issubclass() call would short-circuit + # before we got to the "raise TypeError" line + with self.assertRaises(TypeError): + issubclass(Eggs, Spam) + + def test_no_weird_caching_with_issubclass_after_isinstance_2(self): + @runtime_checkable + class Spam(Protocol): + x: int + + class Eggs: ... + + self.assertNotIsInstance(Eggs(), Spam) + + # gh-104555: If we didn't override ABCMeta.__subclasscheck__ in _ProtocolMeta, + # TypeError wouldn't be raised here, + # as the cached result of the isinstance() check immediately above + # would mean the issubclass() call would short-circuit + # before we got to the "raise TypeError" line + with self.assertRaises(TypeError): + issubclass(Eggs, Spam) + + def test_no_weird_caching_with_issubclass_after_isinstance_3(self): + @runtime_checkable + class Spam(Protocol): + x: int + + class Eggs: + def __getattr__(self, attr): + if attr == "x": + return 42 + raise AttributeError(attr) + + self.assertNotIsInstance(Eggs(), Spam) + + # gh-104555: If we didn't override ABCMeta.__subclasscheck__ in _ProtocolMeta, + # TypeError wouldn't be raised here, + # as the cached result of the isinstance() check immediately above + # would mean the issubclass() call would short-circuit + # before we got to the "raise TypeError" line + with self.assertRaises(TypeError): + issubclass(Eggs, Spam) + + def test_no_weird_caching_with_issubclass_after_isinstance_pep695(self): + @runtime_checkable + class Spam[T](Protocol): + x: T + + class Eggs[T]: + def __init__(self, x: T) -> None: + self.x = x + + self.assertIsInstance(Eggs(42), Spam) + + # gh-104555: If we didn't override ABCMeta.__subclasscheck__ in _ProtocolMeta, + # TypeError wouldn't be raised here, + # as the cached result of the isinstance() check immediately above + # would mean the issubclass() call would short-circuit + # before we got to the "raise TypeError" line + with self.assertRaises(TypeError): + issubclass(Eggs, Spam) + def test_protocols_isinstance(self): T = TypeVar('T') @@ -3037,10 +3154,10 @@ class NonP(P): class NonPR(PR): pass - class C: + class C(metaclass=abc.ABCMeta): x = 1 - class D: + class D(metaclass=abc.ABCMeta): def meth(self): pass self.assertNotIsInstance(C(), NonP) @@ -3050,6 +3167,20 @@ def meth(self): pass self.assertIsInstance(NonPR(), PR) self.assertIsSubclass(NonPR, PR) + self.assertNotIn("__protocol_attrs__", vars(NonP)) + self.assertNotIn("__protocol_attrs__", vars(NonPR)) + self.assertNotIn("__callable_proto_members_only__", vars(NonP)) + self.assertNotIn("__callable_proto_members_only__", vars(NonPR)) + + acceptable_extra_attrs = { + '_is_protocol', '_is_runtime_protocol', '__parameters__', + '__init__', '__annotations__', '__subclasshook__', + } + self.assertLessEqual(vars(NonP).keys(), vars(C).keys() | acceptable_extra_attrs) + self.assertLessEqual( + vars(NonPR).keys(), vars(D).keys() | acceptable_extra_attrs + ) + def test_custom_subclasshook(self): class P(Protocol): x = 1 @@ -3134,6 +3265,24 @@ def bar(self, x: str) -> str: self.assertIsInstance(Test(), PSub) + def test_pep695_generic_protocol_callable_members(self): + @runtime_checkable + class Foo[T](Protocol): + def meth(self, x: T) -> None: ... + + class Bar[T]: + def meth(self, x: T) -> None: ... + + self.assertIsInstance(Bar(), Foo) + self.assertIsSubclass(Bar, Foo) + + @runtime_checkable + class SupportsTrunc[T](Protocol): + def __trunc__(self) -> T: ... + + self.assertIsInstance(0.0, SupportsTrunc) + self.assertIsSubclass(float, SupportsTrunc) + def test_init_called(self): T = TypeVar('T') @@ -6444,34 +6593,27 @@ def foo(a: A) -> Optional[BaseException]: class TestModules(TestCase): func_names = ['_idfunc'] - def test_py_functions(self): - for fname in self.func_names: - self.assertEqual(getattr(py_typing, fname).__module__, 'typing') - - @skipUnless(c_typing, 'requires _typing') def test_c_functions(self): for fname in self.func_names: - self.assertEqual(getattr(c_typing, fname).__module__, '_typing') + self.assertEqual(getattr(typing, fname).__module__, '_typing') -class NewTypeTests: +class NewTypeTests(BaseTestCase): def cleanup(self): - for f in self.module._cleanups: + for f in typing._cleanups: f() @classmethod def setUpClass(cls): - sys.modules['typing'] = cls.module global UserId - UserId = cls.module.NewType('UserId', int) - cls.UserName = cls.module.NewType(cls.__qualname__ + '.UserName', str) + UserId = typing.NewType('UserId', int) + cls.UserName = typing.NewType(cls.__qualname__ + '.UserName', str) @classmethod def tearDownClass(cls): global UserId del UserId del cls.UserName - sys.modules['typing'] = typing def tearDown(self): self.cleanup() @@ -6491,11 +6633,11 @@ class D(UserId): def test_or(self): for cls in (int, self.UserName): with self.subTest(cls=cls): - self.assertEqual(UserId | cls, self.module.Union[UserId, cls]) - self.assertEqual(cls | UserId, self.module.Union[cls, UserId]) + self.assertEqual(UserId | cls, typing.Union[UserId, cls]) + self.assertEqual(cls | UserId, typing.Union[cls, UserId]) - self.assertEqual(self.module.get_args(UserId | cls), (UserId, cls)) - self.assertEqual(self.module.get_args(cls | UserId), (cls, UserId)) + self.assertEqual(typing.get_args(UserId | cls), (UserId, cls)) + self.assertEqual(typing.get_args(cls | UserId), (cls, UserId)) def test_special_attrs(self): self.assertEqual(UserId.__name__, 'UserId') @@ -6516,7 +6658,7 @@ def test_repr(self): f'{__name__}.{self.__class__.__qualname__}.UserName') def test_pickle(self): - UserAge = self.module.NewType('UserAge', float) + UserAge = typing.NewType('UserAge', float) for proto in range(pickle.HIGHEST_PROTOCOL + 1): with self.subTest(proto=proto): pickled = pickle.dumps(UserId, proto) @@ -6548,15 +6690,6 @@ class ProUserId(UserId): ... -class NewTypePythonTests(NewTypeTests, BaseTestCase): - module = py_typing - - -@skipUnless(c_typing, 'requires _typing') -class NewTypeCTests(NewTypeTests, BaseTestCase): - module = c_typing - - class NamedTupleTests(BaseTestCase): class NestedEmployee(NamedTuple): name: str @@ -6676,6 +6809,19 @@ class Y(Generic[T], NamedTuple): with self.assertRaises(TypeError): G[int, str] + def test_generic_pep695(self): + class X[T](NamedTuple): + x: T + T, = X.__type_params__ + self.assertIsInstance(T, TypeVar) + self.assertEqual(T.__name__, 'T') + self.assertEqual(X.__bases__, (tuple, Generic)) + self.assertEqual(X.__orig_bases__, (NamedTuple, Generic[T])) + self.assertEqual(X.__mro__, (X, tuple, Generic, object)) + self.assertEqual(X.__parameters__, (T,)) + self.assertEqual(X[str].__args__, (str,)) + self.assertEqual(X[str].__parameters__, ()) + def test_non_generic_subscript(self): # For backward compatibility, subscription works # on arbitrary NamedTuple types. @@ -7086,6 +7232,20 @@ class FooBarGeneric(BarGeneric[int]): {'a': typing.Optional[T], 'b': int, 'c': str} ) + def test_pep695_generic_typeddict(self): + class A[T](TypedDict): + a: T + + T, = A.__type_params__ + self.assertIsInstance(T, TypeVar) + self.assertEqual(T.__name__, 'T') + self.assertEqual(A.__bases__, (Generic, dict)) + self.assertEqual(A.__orig_bases__, (TypedDict, Generic[T])) + self.assertEqual(A.__mro__, (A, Generic, dict, object)) + self.assertEqual(A.__parameters__, (T,)) + self.assertEqual(A[str].__parameters__, ()) + self.assertEqual(A[str].__args__, (str,)) + def test_generic_inheritance(self): class A(TypedDict, Generic[T]): a: T @@ -7369,17 +7529,6 @@ def stuff(a: BinaryIO) -> bytes: a = stuff.__annotations__['a'] self.assertEqual(a.__parameters__, ()) - def test_io_submodule(self): - with warnings.catch_warnings(record=True) as w: - warnings.filterwarnings("default", category=DeprecationWarning) - from typing.io import IO, TextIO, BinaryIO, __all__, __name__ - self.assertIs(IO, typing.IO) - self.assertIs(TextIO, typing.TextIO) - self.assertIs(BinaryIO, typing.BinaryIO) - self.assertEqual(set(__all__), set(['IO', 'TextIO', 'BinaryIO'])) - self.assertEqual(__name__, 'typing.io') - self.assertEqual(len(w), 1) - class RETests(BaseTestCase): # Much of this is really testing _TypeAlias. @@ -7424,16 +7573,6 @@ def test_repr(self): self.assertEqual(repr(Match[str]), 'typing.Match[str]') self.assertEqual(repr(Match[bytes]), 'typing.Match[bytes]') - def test_re_submodule(self): - with warnings.catch_warnings(record=True) as w: - warnings.filterwarnings("default", category=DeprecationWarning) - from typing.re import Match, Pattern, __all__, __name__ - self.assertIs(Match, typing.Match) - self.assertIs(Pattern, typing.Pattern) - self.assertEqual(set(__all__), set(['Match', 'Pattern'])) - self.assertEqual(__name__, 'typing.re') - self.assertEqual(len(w), 1) - def test_cannot_subclass(self): with self.assertRaisesRegex( TypeError, @@ -7810,6 +7949,7 @@ def test_basic_plain(self): P = ParamSpec('P') self.assertEqual(P, P) self.assertIsInstance(P, ParamSpec) + self.assertEqual(P.__name__, 'P') def test_valid_uses(self): P = ParamSpec('P') @@ -8170,11 +8310,11 @@ def test_paramspec_gets_copied(self): self.assertEqual(C2[Concatenate[T, P2]].__parameters__, (T, P2)) def test_cannot_subclass(self): - with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): + with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpec'): class C(ParamSpec): pass - with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): + with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecArgs'): class C(ParamSpecArgs): pass - with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): + with self.assertRaisesRegex(TypeError, NOT_A_BASE_TYPE % 'ParamSpecKwargs'): class C(ParamSpecKwargs): pass P = ParamSpec('P') with self.assertRaisesRegex(TypeError, @@ -8604,7 +8744,7 @@ def test_all(self): # Context managers. self.assertIn('ContextManager', a) self.assertIn('AsyncContextManager', a) - # Check that io and re are not exported. + # Check that former namespaces io and re are not exported. self.assertNotIn('io', a) self.assertNotIn('re', a) # Spot-check that stdlib modules aren't exported. @@ -8624,7 +8764,6 @@ def test_all_exported_names(self): if k in actual_all or ( # avoid private names not k.startswith('_') and - k not in {'io', 're'} and # there's a few types and metaclasses that aren't exported not k.endswith(('Meta', '_contra', '_co')) and not k.upper() == k and diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py index e324babdd5ed0b..625c6dc88796b6 100644 --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -654,6 +654,65 @@ def test_urlsplit_remove_unsafe_bytes(self): self.assertEqual(p.scheme, "http") self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/?query=something#fragment") + def test_urlsplit_strip_url(self): + noise = bytes(range(0, 0x20 + 1)) + base_url = "http://User:Pass@www.python.org:080/doc/?query=yes#frag" + + url = noise.decode("utf-8") + base_url + p = urllib.parse.urlsplit(url) + self.assertEqual(p.scheme, "http") + self.assertEqual(p.netloc, "User:Pass@www.python.org:080") + self.assertEqual(p.path, "/doc/") + self.assertEqual(p.query, "query=yes") + self.assertEqual(p.fragment, "frag") + self.assertEqual(p.username, "User") + self.assertEqual(p.password, "Pass") + self.assertEqual(p.hostname, "www.python.org") + self.assertEqual(p.port, 80) + self.assertEqual(p.geturl(), base_url) + + url = noise + base_url.encode("utf-8") + p = urllib.parse.urlsplit(url) + self.assertEqual(p.scheme, b"http") + self.assertEqual(p.netloc, b"User:Pass@www.python.org:080") + self.assertEqual(p.path, b"/doc/") + self.assertEqual(p.query, b"query=yes") + self.assertEqual(p.fragment, b"frag") + self.assertEqual(p.username, b"User") + self.assertEqual(p.password, b"Pass") + self.assertEqual(p.hostname, b"www.python.org") + self.assertEqual(p.port, 80) + self.assertEqual(p.geturl(), base_url.encode("utf-8")) + + # Test that trailing space is preserved as some applications rely on + # this within query strings. + query_spaces_url = "https://www.python.org:88/doc/?query= " + p = urllib.parse.urlsplit(noise.decode("utf-8") + query_spaces_url) + self.assertEqual(p.scheme, "https") + self.assertEqual(p.netloc, "www.python.org:88") + self.assertEqual(p.path, "/doc/") + self.assertEqual(p.query, "query= ") + self.assertEqual(p.port, 88) + self.assertEqual(p.geturl(), query_spaces_url) + + p = urllib.parse.urlsplit("www.pypi.org ") + # That "hostname" gets considered a "path" due to the + # trailing space and our existing logic... YUCK... + # and re-assembles via geturl aka unurlsplit into the original. + # django.core.validators.URLValidator (at least through v3.2) relies on + # this, for better or worse, to catch it in a ValidationError via its + # regular expressions. + # Here we test the basic round trip concept of such a trailing space. + self.assertEqual(urllib.parse.urlunsplit(p), "www.pypi.org ") + + # with scheme as cache-key + url = "//www.python.org/" + scheme = noise.decode("utf-8") + "https" + noise.decode("utf-8") + for _ in range(2): + p = urllib.parse.urlsplit(url, scheme=scheme) + self.assertEqual(p.scheme, "https") + self.assertEqual(p.geturl(), "https://www.python.org/") + def test_attributes_bad_port(self): """Check handling of invalid ports.""" for bytes in (False, True): @@ -661,7 +720,7 @@ def test_attributes_bad_port(self): for port in ("foo", "1.5", "-1", "0x10", "-0", "1_1", " 1", "1 ", "६"): with self.subTest(bytes=bytes, parse=parse, port=port): netloc = "www.example.net:" + port - url = "http://" + netloc + url = "http://" + netloc + "/" if bytes: if netloc.isascii() and port.isascii(): netloc = netloc.encode("ascii") diff --git a/Lib/test/test_userstring.py b/Lib/test/test_userstring.py index 51b4f6041e49bf..74df52f5412af0 100644 --- a/Lib/test/test_userstring.py +++ b/Lib/test/test_userstring.py @@ -7,8 +7,7 @@ from collections import UserString class UserStringTest( - string_tests.CommonTest, - string_tests.MixinStrUnicodeUserStringTest, + string_tests.StringLikeTest, unittest.TestCase ): diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index 73c6b0185a1a0e..9960259c4cde0c 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -1080,6 +1080,159 @@ def test_generated_valid_zip64_extra(self): self.assertEqual(zinfo.header_offset, expected_header_offset) self.assertEqual(zf.read(zinfo), expected_content) + def test_force_zip64(self): + """Test that forcing zip64 extensions correctly notes this in the zip file""" + + # GH-103861 describes an issue where forcing a small file to use zip64 + # extensions would add a zip64 extra record, but not change the data + # sizes to 0xFFFFFFFF to indicate to the extractor that the zip64 + # record should be read. Additionally, it would not set the required + # version to indicate that zip64 extensions are required to extract it. + # This test replicates the situation and reads the raw data to specifically ensure: + # - The required extract version is always >= ZIP64_VERSION + # - The compressed and uncompressed size in the file headers are both + # 0xFFFFFFFF (ie. point to zip64 record) + # - The zip64 record is provided and has the correct sizes in it + # Other aspects of the zip are checked as well, but verifying the above is the main goal. + # Because this is hard to verify by parsing the data as a zip, the raw + # bytes are checked to ensure that they line up with the zip spec. + # The spec for this can be found at: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT + # The relevent sections for this test are: + # - 4.3.7 for local file header + # - 4.5.3 for zip64 extra field + + data = io.BytesIO() + with zipfile.ZipFile(data, mode="w", allowZip64=True) as zf: + with zf.open("text.txt", mode="w", force_zip64=True) as zi: + zi.write(b"_") + + zipdata = data.getvalue() + + # pull out and check zip information + ( + header, vers, os, flags, comp, csize, usize, fn_len, + ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, cd_sig + ) = struct.unpack("<4sBBHH8xIIHH8shhQQx4s", zipdata[:63]) + + self.assertEqual(header, b"PK\x03\x04") # local file header + self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract + self.assertEqual(os, 0) # compatible with MS-DOS + self.assertEqual(flags, 0) # no flags + self.assertEqual(comp, 0) # compression method = stored + self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra + self.assertEqual(usize, 0xFFFFFFFF) + self.assertEqual(fn_len, 8) # filename len + self.assertEqual(ex_total_len, 20) # size of extra records + self.assertEqual(ex_id, 1) # Zip64 extra record + self.assertEqual(ex_len, 16) # 16 bytes of data + self.assertEqual(ex_usize, 1) # uncompressed size + self.assertEqual(ex_csize, 1) # compressed size + self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next + + z = zipfile.ZipFile(io.BytesIO(zipdata)) + zinfos = z.infolist() + self.assertEqual(len(zinfos), 1) + self.assertGreaterEqual(zinfos[0].extract_version, zipfile.ZIP64_VERSION) # requires zip64 to extract + + def test_unseekable_zip_unknown_filesize(self): + """Test that creating a zip with/without seeking will raise a RuntimeError if zip64 was required but not used""" + + def make_zip(fp): + with zipfile.ZipFile(fp, mode="w", allowZip64=True) as zf: + with zf.open("text.txt", mode="w", force_zip64=False) as zi: + zi.write(b"_" * (zipfile.ZIP64_LIMIT + 1)) + + self.assertRaises(RuntimeError, make_zip, io.BytesIO()) + self.assertRaises(RuntimeError, make_zip, Unseekable(io.BytesIO())) + + def test_zip64_required_not_allowed_fail(self): + """Test that trying to add a large file to a zip that doesn't allow zip64 extensions fails on add""" + def make_zip(fp): + with zipfile.ZipFile(fp, mode="w", allowZip64=False) as zf: + # pretend zipfile.ZipInfo.from_file was used to get the name and filesize + info = zipfile.ZipInfo("text.txt") + info.file_size = zipfile.ZIP64_LIMIT + 1 + zf.open(info, mode="w") + + self.assertRaises(zipfile.LargeZipFile, make_zip, io.BytesIO()) + self.assertRaises(zipfile.LargeZipFile, make_zip, Unseekable(io.BytesIO())) + + def test_unseekable_zip_known_filesize(self): + """Test that creating a zip without seeking will use zip64 extensions if the file size is provided up-front""" + + # This test ensures that the zip will use a zip64 data descriptor (same + # as a regular data descriptor except the sizes are 8 bytes instead of + # 4) record to communicate the size of a file if the zip is being + # written to an unseekable stream. + # Because this sort of thing is hard to verify by parsing the data back + # in as a zip, this test looks at the raw bytes created to ensure that + # the correct data has been generated. + # The spec for this can be found at: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT + # The relevent sections for this test are: + # - 4.3.7 for local file header + # - 4.3.9 for the data descriptor + # - 4.5.3 for zip64 extra field + + file_size = zipfile.ZIP64_LIMIT + 1 + + def make_zip(fp): + with zipfile.ZipFile(fp, mode="w", allowZip64=True) as zf: + # pretend zipfile.ZipInfo.from_file was used to get the name and filesize + info = zipfile.ZipInfo("text.txt") + info.file_size = file_size + with zf.open(info, mode="w", force_zip64=False) as zi: + zi.write(b"_" * file_size) + return fp + + # check seekable file information + seekable_data = make_zip(io.BytesIO()).getvalue() + ( + header, vers, os, flags, comp, csize, usize, fn_len, + ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, + cd_sig + ) = struct.unpack("<4sBBHH8xIIHH8shhQQ{}x4s".format(file_size), seekable_data[:62 + file_size]) + + self.assertEqual(header, b"PK\x03\x04") # local file header + self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract + self.assertEqual(os, 0) # compatible with MS-DOS + self.assertEqual(flags, 0) # no flags set + self.assertEqual(comp, 0) # compression method = stored + self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra + self.assertEqual(usize, 0xFFFFFFFF) + self.assertEqual(fn_len, 8) # filename len + self.assertEqual(ex_total_len, 20) # size of extra records + self.assertEqual(ex_id, 1) # Zip64 extra record + self.assertEqual(ex_len, 16) # 16 bytes of data + self.assertEqual(ex_usize, file_size) # uncompressed size + self.assertEqual(ex_csize, file_size) # compressed size + self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next + + # check unseekable file information + unseekable_data = make_zip(Unseekable(io.BytesIO())).fp.getvalue() + ( + header, vers, os, flags, comp, csize, usize, fn_len, + ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, + dd_header, dd_usize, dd_csize, cd_sig + ) = struct.unpack("<4sBBHH8xIIHH8shhQQ{}x4s4xQQ4s".format(file_size), unseekable_data[:86 + file_size]) + + self.assertEqual(header, b"PK\x03\x04") # local file header + self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract + self.assertEqual(os, 0) # compatible with MS-DOS + self.assertEqual("{:b}".format(flags), "1000") # streaming flag set + self.assertEqual(comp, 0) # compression method = stored + self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra + self.assertEqual(usize, 0xFFFFFFFF) + self.assertEqual(fn_len, 8) # filename len + self.assertEqual(ex_total_len, 20) # size of extra records + self.assertEqual(ex_id, 1) # Zip64 extra record + self.assertEqual(ex_len, 16) # 16 bytes of data + self.assertEqual(ex_usize, 0) # uncompressed size - 0 to defer to data descriptor + self.assertEqual(ex_csize, 0) # compressed size - 0 to defer to data descriptor + self.assertEqual(dd_header, b"PK\07\x08") # data descriptor + self.assertEqual(dd_usize, file_size) # file size (8 bytes because zip64) + self.assertEqual(dd_csize, file_size) # compressed size (8 bytes because zip64) + self.assertEqual(cd_sig, b"PK\x01\x02") # ensure the central directory header is next + @requires_zlib() class DeflateTestZip64InSmallFiles(AbstractTestZip64InSmallFiles, diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index bf0b3b92155938..c675c511e04533 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -2817,7 +2817,7 @@ def canvasy(self, screeny, gridspacing=None): def coords(self, *args): """Return a list of coordinates for the item given in ARGS.""" - # XXX Should use _flatten on args + args = _flatten(args) return [self.tk.getdouble(x) for x in self.tk.splitlist( self.tk.call((self._w, 'coords') + args))] diff --git a/Lib/token.py b/Lib/token.py index 1459d12b376f82..487f6edd3c951c 100644 --- a/Lib/token.py +++ b/Lib/token.py @@ -67,10 +67,10 @@ FSTRING_START = 61 FSTRING_MIDDLE = 62 FSTRING_END = 63 +COMMENT = 64 +NL = 65 # These aren't used by the C tokenizer but are needed for tokenize.py -ERRORTOKEN = 64 -COMMENT = 65 -NL = 66 +ERRORTOKEN = 66 ENCODING = 67 N_TOKENS = 68 # Special definitions for cooperation with parser diff --git a/Lib/tokenize.py b/Lib/tokenize.py index 46d2224f5cc083..911f0f12f9bb7e 100644 --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -160,8 +160,8 @@ def _compile(expr): class TokenError(Exception): pass -class StopTokenizing(Exception): pass +class StopTokenizing(Exception): pass class Untokenizer: @@ -213,6 +213,14 @@ def untokenize(self, iterable): self.tokens.append(indent) self.prev_col = len(indent) startline = False + elif tok_type == FSTRING_MIDDLE: + if '{' in token or '}' in token: + end_line, end_col = end + end = (end_line, end_col + token.count('{') + token.count('}')) + token = re.sub('{', '{{', token) + token = re.sub('}', '}}', token) + + self.add_whitespace(start) self.tokens.append(token) self.prev_row, self.prev_col = end @@ -255,6 +263,11 @@ def compat(self, token, iterable): elif startline and indents: toks_append(indents[-1]) startline = False + elif toknum == FSTRING_MIDDLE: + if '{' in tokval or '}' in tokval: + tokval = re.sub('{', '{{', tokval) + tokval = re.sub('}', '}}', tokval) + toks_append(tokval) @@ -404,7 +417,6 @@ def open(filename): buffer.close() raise - def tokenize(readline): """ The tokenize() generator requires one argument, readline, which @@ -425,192 +437,22 @@ def tokenize(readline): which tells you which encoding was used to decode the bytes stream. """ encoding, consumed = detect_encoding(readline) - empty = _itertools.repeat(b"") - rl_gen = _itertools.chain(consumed, iter(readline, b""), empty) - return _tokenize(rl_gen.__next__, encoding) - - -def _tokenize(readline, encoding): - lnum = parenlev = continued = 0 - numchars = '0123456789' - contstr, needcont = '', 0 - contline = None - indents = [0] - + rl_gen = _itertools.chain(consumed, iter(readline, b"")) if encoding is not None: if encoding == "utf-8-sig": # BOM will already have been stripped. encoding = "utf-8" yield TokenInfo(ENCODING, encoding, (0, 0), (0, 0), '') - last_line = b'' - line = b'' - while True: # loop over lines in stream - try: - # We capture the value of the line variable here because - # readline uses the empty string '' to signal end of input, - # hence `line` itself will always be overwritten at the end - # of this loop. - last_line = line - line = readline() - except StopIteration: - line = b'' + yield from _tokenize(rl_gen, encoding) - if encoding is not None: - line = line.decode(encoding) - lnum += 1 - pos, max = 0, len(line) - - if contstr: # continued string - if not line: - raise TokenError("EOF in multi-line string", strstart) - endmatch = endprog.match(line) - if endmatch: - pos = end = endmatch.end(0) - yield TokenInfo(STRING, contstr + line[:end], - strstart, (lnum, end), contline + line) - contstr, needcont = '', 0 - contline = None - elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': - yield TokenInfo(ERRORTOKEN, contstr + line, - strstart, (lnum, len(line)), contline) - contstr = '' - contline = None - continue - else: - contstr = contstr + line - contline = contline + line - continue - - elif parenlev == 0 and not continued: # new statement - if not line: break - column = 0 - while pos < max: # measure leading whitespace - if line[pos] == ' ': - column += 1 - elif line[pos] == '\t': - column = (column//tabsize + 1)*tabsize - elif line[pos] == '\f': - column = 0 - else: - break - pos += 1 - if pos == max: - break - - if line[pos] in '#\r\n': # skip comments or blank lines - if line[pos] == '#': - comment_token = line[pos:].rstrip('\r\n') - yield TokenInfo(COMMENT, comment_token, - (lnum, pos), (lnum, pos + len(comment_token)), line) - pos += len(comment_token) - - yield TokenInfo(NL, line[pos:], - (lnum, pos), (lnum, len(line)), line) - continue - - if column > indents[-1]: # count indents or dedents - indents.append(column) - yield TokenInfo(INDENT, line[:pos], (lnum, 0), (lnum, pos), line) - while column < indents[-1]: - if column not in indents: - raise IndentationError( - "unindent does not match any outer indentation level", - ("", lnum, pos, line)) - indents = indents[:-1] - - yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) - - else: # continued statement - if not line: - raise TokenError("EOF in multi-line statement", (lnum, 0)) - continued = 0 - - while pos < max: - pseudomatch = _compile(PseudoToken).match(line, pos) - if pseudomatch: # scan for tokens - start, end = pseudomatch.span(1) - spos, epos, pos = (lnum, start), (lnum, end), end - if start == end: - continue - token, initial = line[start:end], line[start] - - if (initial in numchars or # ordinary number - (initial == '.' and token != '.' and token != '...')): - yield TokenInfo(NUMBER, token, spos, epos, line) - elif initial in '\r\n': - if parenlev > 0: - yield TokenInfo(NL, token, spos, epos, line) - else: - yield TokenInfo(NEWLINE, token, spos, epos, line) - - elif initial == '#': - assert not token.endswith("\n") - yield TokenInfo(COMMENT, token, spos, epos, line) - - elif token in triple_quoted: - endprog = _compile(endpats[token]) - endmatch = endprog.match(line, pos) - if endmatch: # all on one line - pos = endmatch.end(0) - token = line[start:pos] - yield TokenInfo(STRING, token, spos, (lnum, pos), line) - else: - strstart = (lnum, start) # multiple lines - contstr = line[start:] - contline = line - break - - # Check up to the first 3 chars of the token to see if - # they're in the single_quoted set. If so, they start - # a string. - # We're using the first 3, because we're looking for - # "rb'" (for example) at the start of the token. If - # we switch to longer prefixes, this needs to be - # adjusted. - # Note that initial == token[:1]. - # Also note that single quote checking must come after - # triple quote checking (above). - elif (initial in single_quoted or - token[:2] in single_quoted or - token[:3] in single_quoted): - if token[-1] == '\n': # continued string - strstart = (lnum, start) - # Again, using the first 3 chars of the - # token. This is looking for the matching end - # regex for the correct type of quote - # character. So it's really looking for - # endpats["'"] or endpats['"'], by trying to - # skip string prefix characters, if any. - endprog = _compile(endpats.get(initial) or - endpats.get(token[1]) or - endpats.get(token[2])) - contstr, needcont = line[start:], 1 - contline = line - break - else: # ordinary string - yield TokenInfo(STRING, token, spos, epos, line) - - elif initial.isidentifier(): # ordinary name - yield TokenInfo(NAME, token, spos, epos, line) - elif initial == '\\': # continued stmt - continued = 1 - else: - if initial in '([{': - parenlev += 1 - elif initial in ')]}': - parenlev -= 1 - yield TokenInfo(OP, token, spos, epos, line) - else: - yield TokenInfo(ERRORTOKEN, line[pos], - (lnum, pos), (lnum, pos+1), line) - pos += 1 - - # Add an implicit NEWLINE if the input doesn't end in one - if last_line and last_line[-1] not in '\r\n' and not last_line.strip().startswith("#"): - yield TokenInfo(NEWLINE, '', (lnum - 1, len(last_line)), (lnum - 1, len(last_line) + 1), '') - for indent in indents[1:]: # pop remaining indent levels - yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '') - yield TokenInfo(ENDMARKER, '', (lnum, 0), (lnum, 0), '') +def _tokenize(rl_gen, encoding): + source = b"".join(rl_gen).decode(encoding) + token = None + for token in _generate_tokens_from_c_tokenizer(source, extra_tokens=True): + yield token + if token is not None: + last_line, _ = token.start + yield TokenInfo(ENDMARKER, '', (last_line + 1, 0), (last_line + 1, 0), '') def generate_tokens(readline): @@ -619,7 +461,16 @@ def generate_tokens(readline): This has the same API as tokenize(), except that it expects the *readline* callable to return str objects instead of bytes. """ - return _tokenize(readline, None) + def _gen(): + while True: + try: + line = readline() + except StopIteration: + return + if not line: + return + yield line.encode() + return _tokenize(_gen(), 'utf-8') def main(): import argparse @@ -656,7 +507,10 @@ def error(message, filename=None, location=None): tokens = list(tokenize(f.readline)) else: filename = "" - tokens = _tokenize(sys.stdin.readline, None) + tokens = _tokenize( + (x.encode('utf-8') for x in iter(sys.stdin.readline, "") + ), "utf-8") + # Output the tokenization for token in tokens: @@ -682,12 +536,11 @@ def error(message, filename=None, location=None): perror("unexpected error: %s" % err) raise -def _generate_tokens_from_c_tokenizer(source): +def _generate_tokens_from_c_tokenizer(source, extra_tokens=False): """Tokenize a source reading Python code as unicode strings using the internal C tokenizer""" import _tokenize as c_tokenizer - for info in c_tokenizer.TokenizerIter(source): - tok, type, lineno, end_lineno, col_off, end_col_off, line = info - yield TokenInfo(type, tok, (lineno, col_off), (end_lineno, end_col_off), line) + for info in c_tokenizer.TokenizerIter(source, extra_tokens=extra_tokens): + yield TokenInfo._make(info) if __name__ == "__main__": diff --git a/Lib/tty.py b/Lib/tty.py index a72eb6755450bb..7d916029ff2ce9 100644 --- a/Lib/tty.py +++ b/Lib/tty.py @@ -4,9 +4,9 @@ from termios import * -__all__ = ["setraw", "setcbreak"] +__all__ = ["cfmakeraw", "cfmakecbreak", "setraw", "setcbreak"] -# Indexes for termios list. +# Indices for termios list. IFLAG = 0 OFLAG = 1 CFLAG = 2 @@ -15,22 +15,60 @@ OSPEED = 5 CC = 6 -def setraw(fd, when=TCSAFLUSH): - """Put terminal into a raw mode.""" - mode = tcgetattr(fd) - mode[IFLAG] = mode[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON) - mode[OFLAG] = mode[OFLAG] & ~(OPOST) - mode[CFLAG] = mode[CFLAG] & ~(CSIZE | PARENB) - mode[CFLAG] = mode[CFLAG] | CS8 - mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG) +def cfmakeraw(mode): + """Make termios mode raw.""" + # Clear all POSIX.1-2017 input mode flags. + # See chapter 11 "General Terminal Interface" + # of POSIX.1-2017 Base Definitions. + mode[IFLAG] &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | + INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF) + + # Do not post-process output. + mode[OFLAG] &= ~OPOST + + # Disable parity generation and detection; clear character size mask; + # let character size be 8 bits. + mode[CFLAG] &= ~(PARENB | CSIZE) + mode[CFLAG] |= CS8 + + # Clear all POSIX.1-2017 local mode flags. + mode[LFLAG] &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | + IEXTEN | ISIG | NOFLSH | TOSTOP) + + # POSIX.1-2017, 11.1.7 Non-Canonical Mode Input Processing, + # Case B: MIN>0, TIME=0 + # A pending read shall block until MIN (here 1) bytes are received, + # or a signal is received. mode[CC][VMIN] = 1 mode[CC][VTIME] = 0 - tcsetattr(fd, when, mode) -def setcbreak(fd, when=TCSAFLUSH): - """Put terminal into a cbreak mode.""" - mode = tcgetattr(fd) - mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON) +def cfmakecbreak(mode): + """Make termios mode cbreak.""" + # Do not map CR to NL on input. + mode[IFLAG] &= ~(ICRNL) + + # Do not echo characters; disable canonical input. + mode[LFLAG] &= ~(ECHO | ICANON) + + # POSIX.1-2017, 11.1.7 Non-Canonical Mode Input Processing, + # Case B: MIN>0, TIME=0 + # A pending read shall block until MIN (here 1) bytes are received, + # or a signal is received. mode[CC][VMIN] = 1 mode[CC][VTIME] = 0 - tcsetattr(fd, when, mode) + +def setraw(fd, when=TCSAFLUSH): + """Put terminal into raw mode.""" + mode = tcgetattr(fd) + new = list(mode) + cfmakeraw(new) + tcsetattr(fd, when, new) + return mode + +def setcbreak(fd, when=TCSAFLUSH): + """Put terminal into cbreak mode.""" + mode = tcgetattr(fd) + new = list(mode) + cfmakecbreak(new) + tcsetattr(fd, when, new) + return mode diff --git a/Lib/typing.py b/Lib/typing.py index 61aed0980ac2eb..95dbc0b85bcddf 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -16,28 +16,32 @@ no_type_check_decorator. * Generic aliases for collections.abc ABCs and few additional protocols. * Special types: NewType, NamedTuple, TypedDict. -* Wrapper submodules for re and io related types. """ from abc import abstractmethod, ABCMeta import collections from collections import defaultdict import collections.abc +import copyreg import contextlib import functools import operator -import re as stdlib_re # Avoid confusion with the re we export. +import re as stdlib_re # Avoid confusion with the typing.re namespace on <=3.11 import sys import types import warnings from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType, GenericAlias - -try: - from _typing import _idfunc -except ImportError: - def _idfunc(_, x): - return x +from _typing import ( + _idfunc, + TypeVar, + ParamSpec, + TypeVarTuple, + ParamSpecArgs, + ParamSpecKwargs, + TypeAliasType, + Generic, +) # Please keep __all__ alphabetized within each category. __all__ = [ @@ -149,13 +153,10 @@ def _idfunc(_, x): 'TYPE_CHECKING', 'TypeAlias', 'TypeGuard', + 'TypeAliasType', 'Unpack', ] -# The pseudo-submodules 're' and 'io' are part of the public -# namespace, but excluded from __all__ because they might stomp on -# legitimate imports of those modules. - def _type_convert(arg, module=None, *, allow_special_forms=False): """For converting None to type(None), and strings to ForwardRef.""" @@ -695,6 +696,15 @@ def Union(self, parameters): return _UnionGenericAlias(self, parameters, name="Optional") return _UnionGenericAlias(self, parameters) +def _make_union(left, right): + """Used from the C implementation of TypeVar. + + TypeVar.__or__ calls this instead of returning types.UnionType + because we want to allow unions between TypeVars and strings + (forward references.) + """ + return Union[left, right] + @_SpecialForm def Optional(self, parameters): """Optional type. @@ -926,333 +936,162 @@ def __reduce__(self): return self.__name__ -class _BoundVarianceMixin: - """Mixin giving __init__ bound and variance arguments. - - This is used by TypeVar and ParamSpec, which both employ the notions of - a type 'bound' (restricting type arguments to be a subtype of some - specified type) and type 'variance' (determining subtype relations between - generic types). - """ - def __init__(self, bound, covariant, contravariant): - """Used to setup TypeVars and ParamSpec's bound, covariant and - contravariant attributes. - """ - if covariant and contravariant: - raise ValueError("Bivariant types are not supported.") - self.__covariant__ = bool(covariant) - self.__contravariant__ = bool(contravariant) - if bound: - self.__bound__ = _type_check(bound, "Bound must be a type.") - else: - self.__bound__ = None - - def __or__(self, right): - return Union[self, right] - - def __ror__(self, left): - return Union[left, self] - - def __repr__(self): - if self.__covariant__: - prefix = '+' - elif self.__contravariant__: - prefix = '-' - else: - prefix = '~' - return prefix + self.__name__ - - def __mro_entries__(self, bases): - raise TypeError(f"Cannot subclass an instance of {type(self).__name__}") - - -class TypeVar(_Final, _Immutable, _BoundVarianceMixin, _PickleUsingNameMixin, - _root=True): - """Type variable. - - Usage:: - - T = TypeVar('T') # Can be anything - A = TypeVar('A', str, bytes) # Must be str or bytes - - Type variables exist primarily for the benefit of static type - checkers. They serve as the parameters for generic types as well - as for generic function definitions. See class Generic for more - information on generic types. Generic functions work as follows: - - def repeat(x: T, n: int) -> List[T]: - '''Return a list containing n references to x.''' - return [x]*n - - def longest(x: A, y: A) -> A: - '''Return the longest of two strings.''' - return x if len(x) >= len(y) else y - - The latter example's signature is essentially the overloading - of (str, str) -> str and (bytes, bytes) -> bytes. Also note - that if the arguments are instances of some subclass of str, - the return type is still plain str. - - At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError. - - Type variables defined with covariant=True or contravariant=True - can be used to declare covariant or contravariant generic types. - See PEP 484 for more details. By default generic types are invariant - in all type variables. - - Type variables can be introspected. e.g.: - - T.__name__ == 'T' - T.__constraints__ == () - T.__covariant__ == False - T.__contravariant__ = False - A.__constraints__ == (str, bytes) - - Note that only type variables defined in global scope can be pickled. - """ +def _typevar_subst(self, arg): + msg = "Parameters to generic types must be types." + arg = _type_check(arg, msg, is_argument=True) + if ((isinstance(arg, _GenericAlias) and arg.__origin__ is Unpack) or + (isinstance(arg, GenericAlias) and getattr(arg, '__unpacked__', False))): + raise TypeError(f"{arg} is not valid as type argument") + return arg - def __init__(self, name, *constraints, bound=None, - covariant=False, contravariant=False): - self.__name__ = name - super().__init__(bound, covariant, contravariant) - if constraints and bound is not None: - raise TypeError("Constraints cannot be combined with bound=...") - if constraints and len(constraints) == 1: - raise TypeError("A single constraint is not allowed") - msg = "TypeVar(name, constraint, ...): constraints must be types." - self.__constraints__ = tuple(_type_check(t, msg) for t in constraints) - def_mod = _caller() - if def_mod != 'typing': - self.__module__ = def_mod - def __typing_subst__(self, arg): - msg = "Parameters to generic types must be types." - arg = _type_check(arg, msg, is_argument=True) - if ((isinstance(arg, _GenericAlias) and arg.__origin__ is Unpack) or - (isinstance(arg, GenericAlias) and getattr(arg, '__unpacked__', False))): - raise TypeError(f"{arg} is not valid as type argument") - return arg +def _typevartuple_prepare_subst(self, alias, args): + params = alias.__parameters__ + typevartuple_index = params.index(self) + for param in params[typevartuple_index + 1:]: + if isinstance(param, TypeVarTuple): + raise TypeError(f"More than one TypeVarTuple parameter in {alias}") + + alen = len(args) + plen = len(params) + left = typevartuple_index + right = plen - typevartuple_index - 1 + var_tuple_index = None + fillarg = None + for k, arg in enumerate(args): + if not isinstance(arg, type): + subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) + if subargs and len(subargs) == 2 and subargs[-1] is ...: + if var_tuple_index is not None: + raise TypeError("More than one unpacked arbitrary-length tuple argument") + var_tuple_index = k + fillarg = subargs[0] + if var_tuple_index is not None: + left = min(left, var_tuple_index) + right = min(right, alen - var_tuple_index - 1) + elif left + right > alen: + raise TypeError(f"Too few arguments for {alias};" + f" actual {alen}, expected at least {plen-1}") + return ( + *args[:left], + *([fillarg]*(typevartuple_index - left)), + tuple(args[left: alen - right]), + *([fillarg]*(plen - right - left - typevartuple_index - 1)), + *args[alen - right:], + ) -class TypeVarTuple(_Final, _Immutable, _PickleUsingNameMixin, _root=True): - """Type variable tuple. - Usage: - - Ts = TypeVarTuple('Ts') # Can be given any name +def _paramspec_subst(self, arg): + if isinstance(arg, (list, tuple)): + arg = tuple(_type_check(a, "Expected a type.") for a in arg) + elif not _is_param_expr(arg): + raise TypeError(f"Expected a list of types, an ellipsis, " + f"ParamSpec, or Concatenate. Got {arg}") + return arg - Just as a TypeVar (type variable) is a placeholder for a single type, - a TypeVarTuple is a placeholder for an *arbitrary* number of types. For - example, if we define a generic class using a TypeVarTuple: - class C(Generic[*Ts]): ... +def _paramspec_prepare_subst(self, alias, args): + params = alias.__parameters__ + i = params.index(self) + if i >= len(args): + raise TypeError(f"Too few arguments for {alias}") + # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612. + if len(params) == 1 and not _is_param_expr(args[0]): + assert i == 0 + args = (args,) + # Convert lists to tuples to help other libraries cache the results. + elif isinstance(args[i], list): + args = (*args[:i], tuple(args[i]), *args[i+1:]) + return args - Then we can parameterize that class with an arbitrary number of type - arguments: - C[int] # Fine - C[int, str] # Also fine - C[()] # Even this is fine +@_tp_cache +def _generic_class_getitem(cls, params): + """Parameterizes a generic class. - For more details, see PEP 646. + At least, parameterizing a generic class is the *main* thing this method + does. For example, for some generic class `Foo`, this is called when we + do `Foo[int]` - there, with `cls=Foo` and `params=int`. - Note that only TypeVarTuples defined in global scope can be pickled. + However, note that this method is also called when defining generic + classes in the first place with `class Foo(Generic[T]): ...`. """ + if not isinstance(params, tuple): + params = (params,) - def __init__(self, name): - self.__name__ = name - - # Used for pickling. - def_mod = _caller() - if def_mod != 'typing': - self.__module__ = def_mod - - def __iter__(self): - yield Unpack[self] + params = tuple(_type_convert(p) for p in params) + is_generic_or_protocol = cls in (Generic, Protocol) - def __repr__(self): - return self.__name__ - - def __typing_subst__(self, arg): - raise TypeError("Substitution of bare TypeVarTuple is not supported") + if is_generic_or_protocol: + # Generic and Protocol can only be subscripted with unique type variables. + if not params: + raise TypeError( + f"Parameter list to {cls.__qualname__}[...] cannot be empty" + ) + if not all(_is_typevar_like(p) for p in params): + raise TypeError( + f"Parameters to {cls.__name__}[...] must all be type variables " + f"or parameter specification variables.") + if len(set(params)) != len(params): + raise TypeError( + f"Parameters to {cls.__name__}[...] must all be unique") + else: + # Subscripting a regular Generic subclass. + for param in cls.__parameters__: + prepare = getattr(param, '__typing_prepare_subst__', None) + if prepare is not None: + params = prepare(cls, params) + _check_generic(cls, params, len(cls.__parameters__)) - def __typing_prepare_subst__(self, alias, args): - params = alias.__parameters__ - typevartuple_index = params.index(self) - for param in params[typevartuple_index + 1:]: + new_args = [] + for param, new_arg in zip(cls.__parameters__, params): if isinstance(param, TypeVarTuple): - raise TypeError(f"More than one TypeVarTuple parameter in {alias}") - - alen = len(args) - plen = len(params) - left = typevartuple_index - right = plen - typevartuple_index - 1 - var_tuple_index = None - fillarg = None - for k, arg in enumerate(args): - if not isinstance(arg, type): - subargs = getattr(arg, '__typing_unpacked_tuple_args__', None) - if subargs and len(subargs) == 2 and subargs[-1] is ...: - if var_tuple_index is not None: - raise TypeError("More than one unpacked arbitrary-length tuple argument") - var_tuple_index = k - fillarg = subargs[0] - if var_tuple_index is not None: - left = min(left, var_tuple_index) - right = min(right, alen - var_tuple_index - 1) - elif left + right > alen: - raise TypeError(f"Too few arguments for {alias};" - f" actual {alen}, expected at least {plen-1}") - - return ( - *args[:left], - *([fillarg]*(typevartuple_index - left)), - tuple(args[left: alen - right]), - *([fillarg]*(plen - right - left - typevartuple_index - 1)), - *args[alen - right:], - ) - - def __mro_entries__(self, bases): - raise TypeError(f"Cannot subclass an instance of {type(self).__name__}") - - -class ParamSpecArgs(_Final, _Immutable, _root=True): - """The args for a ParamSpec object. - - Given a ParamSpec object P, P.args is an instance of ParamSpecArgs. - - ParamSpecArgs objects have a reference back to their ParamSpec: - - P.args.__origin__ is P - - This type is meant for runtime introspection and has no special meaning to - static type checkers. - """ - def __init__(self, origin): - self.__origin__ = origin - - def __repr__(self): - return f"{self.__origin__.__name__}.args" - - def __eq__(self, other): - if not isinstance(other, ParamSpecArgs): - return NotImplemented - return self.__origin__ == other.__origin__ - - def __mro_entries__(self, bases): - raise TypeError(f"Cannot subclass an instance of {type(self).__name__}") - - -class ParamSpecKwargs(_Final, _Immutable, _root=True): - """The kwargs for a ParamSpec object. - - Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs. - - ParamSpecKwargs objects have a reference back to their ParamSpec: - - P.kwargs.__origin__ is P - - This type is meant for runtime introspection and has no special meaning to - static type checkers. - """ - def __init__(self, origin): - self.__origin__ = origin - - def __repr__(self): - return f"{self.__origin__.__name__}.kwargs" - - def __eq__(self, other): - if not isinstance(other, ParamSpecKwargs): - return NotImplemented - return self.__origin__ == other.__origin__ - - def __mro_entries__(self, bases): - raise TypeError(f"Cannot subclass an instance of {type(self).__name__}") - - -class ParamSpec(_Final, _Immutable, _BoundVarianceMixin, _PickleUsingNameMixin, - _root=True): - """Parameter specification variable. - - Usage:: - - P = ParamSpec('P') - - Parameter specification variables exist primarily for the benefit of static - type checkers. They are used to forward the parameter types of one - callable to another callable, a pattern commonly found in higher order - functions and decorators. They are only valid when used in ``Concatenate``, - or as the first argument to ``Callable``, or as parameters for user-defined - Generics. See class Generic for more information on generic types. An - example for annotating a decorator:: - - T = TypeVar('T') - P = ParamSpec('P') - - def add_logging(f: Callable[P, T]) -> Callable[P, T]: - '''A type-safe decorator to add logging to a function.''' - def inner(*args: P.args, **kwargs: P.kwargs) -> T: - logging.info(f'{f.__name__} was called') - return f(*args, **kwargs) - return inner - - @add_logging - def add_two(x: float, y: float) -> float: - '''Add two numbers together.''' - return x + y - - Parameter specification variables defined with covariant=True or - contravariant=True can be used to declare covariant or contravariant - generic types. These keyword arguments are valid, but their actual semantics - are yet to be decided. See PEP 612 for details. - - Parameter specification variables can be introspected. e.g.: - - P.__name__ == 'P' - P.__bound__ == None - P.__covariant__ == False - P.__contravariant__ == False - - Note that only parameter specification variables defined in global scope can - be pickled. - """ - - @property - def args(self): - return ParamSpecArgs(self) + new_args.extend(new_arg) + else: + new_args.append(new_arg) + params = tuple(new_args) - @property - def kwargs(self): - return ParamSpecKwargs(self) + return _GenericAlias(cls, params) - def __init__(self, name, *, bound=None, covariant=False, contravariant=False): - self.__name__ = name - super().__init__(bound, covariant, contravariant) - def_mod = _caller() - if def_mod != 'typing': - self.__module__ = def_mod - def __typing_subst__(self, arg): - if isinstance(arg, (list, tuple)): - arg = tuple(_type_check(a, "Expected a type.") for a in arg) - elif not _is_param_expr(arg): - raise TypeError(f"Expected a list of types, an ellipsis, " - f"ParamSpec, or Concatenate. Got {arg}") - return arg +def _generic_init_subclass(cls, *args, **kwargs): + super(Generic, cls).__init_subclass__(*args, **kwargs) + tvars = [] + if '__orig_bases__' in cls.__dict__: + error = Generic in cls.__orig_bases__ + else: + error = (Generic in cls.__bases__ and + cls.__name__ != 'Protocol' and + type(cls) != _TypedDictMeta) + if error: + raise TypeError("Cannot inherit from plain Generic") + if '__orig_bases__' in cls.__dict__: + tvars = _collect_parameters(cls.__orig_bases__) + # Look for Generic[T1, ..., Tn]. + # If found, tvars must be a subset of it. + # If not found, tvars is it. + # Also check for and reject plain Generic, + # and reject multiple Generic[...]. + gvars = None + for base in cls.__orig_bases__: + if (isinstance(base, _GenericAlias) and + base.__origin__ is Generic): + if gvars is not None: + raise TypeError( + "Cannot inherit from Generic[...] multiple times.") + gvars = base.__parameters__ + if gvars is not None: + tvarset = set(tvars) + gvarset = set(gvars) + if not tvarset <= gvarset: + s_vars = ', '.join(str(t) for t in tvars if t not in gvarset) + s_args = ', '.join(str(g) for g in gvars) + raise TypeError(f"Some type variables ({s_vars}) are" + f" not listed in Generic[{s_args}]") + tvars = gvars + cls.__parameters__ = tuple(tvars) - def __typing_prepare_subst__(self, alias, args): - params = alias.__parameters__ - i = params.index(self) - if i >= len(args): - raise TypeError(f"Too few arguments for {alias}") - # Special case where Z[[int, str, bool]] == Z[int, str, bool] in PEP 612. - if len(params) == 1 and not _is_param_expr(args[0]): - assert i == 0 - args = (args,) - # Convert lists to tuples to help other libraries cache the results. - elif isinstance(args[i], list): - args = (*args[:i], tuple(args[i]), *args[i+1:]) - return args def _is_dunder(attr): return attr.startswith('__') and attr.endswith('__') @@ -1812,113 +1651,6 @@ def __typing_is_unpacked_typevartuple__(self): return isinstance(self.__args__[0], TypeVarTuple) -class Generic: - """Abstract base class for generic types. - - A generic type is typically declared by inheriting from - this class parameterized with one or more type variables. - For example, a generic mapping type might be defined as:: - - class Mapping(Generic[KT, VT]): - def __getitem__(self, key: KT) -> VT: - ... - # Etc. - - This class can then be used as follows:: - - def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: - try: - return mapping[key] - except KeyError: - return default - """ - __slots__ = () - _is_protocol = False - - @_tp_cache - def __class_getitem__(cls, params): - """Parameterizes a generic class. - - At least, parameterizing a generic class is the *main* thing this method - does. For example, for some generic class `Foo`, this is called when we - do `Foo[int]` - there, with `cls=Foo` and `params=int`. - - However, note that this method is also called when defining generic - classes in the first place with `class Foo(Generic[T]): ...`. - """ - if not isinstance(params, tuple): - params = (params,) - - params = tuple(_type_convert(p) for p in params) - if cls in (Generic, Protocol): - # Generic and Protocol can only be subscripted with unique type variables. - if not params: - raise TypeError( - f"Parameter list to {cls.__qualname__}[...] cannot be empty" - ) - if not all(_is_typevar_like(p) for p in params): - raise TypeError( - f"Parameters to {cls.__name__}[...] must all be type variables " - f"or parameter specification variables.") - if len(set(params)) != len(params): - raise TypeError( - f"Parameters to {cls.__name__}[...] must all be unique") - else: - # Subscripting a regular Generic subclass. - for param in cls.__parameters__: - prepare = getattr(param, '__typing_prepare_subst__', None) - if prepare is not None: - params = prepare(cls, params) - _check_generic(cls, params, len(cls.__parameters__)) - - new_args = [] - for param, new_arg in zip(cls.__parameters__, params): - if isinstance(param, TypeVarTuple): - new_args.extend(new_arg) - else: - new_args.append(new_arg) - params = tuple(new_args) - - return _GenericAlias(cls, params) - - def __init_subclass__(cls, *args, **kwargs): - super().__init_subclass__(*args, **kwargs) - tvars = [] - if '__orig_bases__' in cls.__dict__: - error = Generic in cls.__orig_bases__ - else: - error = (Generic in cls.__bases__ and - cls.__name__ != 'Protocol' and - type(cls) != _TypedDictMeta) - if error: - raise TypeError("Cannot inherit from plain Generic") - if '__orig_bases__' in cls.__dict__: - tvars = _collect_parameters(cls.__orig_bases__) - # Look for Generic[T1, ..., Tn]. - # If found, tvars must be a subset of it. - # If not found, tvars is it. - # Also check for and reject plain Generic, - # and reject multiple Generic[...]. - gvars = None - for base in cls.__orig_bases__: - if (isinstance(base, _GenericAlias) and - base.__origin__ is Generic): - if gvars is not None: - raise TypeError( - "Cannot inherit from Generic[...] multiple times.") - gvars = base.__parameters__ - if gvars is not None: - tvarset = set(tvars) - gvarset = set(gvars) - if not tvarset <= gvarset: - s_vars = ', '.join(str(t) for t in tvars if t not in gvarset) - s_args = ', '.join(str(g) for g in gvars) - raise TypeError(f"Some type variables ({s_vars}) are" - f" not listed in Generic[{s_args}]") - tvars = gvars - cls.__parameters__ = tuple(tvars) - - class _TypingEllipsis: """Internal placeholder for ... (ellipsis).""" @@ -1926,7 +1658,7 @@ class _TypingEllipsis: _TYPING_INTERNALS = frozenset({ '__parameters__', '__orig_bases__', '__orig_class__', '_is_protocol', '_is_runtime_protocol', '__protocol_attrs__', - '__callable_proto_members_only__', + '__callable_proto_members_only__', '__type_params__', }) _SPECIAL_NAMES = frozenset({ @@ -2024,25 +1756,51 @@ def _lazy_load_getattr_static(): _cleanups.append(_lazy_load_getattr_static.cache_clear) +def _pickle_psargs(psargs): + return ParamSpecArgs, (psargs.__origin__,) + +copyreg.pickle(ParamSpecArgs, _pickle_psargs) + +def _pickle_pskwargs(pskwargs): + return ParamSpecKwargs, (pskwargs.__origin__,) + +copyreg.pickle(ParamSpecKwargs, _pickle_pskwargs) + +del _pickle_psargs, _pickle_pskwargs + class _ProtocolMeta(ABCMeta): - # This metaclass is really unfortunate and exists only because of - # the lack of __instancehook__. + # This metaclass is somewhat unfortunate, + # but is necessary for several reasons... def __init__(cls, *args, **kwargs): super().__init__(*args, **kwargs) - cls.__protocol_attrs__ = _get_protocol_attrs(cls) - # PEP 544 prohibits using issubclass() - # with protocols that have non-method members. - cls.__callable_proto_members_only__ = all( - callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__ - ) + if getattr(cls, "_is_protocol", False): + cls.__protocol_attrs__ = _get_protocol_attrs(cls) + # PEP 544 prohibits using issubclass() + # with protocols that have non-method members. + cls.__callable_proto_members_only__ = all( + callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__ + ) + + def __subclasscheck__(cls, other): + if ( + getattr(cls, '_is_protocol', False) + and not cls.__callable_proto_members_only__ + and not _allow_reckless_class_checks(depth=2) + ): + raise TypeError( + "Protocols with non-method members don't support issubclass()" + ) + return super().__subclasscheck__(other) def __instancecheck__(cls, instance): # We need this method for situations where attributes are # assigned in __init__. - is_protocol_cls = getattr(cls, "_is_protocol", False) + if not getattr(cls, "_is_protocol", False): + # i.e., it's a concrete subclass of a protocol + return super().__instancecheck__(instance) + if ( - is_protocol_cls and not getattr(cls, '_is_runtime_protocol', False) and not _allow_reckless_class_checks(depth=2) ): @@ -2052,17 +1810,16 @@ def __instancecheck__(cls, instance): if super().__instancecheck__(instance): return True - if is_protocol_cls: - getattr_static = _lazy_load_getattr_static() - for attr in cls.__protocol_attrs__: - try: - val = getattr_static(instance, attr) - except AttributeError: - break - if val is None and callable(getattr(cls, attr, None)): - break - else: - return True + getattr_static = _lazy_load_getattr_static() + for attr in cls.__protocol_attrs__: + try: + val = getattr_static(instance, attr) + except AttributeError: + break + if val is None and callable(getattr(cls, attr, None)): + break + else: + return True return False @@ -2120,11 +1877,6 @@ def _proto_hook(other): raise TypeError("Instance and class checks can only be used with" " @runtime_checkable protocols") - if not cls.__callable_proto_members_only__ : - if _allow_reckless_class_checks(): - return NotImplemented - raise TypeError("Protocols with non-method members" - " don't support issubclass()") if not isinstance(other, type): # Same error message as for issubclass(1, int). raise TypeError('issubclass() arg 1 must be a class') @@ -2722,8 +2474,9 @@ class Other(Leaf): # Error reported by type checker return f -# Some unconstrained type variables. These are used by the container types. -# (These are not for export.) +# Some unconstrained type variables. These were initially used by the container types. +# They were never meant for export and are now unused, but we keep them around to +# avoid breaking compatibility with users who import them. T = TypeVar('T') # Any type. KT = TypeVar('KT') # Key type. VT = TypeVar('VT') # Value type. @@ -2828,8 +2581,6 @@ def new_user(user_class: Type[U]) -> U: At this point the type checker knows that joe has type BasicUser. """ -# Internal type variable for callables. Not for export. -F = TypeVar("F", bound=Callable[..., Any]) @runtime_checkable class SupportsInt(Protocol): @@ -2882,22 +2633,22 @@ def __index__(self) -> int: @runtime_checkable -class SupportsAbs(Protocol[T_co]): +class SupportsAbs[T](Protocol): """An ABC with one abstract method __abs__ that is covariant in its return type.""" __slots__ = () @abstractmethod - def __abs__(self) -> T_co: + def __abs__(self) -> T: pass @runtime_checkable -class SupportsRound(Protocol[T_co]): +class SupportsRound[T](Protocol): """An ABC with one abstract method __round__ that is covariant in its return type.""" __slots__ = () @abstractmethod - def __round__(self, ndigits: int = 0) -> T_co: + def __round__(self, ndigits: int = 0) -> T: pass @@ -2943,7 +2694,7 @@ def __new__(cls, typename, bases, ns): module=ns['__module__']) nm_tpl.__bases__ = bases if Generic in bases: - class_getitem = Generic.__class_getitem__.__func__ + class_getitem = _generic_class_getitem nm_tpl.__class_getitem__ = classmethod(class_getitem) # update from user namespace without overriding special namedtuple attributes for key in ns: @@ -3394,47 +3145,11 @@ def __enter__(self) -> 'TextIO': pass -class _DeprecatedType(type): - def __getattribute__(cls, name): - if name not in ("__dict__", "__module__") and name in cls.__dict__: - warnings.warn( - f"{cls.__name__} is deprecated, import directly " - f"from typing instead. {cls.__name__} will be removed " - "in Python 3.12.", - DeprecationWarning, - stacklevel=2, - ) - return super().__getattribute__(name) - - -class io(metaclass=_DeprecatedType): - """Wrapper namespace for IO generic classes.""" - - __all__ = ['IO', 'TextIO', 'BinaryIO'] - IO = IO - TextIO = TextIO - BinaryIO = BinaryIO - - -io.__name__ = __name__ + '.io' -sys.modules[io.__name__] = io - Pattern = _alias(stdlib_re.Pattern, 1) Match = _alias(stdlib_re.Match, 1) -class re(metaclass=_DeprecatedType): - """Wrapper namespace for re type aliases.""" - - __all__ = ['Pattern', 'Match'] - Pattern = Pattern - Match = Match - -re.__name__ = __name__ + '.re' -sys.modules[re.__name__] = re - - -def reveal_type(obj: T, /) -> T: +def reveal_type[T](obj: T, /) -> T: """Reveal the inferred type of a variable. When a static type checker encounters a call to ``reveal_type()``, @@ -3454,6 +3169,11 @@ def reveal_type(obj: T, /) -> T: return obj +class _IdentityCallable(Protocol): + def __call__[T](self, arg: T, /) -> T: + ... + + def dataclass_transform( *, eq_default: bool = True, @@ -3462,7 +3182,7 @@ def dataclass_transform( frozen_default: bool = False, field_specifiers: tuple[type[Any] | Callable[..., Any], ...] = (), **kwargs: Any, -) -> Callable[[T], T]: +) -> _IdentityCallable: """Decorator that marks a function, class, or metaclass as providing dataclass-like behavior. @@ -3539,8 +3259,10 @@ def decorator(cls_or_fn): return decorator +type _Func = Callable[..., Any] + -def override(method: F, /) -> F: +def override[F: _Func](method: F, /) -> F: """Indicate that a method is intended to override a method in a base class. Usage: diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index da0073969bff0b..b73b34428764f7 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -25,6 +25,10 @@ scenarios for parsing, and for backward compatibility purposes, some parsing quirks from older RFCs are retained. The testcases in test_urlparse.py provides a good indicator of parsing behavior. + +The WHATWG URL Parser spec should also be considered. We are not compliant with +it either due to existing user code API behavior expectations (Hyrum's Law). +It serves as a useful guide when making changes. """ from collections import namedtuple @@ -80,6 +84,10 @@ '0123456789' '+-.') +# Leading and trailing C0 control and space to be stripped per WHATWG spec. +# == "".join([chr(i) for i in range(0, 0x20 + 1)]) +_WHATWG_C0_CONTROL_OR_SPACE = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ' + # Unsafe bytes to be removed per WHATWG spec _UNSAFE_URL_BYTES_TO_REMOVE = ['\t', '\r', '\n'] @@ -464,6 +472,10 @@ def urlsplit(url, scheme='', allow_fragments=True): """ url, scheme, _coerce_result = _coerce_args(url, scheme) + # Only lstrip url as some applications rely on preserving trailing space. + # (https://url.spec.whatwg.org/#concept-basic-url-parser would strip both) + url = url.lstrip(_WHATWG_C0_CONTROL_OR_SPACE) + scheme = scheme.strip(_WHATWG_C0_CONTROL_OR_SPACE) for b in _UNSAFE_URL_BYTES_TO_REMOVE: url = url.replace(b, "") diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 116b939e55fe70..9fc1840ba1e534 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -442,7 +442,12 @@ def __repr__(self): return ''.join(result) def FileHeader(self, zip64=None): - """Return the per-file header as a bytes object.""" + """Return the per-file header as a bytes object. + + When the optional zip64 arg is None rather than a bool, we will + decide based upon the file_size and compress_size, if known, + False otherwise. + """ dt = self.date_time dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2] dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2) @@ -458,16 +463,13 @@ def FileHeader(self, zip64=None): min_version = 0 if zip64 is None: + # We always explicitly pass zip64 within this module.... This + # remains for anyone using ZipInfo.FileHeader as a public API. zip64 = file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT if zip64: fmt = ' ZIP64_LIMIT or compress_size > ZIP64_LIMIT: - if not zip64: - raise LargeZipFile("Filesize would require ZIP64 extensions") - # File is larger than what fits into a 4 byte integer, - # fall back to the ZIP64 extension file_size = 0xffffffff compress_size = 0xffffffff min_version = ZIP64_VERSION @@ -1219,6 +1221,12 @@ def close(self): self._zinfo.CRC = self._crc self._zinfo.file_size = self._file_size + if not self._zip64: + if self._file_size > ZIP64_LIMIT: + raise RuntimeError("File size too large, try using force_zip64") + if self._compress_size > ZIP64_LIMIT: + raise RuntimeError("Compressed size too large, try using force_zip64") + # Write updated header info if self._zinfo.flag_bits & _MASK_USE_DATA_DESCRIPTOR: # Write CRC and file sizes after the file data @@ -1227,13 +1235,6 @@ def close(self): self._zinfo.compress_size, self._zinfo.file_size)) self._zipfile.start_dir = self._fileobj.tell() else: - if not self._zip64: - if self._file_size > ZIP64_LIMIT: - raise RuntimeError( - 'File size too large, try using force_zip64') - if self._compress_size > ZIP64_LIMIT: - raise RuntimeError( - 'Compressed size too large, try using force_zip64') # Seek backwards and write file header (which will now include # correct CRC and file sizes) @@ -1672,8 +1673,9 @@ def _open_to_write(self, zinfo, force_zip64=False): zinfo.external_attr = 0o600 << 16 # permissions: ?rw------- # Compressed size can be larger than uncompressed size - zip64 = self._allowZip64 and \ - (force_zip64 or zinfo.file_size * 1.05 > ZIP64_LIMIT) + zip64 = force_zip64 or (zinfo.file_size * 1.05 > ZIP64_LIMIT) + if not self._allowZip64 and zip64: + raise LargeZipFile("Filesize would require ZIP64 extensions") if self._seekable: self.fp.seek(self.start_dir) diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 2f5937489ac03d..177fc2044f694b 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -264,10 +264,10 @@ def library_recipes(): tk_patches = ['tk868_on_10_8_10_9.patch'] else: - tcl_tk_ver='8.6.12' - tcl_checksum='87ea890821d2221f2ab5157bc5eb885f' + tcl_tk_ver='8.6.13' + tcl_checksum='43a1fae7412f61ff11de2cfd05d28cfc3a73762f354a417c62370a54e2caf066' - tk_checksum='1d6dcf6120356e3d211e056dff5e462a' + tk_checksum='2e65fa069a23365440a3c56c556b8673b5e32a283800d8d9b257e3f584ce0675' tk_patches = [ ] @@ -359,9 +359,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.41.2", - url="https://sqlite.org/2023/sqlite-autoconf-3410200.tar.gz", - checksum="862075fd1c38324878ef809eda39edfe", + name="SQLite 3.42.0", + url="https://sqlite.org/2023/sqlite-autoconf-3420000.tar.gz", + checksum="0c5a92bc51cf07cae45b4a1e94653dea", extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index dbe8c520a7c78d..5bc356d5267045 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf2639 +{\rtf1\ansi\ansicpg1252\cocoartf2709 \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fswiss\fcharset0 Helvetica-Oblique; \f3\fmodern\fcharset0 CourierNewPSMT;\f4\fmodern\fcharset0 Courier;} {\colortbl;\red255\green255\blue255;} @@ -11,7 +11,7 @@ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 \f1\b \cf0 NOTE: -\f0\b0 This is an alpha preview of Python 3.12.0, the next feature release of Python 3. It is not intended for production use.\ +\f0\b0 This is a beta preview of Python 3.12.0, the next feature release of Python 3. It is not intended for production use.\ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 \cf0 \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 diff --git a/Mac/BuildScript/resources/Welcome.rtf b/Mac/BuildScript/resources/Welcome.rtf index 1f109ee9f13e0d..83b7aa9d883a16 100644 --- a/Mac/BuildScript/resources/Welcome.rtf +++ b/Mac/BuildScript/resources/Welcome.rtf @@ -1,4 +1,4 @@ -{\rtf1\ansi\ansicpg1252\cocoartf2708 +{\rtf1\ansi\ansicpg1252\cocoartf2709 \cocoascreenfonts1\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fmodern\fcharset0 CourierNewPSMT; } {\colortbl;\red255\green255\blue255;} @@ -12,8 +12,9 @@ \f1\b macOS $MACOSX_DEPLOYMENT_TARGET \f0\b0 .\ \ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 -\f1\b Python for macOS +\f1\b \cf0 Python for macOS \f0\b0 consists of the {\field{\*\fldinst{HYPERLINK "https://www.python.org"}}{\fldrslt Python}} programming language interpreter and its batteries-included standard library to allow easy access to macOS features. It also includes the Python integrated development environment, \f1\b IDLE \f0\b0 . You can also use the included @@ -25,28 +26,6 @@ At the end of this install, click on \f0 to install a set of current SSL root certificates.\ \ -\f1\b macOS 13 Ventura users -\f0\b0 : Due to an issue with the macOS -\f1\b Installer -\f0\b0 app, installation of some third-party packages including this Python package may fail with a vague -\f1\b "The installer encountered an error" -\f0\b0 message if the -\f1\b Installer -\f0\b0 app does not have permission to access the folder containing the downloaded installer file, typically in the -\f1\b Downloads -\f0\b0 folder. Go to -\f1\b System Settings -\f0\b0 -> -\f1\b Privacy & Security -\f0\b0 -> -\f1\b Files and Folders -\f0\b0 , then click the mark in front of -\f1\b Installer -\f0\b0 to expand, and enable -\f1\b Downloads Folder -\f0\b0 by moving the toggle to the right. See {\field{\*\fldinst{HYPERLINK "https://github.com/python/cpython/issues/103207"}}{\fldrslt https://github.com/python/cpython/issues/103207}} for up-to-date information on this issue.\ -\ - \f1\b NOTE: -\f0\b0 This is an alpha test preview of Python 3.12.0, the next feature release of Python 3. It is not intended for production use.\ +\f0\b0 This is a beta test preview of Python 3.12.0, the next feature release of Python 3. It is not intended for production use.\ } \ No newline at end of file diff --git a/Mac/BuildScript/scripts/postflight.framework b/Mac/BuildScript/scripts/postflight.framework index a63909358f1719..411fda13b89559 100755 --- a/Mac/BuildScript/scripts/postflight.framework +++ b/Mac/BuildScript/scripts/postflight.framework @@ -8,12 +8,12 @@ FWK="/Library/Frameworks/Python.framework/Versions/@PYVER@" "${FWK}/bin/python@PYVER@" -E -s -Wi \ "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ - -f -x 'bad_coding|badsyntax|site-packages|test/test_lib2to3/data' \ + -f -x 'bad_coding|badsyntax|site-packages' \ "${FWK}/lib/python${PYVER}" "${FWK}/bin/python@PYVER@" -E -s -Wi -O \ "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ - -f -x 'bad_coding|badsyntax|site-packages|test/test_lib2to3/data' \ + -f -x 'bad_coding|badsyntax|site-packages' \ "${FWK}/lib/python${PYVER}" "${FWK}/bin/python@PYVER@" -E -s -Wi \ diff --git a/Mac/Makefile.in b/Mac/Makefile.in index 69ab4198988570..78b4499cca986a 100644 --- a/Mac/Makefile.in +++ b/Mac/Makefile.in @@ -63,7 +63,6 @@ installunixtools: fi cd "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" && \ for fn in \ - 2to3 \ idle3 \ pydoc3 \ python3 \ @@ -123,7 +122,6 @@ altinstallunixtools: fi cd "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" && \ for fn in \ - 2to3-$(VERSION) \ idle$(VERSION) \ pydoc$(VERSION) \ python$(VERSION) \ diff --git a/Makefile.pre.in b/Makefile.pre.in index 7c44b7be5dbe67..091df3e4c0b814 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -421,6 +421,7 @@ PYTHON_OBJS= \ Python/sysmodule.o \ Python/thread.o \ Python/traceback.o \ + Python/tracemalloc.o \ Python/getopt.o \ Python/pystrcmp.o \ Python/pystrtod.o \ @@ -479,6 +480,7 @@ OBJECT_OBJS= \ Objects/structseq.o \ Objects/tupleobject.o \ Objects/typeobject.o \ + Objects/typevarobject.o \ Objects/unicodeobject.o \ Objects/unicodectype.o \ Objects/unionobject.o \ @@ -642,7 +644,7 @@ profile-gen-stamp: profile-clean-stamp exit 1;\ fi @echo "Building with support for profile generation:" - $(MAKE) build_all_generate_profile + $(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS_NODIST) $(PGO_PROF_GEN_FLAG)" LDFLAGS_NODIST="$(LDFLAGS_NODIST) $(PGO_PROF_GEN_FLAG)" LIBS="$(LIBS)" touch $@ # Run task with profile generation build to create profile information. @@ -652,8 +654,9 @@ profile-run-stamp: # enabled. $(MAKE) profile-gen-stamp # Next, run the profile task to generate the profile information. - $(MAKE) run_profile_task - $(MAKE) build_all_merge_profile + @ # FIXME: can't run for a cross build + $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true + $(LLVM_PROF_MERGER) # Remove profile generation binary since we are done with it. $(MAKE) clean-retain-profile # This is an expensive target to build and it does not have proper @@ -661,19 +664,6 @@ profile-run-stamp: # to record its completion and avoid re-running it. touch $@ -.PHONY: build_all_generate_profile -build_all_generate_profile: - $(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS_NODIST) $(PGO_PROF_GEN_FLAG)" LDFLAGS_NODIST="$(LDFLAGS_NODIST) $(PGO_PROF_GEN_FLAG)" LIBS="$(LIBS)" - -.PHONY: run_profile_task -run_profile_task: - @ # FIXME: can't run for a cross build - $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true - -.PHONY: build_all_merge_profile -build_all_merge_profile: - $(LLVM_PROF_MERGER) - # Compile Python binary with profile guided optimization. # To force re-running of the profile task, remove the profile-run-stamp file. .PHONY: profile-opt @@ -682,21 +672,55 @@ profile-opt: profile-run-stamp -rm -f profile-clean-stamp $(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS_NODIST) $(PGO_PROF_USE_FLAG)" LDFLAGS_NODIST="$(LDFLAGS_NODIST)" -.PHONY: bolt-opt -bolt-opt: @PREBOLT_RULE@ +# List of binaries that BOLT runs on. +BOLT_BINARIES := @BOLT_BINARIES@ + +BOLT_INSTRUMENT_FLAGS := @BOLT_INSTRUMENT_FLAGS@ +BOLT_APPLY_FLAGS := @BOLT_APPLY_FLAGS@ + +.PHONY: clean-bolt +clean-bolt: + # Profile data. rm -f *.fdata - @if $(READELF) -p .note.bolt_info $(BUILDPYTHON) | grep BOLT > /dev/null; then\ - echo "skip: $(BUILDPYTHON) is already BOLTed."; \ - else \ - @LLVM_BOLT@ ./$(BUILDPYTHON) -instrument -instrumentation-file-append-pid -instrumentation-file=$(abspath $(BUILDPYTHON).bolt) -o $(BUILDPYTHON).bolt_inst; \ - ./$(BUILDPYTHON).bolt_inst $(PROFILE_TASK) || true; \ - @MERGE_FDATA@ $(BUILDPYTHON).*.fdata > $(BUILDPYTHON).fdata; \ - @LLVM_BOLT@ ./$(BUILDPYTHON) -o $(BUILDPYTHON).bolt -data=$(BUILDPYTHON).fdata -update-debug-sections -reorder-blocks=ext-tsp -reorder-functions=hfsort+ -split-functions -icf=1 -inline-all -split-eh -reorder-functions-use-hot-size -peepholes=none -jump-tables=aggressive -inline-ap -indirect-call-promotion=all -dyno-stats -use-gnu-stack -frame-opt=hot; \ - rm -f *.fdata; \ - rm -f $(BUILDPYTHON).bolt_inst; \ - mv $(BUILDPYTHON).bolt $(BUILDPYTHON); \ - fi + # Pristine binaries before BOLT optimization. + rm -f *.prebolt + # BOLT instrumented binaries. + rm -f *.bolt_inst + +profile-bolt-stamp: $(BUILDPYTHON) + # Ensure a pristine, pre-BOLT copy of the binary and no profile data from last run. + for bin in $(BOLT_BINARIES); do \ + prebolt="$${bin}.prebolt"; \ + if [ -e "$${prebolt}" ]; then \ + echo "Restoring pre-BOLT binary $${prebolt}"; \ + mv "$${bin}.prebolt" "$${bin}"; \ + fi; \ + cp "$${bin}" "$${prebolt}"; \ + rm -f $${bin}.bolt.*.fdata $${bin}.fdata; \ + done + # Instrument each binary. + for bin in $(BOLT_BINARIES); do \ + @LLVM_BOLT@ "$${bin}" -instrument -instrumentation-file-append-pid -instrumentation-file=$(abspath $${bin}.bolt) -o $${bin}.bolt_inst $(BOLT_INSTRUMENT_FLAGS); \ + mv "$${bin}.bolt_inst" "$${bin}"; \ + done + # Run instrumented binaries to collect data. + $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true + # Merge all the data files together. + for bin in $(BOLT_BINARIES); do \ + @MERGE_FDATA@ $${bin}.*.fdata > "$${bin}.fdata"; \ + rm -f $${bin}.*.fdata; \ + done + # Run bolt against the merged data to produce an optimized binary. + for bin in $(BOLT_BINARIES); do \ + @LLVM_BOLT@ "$${bin}.prebolt" -o "$${bin}.bolt" -data="$${bin}.fdata" $(BOLT_APPLY_FLAGS); \ + mv "$${bin}.bolt" "$${bin}"; \ + done + touch $@ +.PHONY: bolt-opt +bolt-opt: + $(MAKE) @PREBOLT_RULE@ + $(MAKE) profile-bolt-stamp # Compile and run with gcov .PHONY: coverage @@ -1767,6 +1791,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_tracemalloc.h \ $(srcdir)/Include/internal/pycore_tuple.h \ $(srcdir)/Include/internal/pycore_typeobject.h \ + $(srcdir)/Include/internal/pycore_typevarobject.h \ $(srcdir)/Include/internal/pycore_ucnhash.h \ $(srcdir)/Include/internal/pycore_unionobject.h \ $(srcdir)/Include/internal/pycore_unicodeobject.h \ @@ -1844,7 +1869,7 @@ hostrunnertest: all pythoninfo: all $(RUNSHARED) $(HOSTRUNNER) ./$(BUILDPYTHON) -m test.pythoninfo -QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io test_lib2to3 \ +QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io \ test_multibytecodec test_urllib2_localnet test_itertools \ test_multiprocessing_fork test_multiprocessing_spawn \ test_multiprocessing_forkserver \ @@ -2017,8 +2042,6 @@ bininstall: altbininstall (cd $(DESTDIR)$(BINDIR); $(LN) -s idle$(VERSION) idle3) -rm -f $(DESTDIR)$(BINDIR)/pydoc3 (cd $(DESTDIR)$(BINDIR); $(LN) -s pydoc$(VERSION) pydoc3) - -rm -f $(DESTDIR)$(BINDIR)/2to3 - (cd $(DESTDIR)$(BINDIR); $(LN) -s 2to3-$(VERSION) 2to3) if test "x$(LIPO_32BIT_FLAGS)" != "x" ; then \ rm -f $(DESTDIR)$(BINDIR)/python3-32$(EXE); \ (cd $(DESTDIR)$(BINDIR); $(LN) -s python$(VERSION)-32$(EXE) python3-32$(EXE)) \ @@ -2065,7 +2088,6 @@ LIBSUBDIRS= asyncio \ idlelib idlelib/Icons \ importlib importlib/resources importlib/metadata \ json \ - lib2to3 lib2to3/fixes lib2to3/pgen2 \ logging \ multiprocessing multiprocessing/dummy \ pydoc_data \ @@ -2159,10 +2181,6 @@ TESTSUBDIRS= idlelib/idle_test \ test/test_importlib/resources/zipdata02 \ test/test_importlib/source \ test/test_json \ - test/test_lib2to3 \ - test/test_lib2to3/data \ - test/test_lib2to3/data/fixers \ - test/test_lib2to3/data/fixers/myfixes \ test/test_peg_generator \ test/test_sqlite3 \ test/test_tkinter \ @@ -2276,16 +2294,12 @@ libinstall: all $(srcdir)/Modules/xxmodule.c -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ $(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \ -o 0 -o 1 -o 2 $(COMPILEALL_OPTS) -d $(LIBDEST) -f \ - -x 'bad_coding|badsyntax|site-packages|test/test_lib2to3/data' \ + -x 'bad_coding|badsyntax|site-packages' \ $(DESTDIR)$(LIBDEST) -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ $(PYTHON_FOR_BUILD) -Wi $(DESTDIR)$(LIBDEST)/compileall.py \ -o 0 -o 1 -o 2 $(COMPILEALL_OPTS) -d $(LIBDEST)/site-packages -f \ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages - -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt - -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt # bpo-21536: Misc/python-config.sh is generated in the build directory # from $(srcdir)Misc/python-config.sh.in. @@ -2305,15 +2319,9 @@ python-config: $(srcdir)/Misc/python-config.in Misc/python-config.sh # macOS' make seems to ignore a dependency on a # "$(BUILD_SCRIPTS_DIR): $(MKDIR_P) $@" rule. BUILD_SCRIPTS_DIR=build/scripts-$(VERSION) -SCRIPT_2TO3=$(BUILD_SCRIPTS_DIR)/2to3-$(VERSION) SCRIPT_IDLE=$(BUILD_SCRIPTS_DIR)/idle$(VERSION) SCRIPT_PYDOC=$(BUILD_SCRIPTS_DIR)/pydoc$(VERSION) -$(SCRIPT_2TO3): $(srcdir)/Tools/scripts/2to3 - @$(MKDIR_P) $(BUILD_SCRIPTS_DIR) - sed -e "s,/usr/bin/env python3,$(EXENAME)," < $(srcdir)/Tools/scripts/2to3 > $@ - @chmod +x $@ - $(SCRIPT_IDLE): $(srcdir)/Tools/scripts/idle3 @$(MKDIR_P) $(BUILD_SCRIPTS_DIR) sed -e "s,/usr/bin/env python3,$(EXENAME)," < $(srcdir)/Tools/scripts/idle3 > $@ @@ -2325,7 +2333,7 @@ $(SCRIPT_PYDOC): $(srcdir)/Tools/scripts/pydoc3 @chmod +x $@ .PHONY: scripts -scripts: $(SCRIPT_2TO3) $(SCRIPT_IDLE) $(SCRIPT_PYDOC) python-config +scripts: $(SCRIPT_IDLE) $(SCRIPT_PYDOC) python-config # Install the include files INCLDIRSTOMAKE=$(INCLUDEDIR) $(CONFINCLUDEDIR) $(INCLUDEPY) $(CONFINCLUDEPY) @@ -2411,7 +2419,6 @@ libainstall: all scripts $(INSTALL_SCRIPT) $(srcdir)/install-sh $(DESTDIR)$(LIBPL)/install-sh $(INSTALL_SCRIPT) python-config.py $(DESTDIR)$(LIBPL)/python-config.py $(INSTALL_SCRIPT) python-config $(DESTDIR)$(BINDIR)/python$(LDVERSION)-config - $(INSTALL_SCRIPT) $(SCRIPT_2TO3) $(DESTDIR)$(BINDIR)/2to3-$(VERSION) $(INSTALL_SCRIPT) $(SCRIPT_IDLE) $(DESTDIR)$(BINDIR)/idle$(VERSION) $(INSTALL_SCRIPT) $(SCRIPT_PYDOC) $(DESTDIR)$(BINDIR)/pydoc$(VERSION) @if [ -s Modules/python.exp -a \ @@ -2612,7 +2619,6 @@ clean-retain-profile: pycremoval find build -name '*.py' -exec rm -f {} ';' || true find build -name '*.py[co]' -exec rm -f {} ';' || true -rm -f pybuilddir.txt - -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f _bootstrap_python -rm -f python.html python*.js python.data python*.symbols python*.map -rm -f $(WASM_STDLIB) @@ -2632,10 +2638,11 @@ profile-removal: rm -f $(COVERAGE_INFO) rm -rf $(COVERAGE_REPORT) rm -f profile-run-stamp + rm -f profile-bolt-stamp .PHONY: clean -clean: clean-retain-profile - @if test @DEF_MAKE_ALL_RULE@ = profile-opt; then \ +clean: clean-retain-profile clean-bolt + @if test @DEF_MAKE_ALL_RULE@ = profile-opt -o @DEF_MAKE_ALL_RULE@ = bolt-opt; then \ rm -f profile-gen-stamp profile-clean-stamp; \ $(MAKE) profile-removal; \ fi diff --git a/Misc/ACKS b/Misc/ACKS index 42ec059a7c4ec2..be8755637ffa3c 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -2060,6 +2060,7 @@ Yuxiao Zeng Uwe Zessin Cheng Zhang George Zhang +Youfu Zhang Charlie Zhao Kai Zhu Tarek Ziadé diff --git a/Misc/NEWS.d/3.11.0a1.rst b/Misc/NEWS.d/3.11.0a1.rst index 7670e482ede5b6..10e123e325c863 100644 --- a/Misc/NEWS.d/3.11.0a1.rst +++ b/Misc/NEWS.d/3.11.0a1.rst @@ -1825,7 +1825,7 @@ Patch by Victor Stinner. .. nonce: 9nmMtB .. section: Library -The :mod:`lib2to3` package is now deprecated and may not be able to parse +The :mod:`!lib2to3` package is now deprecated and may not be able to parse Python 3.10 or newer. See the :pep:`617` (New PEG parser for CPython). Patch by Victor Stinner. diff --git a/Misc/NEWS.d/3.12.0b1.rst b/Misc/NEWS.d/3.12.0b1.rst new file mode 100644 index 00000000000000..eb42b45726f5ed --- /dev/null +++ b/Misc/NEWS.d/3.12.0b1.rst @@ -0,0 +1,2412 @@ +.. date: 2023-05-02-17-56-32 +.. gh-issue: 99889 +.. nonce: l664SU +.. release date: 2023-05-22 +.. section: Security + +Fixed a security in flaw in :func:`uu.decode` that could allow for directory +traversal based on the input if no ``out_file`` was specified. + +.. + +.. date: 2023-05-01-15-03-25 +.. gh-issue: 104049 +.. nonce: b01Y3g +.. section: Security + +Do not expose the local on-disk location in directory indexes produced by +:class:`http.client.SimpleHTTPRequestHandler`. + +.. + +.. date: 2023-04-17-14-38-12 +.. gh-issue: 99108 +.. nonce: 720lG8 +.. section: Security + +Upgrade built-in :mod:`hashlib` SHA3 implementation to a verified +implementation from the ``HACL*`` project. Used when OpenSSL is not present +or lacks SHA3. + +.. + +.. date: 2023-03-07-20-59-17 +.. gh-issue: 102153 +.. nonce: 14CLSZ +.. section: Security + +:func:`urllib.parse.urlsplit` now strips leading C0 control and space +characters following the specification for URLs defined by WHATWG in +response to CVE-2023-24329. Patch by Illia Volochii. + +.. + +.. date: 2023-05-20-23-08-48 +.. gh-issue: 102856 +.. nonce: Knv9WT +.. section: Core and Builtins + +Implement PEP 701 changes in the :mod:`tokenize` module. Patch by Marta +Gómez Macías and Pablo Galindo Salgado + +.. + +.. date: 2023-05-18-13-00-21 +.. gh-issue: 104615 +.. nonce: h_rtw2 +.. section: Core and Builtins + +Fix wrong ordering of assignments in code like ``a, a = x, y``. Contributed +by Carl Meyer. + +.. + +.. date: 2023-05-16-19-17-48 +.. gh-issue: 104572 +.. nonce: eBZQYS +.. section: Core and Builtins + +Improve syntax error message for invalid constructs in :pep:`695` contexts +and in annotations when ``from __future__ import annotations`` is active. + +.. + +.. date: 2023-05-14-18-56-54 +.. gh-issue: 104482 +.. nonce: yaQsv8 +.. section: Core and Builtins + +Fix three error handling bugs in ast.c's validation of pattern matching +statements. + +.. + +.. date: 2023-05-12-13-30-04 +.. gh-issue: 102818 +.. nonce: rnv1mH +.. section: Core and Builtins + +Do not add a frame to the traceback in the ``sys.setprofile`` and +``sys.settrace`` trampoline functions. This ensures that frames are not +duplicated if an exception is raised in the callback function, and ensures +that frames are not omitted if a C callback is used and that does not add +the frame. + +.. + +.. date: 2023-05-11-15-56-07 +.. gh-issue: 104405 +.. nonce: tXV5fn +.. section: Core and Builtins + +Fix an issue where some :term:`bytecode` instructions could ignore +:pep:`523` when "inlining" calls. + +.. + +.. date: 2023-05-10-20-52-29 +.. gh-issue: 103082 +.. nonce: y3LG5Q +.. section: Core and Builtins + +Change behavior of ``sys.monitoring.events.LINE`` events in +``sys.monitoring``: Line events now occur when a new line is reached +dynamically, instead of using a static approximation, as before. This makes +the behavior very similar to that of "line" events in ``sys.settrace``. This +should ease porting of tools from 3.11 to 3.12. + +.. + +.. date: 2023-05-08-10-34-55 +.. gh-issue: 104263 +.. nonce: ctHWI8 +.. section: Core and Builtins + +Fix ``float("nan")`` to produce a quiet NaN on platforms (like MIPS) where +the meaning of the signalling / quiet bit is inverted from its usual +meaning. Also introduce a new macro ``Py_INFINITY`` matching C99's +``INFINITY``, and refactor internals to rely on C99's ``NAN`` and +``INFINITY`` macros instead of hard-coding bit patterns for infinities and +NaNs. Thanks Sebastian Berg. + +.. + +.. date: 2023-05-05-13-18-56 +.. gh-issue: 99113 +.. nonce: hT1ajK +.. section: Core and Builtins + +Multi-phase init extension modules may now indicate that they support +running in subinterpreters that have their own GIL. This is done by using +``Py_MOD_PER_INTERPRETER_GIL_SUPPORTED`` as the value for the +``Py_mod_multiple_interpreters`` module def slot. Otherwise the module, by +default, cannot be imported in such subinterpreters. (This does not affect +the main interpreter or subinterpreters that do not have their own GIL.) In +addition to the isolation that multi-phase init already normally requires, +support for per-interpreter GIL involves one additional constraint: +thread-safety. If the module has external (linked) dependencies and those +libraries have any state that isn't thread-safe then the module must do the +additional work to add thread-safety. This should be an uncommon case. + +.. + +.. date: 2023-05-05-12-14-47 +.. gh-issue: 99113 +.. nonce: -RAdnv +.. section: Core and Builtins + +The GIL is now (optionally) per-interpreter. This is the fundamental change +for PEP 684. This is all made possible by virtue of the isolated state of +each interpreter in the process. The behavior of the main interpreter +remains unchanged. Likewise, interpreters created using +``Py_NewInterpreter()`` are not affected. To get an interpreter with its +own GIL, call ``Py_NewInterpreterFromConfig()``. + +.. + +.. date: 2023-05-03-17-46-47 +.. gh-issue: 104108 +.. nonce: GOxAYt +.. section: Core and Builtins + +Multi-phase init extension modules may now indicate whether or not they +actually support multiple interpreters. By default such modules are +expected to support use in multiple interpreters. In the uncommon case that +one does not, it may use the new ``Py_mod_multiple_interpreters`` module def +slot. A value of ``0`` means the module does not support them. ``1`` means +it does. The default is ``1``. + +.. + +.. date: 2023-05-02-18-29-49 +.. gh-issue: 104142 +.. nonce: _5Et6I +.. section: Core and Builtins + +Fix an issue where :class:`list` or :class:`tuple` repetition could fail to +respect :pep:`683`. + +.. + +.. date: 2023-05-01-21-05-47 +.. gh-issue: 104078 +.. nonce: vRaBsU +.. section: Core and Builtins + +Improve the performance of :c:func:`PyObject_HasAttrString` + +.. + +.. date: 2023-05-01-14-48-29 +.. gh-issue: 104066 +.. nonce: pzoUZQ +.. section: Core and Builtins + +Improve the performance of :func:`hasattr` for module objects with a missing +attribute. + +.. + +.. date: 2023-05-01-14-10-38 +.. gh-issue: 104028 +.. nonce: dxfh13 +.. section: Core and Builtins + +Reduce object creation while calling callback function from gc. Patch by +Dong-hee Na. + +.. + +.. date: 2023-05-01-12-03-52 +.. gh-issue: 104018 +.. nonce: PFxGS4 +.. section: Core and Builtins + +Disallow the "z" format specifier in %-format of bytes objects. + +.. + +.. date: 2023-05-01-08-08-05 +.. gh-issue: 102213 +.. nonce: nfH-4C +.. section: Core and Builtins + +Fix performance loss when accessing an object's attributes with +``__getattr__`` defined. + +.. + +.. date: 2023-04-26-17-56-18 +.. gh-issue: 103895 +.. nonce: ESB6tn +.. section: Core and Builtins + +Improve handling of edge cases in showing ``Exception.__notes__``. Ensures +that the messages always end with a newline and that string/bytes are not +exploded over multiple lines. Patch by Carey Metcalfe. + +.. + +.. date: 2023-04-26-16-26-35 +.. gh-issue: 103907 +.. nonce: kiONZQ +.. section: Core and Builtins + +Don't modify the refcounts of known immortal objects (:const:`True`, +:const:`False`, and :const:`None`) in the main interpreter loop. + +.. + +.. date: 2023-04-26-15-14-23 +.. gh-issue: 103899 +.. nonce: 1pqKPF +.. section: Core and Builtins + +Provide a helpful hint in the :exc:`TypeError` message when accidentally +calling a :term:`module` object that has a callable attribute of the same +name (such as :func:`dis.dis` or :class:`datetime.datetime`). + +.. + +.. date: 2023-04-25-20-56-01 +.. gh-issue: 103845 +.. nonce: V7NYFn +.. section: Core and Builtins + +Remove both line and instruction instrumentation before adding new ones for +monitoring, to avoid newly added instrumentation being removed immediately. + +.. + +.. date: 2023-04-25-08-43-11 +.. gh-issue: 103763 +.. nonce: ZLBZk1 +.. section: Core and Builtins + +Implement :pep:`695`, adding syntactic support for generic classes, generic +functions, and type aliases. + +A new ``type X = ...`` syntax is added for type aliases, which resolves at +runtime to an instance of the new class ``typing.TypeAliasType``. The value +is lazily evaluated and is accessible through the ``.__value__`` attribute. +This is implemented as a new AST node ``ast.TypeAlias``. + +New syntax (``class X[T]: ...``, ``def func[T](): ...``) is added for +defining generic functions and classes. This is implemented as a new +``type_params`` attribute on the AST nodes for classes and functions. This +node holds instances of the new AST classes ``ast.TypeVar``, +``ast.ParamSpec``, and ``ast.TypeVarTuple``. + +``typing.TypeVar``, ``typing.ParamSpec``, ``typing.ParamSpecArgs``, +``typing.ParamSpecKwargs``, ``typing.TypeVarTuple``, and ``typing.Generic`` +are now implemented in C rather than Python. + +There are new bytecode instructions ``LOAD_LOCALS``, +``LOAD_CLASSDICT_OR_GLOBAL``, and ``LOAD_CLASSDICT_OR_DEREF`` to support +correct resolution of names in class namespaces. + +Patch by Eric Traut, Larry Hastings, and Jelle Zijlstra. + +.. + +.. date: 2023-04-24-21-47-38 +.. gh-issue: 103801 +.. nonce: WaBanq +.. section: Core and Builtins + +Adds three minor linting fixes to the wasm module caught that were caught by +ruff. + +.. + +.. date: 2023-04-24-14-38-16 +.. gh-issue: 103793 +.. nonce: kqoH6Q +.. section: Core and Builtins + +Optimized asyncio Task creation by deferring expensive string formatting +(task name generation) from Task creation to the first time ``get_name`` is +called. This makes asyncio benchmarks up to 5% faster. + +.. + +.. date: 2023-04-21-17-03-14 +.. gh-issue: 102310 +.. nonce: anLjDx +.. section: Core and Builtins + +Change the error range for invalid bytes literals. + +.. + +.. date: 2023-04-21-16-12-41 +.. gh-issue: 103590 +.. nonce: 7DHDOE +.. section: Core and Builtins + +Do not wrap a single exception raised from a ``try-except*`` construct in an +:exc:`ExceptionGroup`. + +.. + +.. date: 2023-04-20-16-17-51 +.. gh-issue: 103650 +.. nonce: K1MFXR +.. section: Core and Builtins + +Change the perf map format to remove the '0x' prefix from the addresses + +.. + +.. date: 2023-04-17-16-00-32 +.. gh-issue: 102856 +.. nonce: UunJ7y +.. section: Core and Builtins + +Implement the required C tokenizer changes for PEP 701. Patch by Pablo +Galindo Salgado, Lysandros Nikolaou, Batuhan Taskaya, Marta Gómez Macías and +sunmy2019. + +.. + +.. date: 2023-04-16-14-38-39 +.. gh-issue: 100530 +.. nonce: OR6-sn +.. section: Core and Builtins + +Clarify the error message raised when the called part of a class pattern +isn't actually a class. + +.. + +.. date: 2023-04-14-22-35-23 +.. gh-issue: 101517 +.. nonce: 5EqM-S +.. section: Core and Builtins + +Fix bug in line numbers of instructions emitted for :keyword:`except* +`. + +.. + +.. date: 2023-04-13-00-58-55 +.. gh-issue: 103492 +.. nonce: P4k0Ay +.. section: Core and Builtins + +Clarify :exc:`SyntaxWarning` with literal ``is`` comparison by specifying +which literal is problematic, since comparisons using ``is`` with e.g. None +and bool literals are idiomatic. + +.. + +.. date: 2023-04-12-20-22-03 +.. gh-issue: 87729 +.. nonce: 99A7UO +.. section: Core and Builtins + +Add :opcode:`LOAD_SUPER_ATTR` (and a specialization for +``super().method()``) to speed up ``super().method()`` and ``super().attr``. +This makes ``super().method()`` roughly 2.3x faster and brings it within 20% +of the performance of a simple method call. Patch by Vladimir Matveev and +Carl Meyer. + +.. + +.. date: 2023-04-12-20-18-51 +.. gh-issue: 103488 +.. nonce: vYvlHD +.. section: Core and Builtins + +Change the internal offset distinguishing yield and return target addresses, +so that the instruction pointer is correct for exception handling and other +stack unwinding. + +.. + +.. date: 2023-04-12-19-55-24 +.. gh-issue: 82012 +.. nonce: FlcJAh +.. section: Core and Builtins + +The bitwise inversion operator (``~``) on bool is deprecated. It returns the +bitwise inversion of the underlying ``int`` representation such that +``bool(~True) == True``, which can be confusing. Use ``not`` for logical +negation of bools. In the rare case that you really need the bitwise +inversion of the underlying ``int``, convert to int explicitly ``~int(x)``. + +.. + +.. date: 2023-04-09-22-21-57 +.. gh-issue: 77757 +.. nonce: _Ow-u2 +.. section: Core and Builtins + +Exceptions raised in a typeobject's ``__set_name__`` method are no longer +wrapped by a :exc:`RuntimeError`. Context information is added to the +exception as a :pep:`678` note. + +.. + +.. date: 2023-04-09-04-30-02 +.. gh-issue: 103333 +.. nonce: gKOetS +.. section: Core and Builtins + +:exc:`AttributeError` now retains the ``name`` attribute when pickled and +unpickled. + +.. + +.. date: 2023-04-08-17-13-07 +.. gh-issue: 103242 +.. nonce: ysI1b3 +.. section: Core and Builtins + +Migrate :meth:`~ssl.SSLContext.set_ecdh_curve` method not to use deprecated +OpenSSL APIs. Patch by Dong-hee Na. + +.. + +.. date: 2023-04-07-12-18-41 +.. gh-issue: 103323 +.. nonce: 9802br +.. section: Core and Builtins + +We've replaced our use of ``_PyRuntime.tstate_current`` with a thread-local +variable. This is a fairly low-level implementation detail, and there +should be no change in behavior. + +.. + +.. date: 2023-04-02-22-14-57 +.. gh-issue: 84436 +.. nonce: hvMgwF +.. section: Core and Builtins + +The implementation of PEP-683 which adds Immortal Objects by using a fixed +reference count that skips reference counting to make objects truly +immutable. + +.. + +.. date: 2023-04-01-00-46-31 +.. gh-issue: 102700 +.. nonce: 493NB4 +.. section: Core and Builtins + +Allow built-in modules to be submodules. This allows submodules to be +statically linked into a CPython binary. + +.. + +.. date: 2023-03-31-17-24-03 +.. gh-issue: 103082 +.. nonce: isRUcV +.. section: Core and Builtins + +Implement :pep:`669` Low Impact Monitoring for CPython. + +.. + +.. date: 2023-03-25-23-24-38 +.. gh-issue: 88691 +.. nonce: 2SWBd1 +.. section: Core and Builtins + +Reduce the number of inline :opcode:`CACHE` entries for :opcode:`CALL`. + +.. + +.. date: 2023-03-07-17-37-00 +.. gh-issue: 102500 +.. nonce: RUSQhz +.. section: Core and Builtins + +Make the buffer protocol accessible in Python code using the new +``__buffer__`` and ``__release_buffer__`` magic methods. See :pep:`688` for +details. Patch by Jelle Zijlstra. + +.. + +.. date: 2023-01-30-15-40-29 +.. gh-issue: 97933 +.. nonce: nUlp3r +.. section: Core and Builtins + +:pep:`709`: inline list, dict and set comprehensions to improve performance +and reduce bytecode size. + +.. + +.. date: 2022-11-08-12-36-25 +.. gh-issue: 99184 +.. nonce: KIaqzz +.. section: Core and Builtins + +Bypass instance attribute access of ``__name__`` in ``repr`` of +:class:`weakref.ref`. + +.. + +.. date: 2022-10-06-23-32-11 +.. gh-issue: 98003 +.. nonce: xWE0Yu +.. section: Core and Builtins + +Complex function calls are now faster and consume no C stack space. + +.. + +.. bpo: 39610 +.. date: 2020-02-11-15-54-40 +.. nonce: fvgsCl +.. section: Core and Builtins + +``len()`` for 0-dimensional :class:`memoryview`` objects (such as +``memoryview(ctypes.c_uint8(42))``) now raises a :exc:`TypeError`. +Previously this returned ``1``, which was not consistent with ``mem_0d[0]`` +raising an :exc:`IndexError``. + +.. + +.. bpo: 31821 +.. date: 2019-12-01-12-58-31 +.. nonce: 1FNmwk +.. section: Core and Builtins + +Fix :func:`!pause_reading` to work when called from :func:`!connection_made` +in :mod:`asyncio`. + +.. + +.. date: 2023-05-17-21-01-48 +.. gh-issue: 104600 +.. nonce: E6CK35 +.. section: Library + +:func:`functools.update_wrapper` now sets the ``__type_params__`` attribute +(added by :pep:`695`). + +.. + +.. date: 2023-05-17-20-03-01 +.. gh-issue: 104340 +.. nonce: kp_XmX +.. section: Library + +When an ``asyncio`` pipe protocol loses its connection due to an error, and +the caller doesn't await ``wait_closed()`` on the corresponding +``StreamWriter``, don't log a warning about an exception that was never +retrieved. After all, according to the ``StreamWriter.close()`` docs, the +``wait_closed()`` call is optional ("not mandatory"). + +.. + +.. date: 2023-05-17-16-58-23 +.. gh-issue: 104555 +.. nonce: 5rb5oM +.. section: Library + +Fix issue where an :func:`issubclass` check comparing a class ``X`` against +a :func:`runtime-checkable protocol ` ``Y`` with +non-callable members would not cause :exc:`TypeError` to be raised if an +:func:`isinstance` call had previously been made comparing an instance of +``X`` to ``Y``. This issue was present in edge cases on Python 3.11, but +became more prominent in 3.12 due to some unrelated changes that were made +to runtime-checkable protocols. Patch by Alex Waygood. + +.. + +.. date: 2023-05-17-08-01-36 +.. gh-issue: 104372 +.. nonce: jpoWs6 +.. section: Library + +Refactored the ``_posixsubprocess`` internals to avoid Python C API usage +between fork and exec when marking ``pass_fds=`` file descriptors +inheritable. + +.. + +.. date: 2023-05-17-03-14-07 +.. gh-issue: 104484 +.. nonce: y6KxL6 +.. section: Library + +Added *case_sensitive* argument to :meth:`pathlib.PurePath.match` + +.. + +.. date: 2023-05-16-11-02-44 +.. gh-issue: 75367 +.. nonce: qLWR35 +.. section: Library + +Fix data descriptor detection in :func:`inspect.getattr_static`. + +.. + +.. date: 2023-05-16-10-07-16 +.. gh-issue: 104536 +.. nonce: hFWD8f +.. section: Library + +Fix a race condition in the internal :mod:`multiprocessing.process` cleanup +logic that could manifest as an unintended ``AttributeError`` when calling +``process.close()``. + +.. + +.. date: 2023-05-12-19-29-28 +.. gh-issue: 103857 +.. nonce: 0IzSxr +.. section: Library + +Update datetime deprecations' stracktrace to point to the calling line + +.. + +.. date: 2023-05-11-21-32-18 +.. gh-issue: 101520 +.. nonce: l9MjRE +.. section: Library + +Move the core functionality of the ``tracemalloc`` module in the ``Python/`` +folder, leaving just the module wrapper in ``Modules/``. + +.. + +.. date: 2023-05-11-07-50-00 +.. gh-issue: 104392 +.. nonce: YSllzt +.. section: Library + +Remove undocumented and unused ``_paramspec_tvars`` attribute from some +classes in :mod:`typing`. + +.. + +.. date: 2023-05-11-01-07-42 +.. gh-issue: 102613 +.. nonce: uMsokt +.. section: Library + +Fix issue where :meth:`pathlib.Path.glob` raised :exc:`RecursionError` when +walking deep directory trees. + +.. + +.. date: 2023-05-10-19-33-36 +.. gh-issue: 103000 +.. nonce: j0KSfD +.. section: Library + +Improve performance of :func:`dataclasses.asdict` for the common case where +*dict_factory* is ``dict``. Patch by David C Ellis. + +.. + +.. date: 2023-05-09-18-46-24 +.. gh-issue: 104301 +.. nonce: gNnbId +.. section: Library + +Allow leading whitespace in disambiguated statements in :mod:`pdb`. + +.. + +.. date: 2023-05-08-23-01-59 +.. gh-issue: 104139 +.. nonce: 83Tnt- +.. section: Library + +Teach :func:`urllib.parse.unsplit` to retain the ``"//"`` when assembling +``itms-services://?action=generate-bugs`` style `Apple Platform Deployment +`_ URLs. + +.. + +.. date: 2023-05-08-20-57-17 +.. gh-issue: 104307 +.. nonce: DSB93G +.. section: Library + +:func:`socket.getnameinfo` now releases the GIL while contacting the DNS +server + +.. + +.. date: 2023-05-08-15-50-59 +.. gh-issue: 104310 +.. nonce: fXVSPY +.. section: Library + +Users may now use ``importlib.util.allowing_all_extensions()`` (a context +manager) to temporarily disable the strict compatibility checks for +importing extension modules in subinterpreters. + +.. + +.. date: 2023-05-08-15-39-00 +.. gh-issue: 87695 +.. nonce: f6iO7v +.. section: Library + +Fix issue where :meth:`pathlib.Path.glob` raised :exc:`OSError` when it +encountered a symlink to an overly long path. + +.. + +.. date: 2023-05-07-19-56-45 +.. gh-issue: 104265 +.. nonce: fVblry +.. section: Library + +Prevent possible crash by disallowing instantiation of the +:class:`!_csv.Reader` and :class:`!_csv.Writer` types. The regression was +introduced in 3.10.0a4 with PR 23224 (:issue:`14935`). Patch by Radislav +Chugunov. + +.. + +.. date: 2023-05-06-20-37-46 +.. gh-issue: 102613 +.. nonce: QZG9iX +.. section: Library + +Improve performance of :meth:`pathlib.Path.glob` when expanding recursive +wildcards ("``**``") by merging adjacent wildcards and de-duplicating +results only when necessary. + +.. + +.. date: 2023-05-05-18-52-22 +.. gh-issue: 65772 +.. nonce: w5P5Wv +.. section: Library + +Remove unneeded comments and code in turtle.py. + +.. + +.. date: 2023-05-03-19-22-24 +.. gh-issue: 90208 +.. nonce: tI00da +.. section: Library + +Fixed issue where :meth:`pathlib.Path.glob` returned incomplete results when +it encountered a :exc:`PermissionError`. This method now suppresses all +:exc:`OSError` exceptions, except those raised from calling +:meth:`~pathlib.Path.is_dir` on the top-level path. + +.. + +.. date: 2023-05-03-16-51-53 +.. gh-issue: 104144 +.. nonce: 653Q0P +.. section: Library + +Optimize :class:`asyncio.TaskGroup` when using +:func:`asyncio.eager_task_factory`. Skip scheduling a done callback if a +TaskGroup task completes eagerly. + +.. + +.. date: 2023-05-03-16-50-24 +.. gh-issue: 104144 +.. nonce: yNkjL8 +.. section: Library + +Optimize :func:`asyncio.gather` when using +:func:`asyncio.eager_task_factory` to complete eagerly if all fututres +completed eagerly. Avoid scheduling done callbacks for futures that complete +eagerly. + +.. + +.. date: 2023-05-03-03-14-33 +.. gh-issue: 104114 +.. nonce: RG26RD +.. section: Library + +Fix issue where :meth:`pathlib.Path.glob` returns paths using the case of +non-wildcard segments for corresponding path segments, rather than the real +filesystem case. + +.. + +.. date: 2023-05-02-21-05-30 +.. gh-issue: 104104 +.. nonce: 9tjplT +.. section: Library + +Improve performance of :meth:`pathlib.Path.glob` by using +:data:`re.IGNORECASE` to implement case-insensitive matching. + +.. + +.. date: 2023-05-02-20-43-03 +.. gh-issue: 104102 +.. nonce: vgSdEJ +.. section: Library + +Improve performance of :meth:`pathlib.Path.glob` when evaluating patterns +that contain ``'../'`` segments. + +.. + +.. date: 2023-05-02-04-49-45 +.. gh-issue: 103822 +.. nonce: m0QdAO +.. section: Library + +Update the return type of ``weekday`` to the newly added Day attribute + +.. + +.. date: 2023-05-01-19-10-05 +.. gh-issue: 103629 +.. nonce: 81bpZz +.. section: Library + +Update the ``repr`` of :class:`typing.Unpack` according to :pep:`692`. + +.. + +.. date: 2023-05-01-17-58-28 +.. gh-issue: 103963 +.. nonce: XWlHx7 +.. section: Library + +Make :mod:`dis` display the names of the args for +:opcode:`CALL_INTRINSIC_*`. + +.. + +.. date: 2023-05-01-16-43-28 +.. gh-issue: 104035 +.. nonce: MrJBw8 +.. section: Library + +Do not ignore user-defined ``__getstate__`` and ``__setstate__`` methods for +slotted frozen dataclasses. + +.. + +.. date: 2023-04-29-18-23-16 +.. gh-issue: 103987 +.. nonce: sRgALL +.. section: Library + +In :mod:`mmap`, fix several bugs that could lead to access to memory-mapped +files after they have been invalidated. + +.. + +.. date: 2023-04-28-19-08-50 +.. gh-issue: 103977 +.. nonce: msF70A +.. section: Library + +Improve import time of :mod:`platform` module. + +.. + +.. date: 2023-04-28-18-04-23 +.. gh-issue: 88773 +.. nonce: xXCNJw +.. section: Library + +Added :func:`turtle.teleport` to the :mod:`turtle` module to move a turtle +to a new point without tracing a line, visible or invisible. Patch by Liam +Gersten. + +.. + +.. date: 2023-04-27-20-03-08 +.. gh-issue: 103935 +.. nonce: Uaf2M0 +.. section: Library + +Use :func:`io.open_code` for files to be executed instead of raw +:func:`open` + +.. + +.. date: 2023-04-27-18-46-31 +.. gh-issue: 68968 +.. nonce: E3tnhy +.. section: Library + +Fixed garbled output of :meth:`~unittest.TestCase.assertEqual` when an input +lacks final newline. + +.. + +.. date: 2023-04-27-00-45-41 +.. gh-issue: 100370 +.. nonce: MgZ3KY +.. section: Library + +Fix potential :exc:`OverflowError` in :meth:`sqlite3.Connection.blobopen` +for 32-bit builds. Patch by Erlend E. Aasland. + +.. + +.. date: 2023-04-27-00-05-32 +.. gh-issue: 102628 +.. nonce: X230E- +.. section: Library + +Substitute CTRL-D with CTRL-Z in :mod:`sqlite3` CLI banner when running on +Windows. + +.. + +.. date: 2023-04-26-18-12-13 +.. gh-issue: 103636 +.. nonce: -KvCgO +.. section: Library + +Module-level attributes ``January`` and ``February`` are deprecated from +:mod:`calendar`. + +.. + +.. date: 2023-04-26-15-14-36 +.. gh-issue: 103583 +.. nonce: iCMDFt +.. section: Library + +Isolate :mod:`!_multibytecodec` and codecs extension modules. Patches by +Erlend E. Aasland. + +.. + +.. date: 2023-04-26-09-54-25 +.. gh-issue: 103848 +.. nonce: aDSnpR +.. section: Library + +Add checks to ensure that ``[`` bracketed ``]`` hosts found by +:func:`urllib.parse.urlsplit` are of IPv6 or IPvFuture format. + +.. + +.. date: 2023-04-26-09-38-47 +.. gh-issue: 103872 +.. nonce: 8LBsDz +.. section: Library + +Update the bundled copy of pip to version 23.1.2. + +.. + +.. date: 2023-04-25-22-59-06 +.. gh-issue: 99944 +.. nonce: pst8iT +.. section: Library + +Make :mod:`dis` display the value of oparg of :opcode:`KW_NAMES`. + +.. + +.. date: 2023-04-25-22-06-00 +.. gh-issue: 74940 +.. nonce: TOacQ9 +.. section: Library + +The C.UTF-8 locale is no longer converted to en_US.UTF-8, enabling the use +of UTF-8 encoding on systems which have no locales installed. + +.. + +.. date: 2023-04-25-19-58-13 +.. gh-issue: 103861 +.. nonce: JeozgD +.. section: Library + +Fix ``zipfile.Zipfile`` creating invalid zip files when ``force_zip64`` was +used to add files to them. Patch by Carey Metcalfe. + +.. + +.. date: 2023-04-25-17-03-18 +.. gh-issue: 103857 +.. nonce: Mr2Cak +.. section: Library + +Deprecated :meth:`datetime.datetime.utcnow` and +:meth:`datetime.datetime.utcfromtimestamp`. (Patch by Paul Ganssle) + +.. + +.. date: 2023-04-25-16-31-00 +.. gh-issue: 103839 +.. nonce: tpyLhI +.. section: Library + +Avoid compilation error due to tommath.h not being found when building +Tkinter against Tcl 8.7 built with bundled libtommath. + +.. + +.. date: 2023-04-24-23-07-56 +.. gh-issue: 103791 +.. nonce: bBPWdS +.. section: Library + +:class:`contextlib.suppress` now supports suppressing exceptions raised as +part of an :exc:`ExceptionGroup`. If other exceptions exist on the group, +they are re-raised in a group that does not contain the suppressed +exceptions. + +.. + +.. date: 2023-04-24-16-00-28 +.. gh-issue: 90750 +.. nonce: da0Xi8 +.. section: Library + +Use :meth:`datetime.datetime.fromisocalendar` in the implementation of +:meth:`datetime.datetime.strptime`, which should now accept only valid ISO +dates. (Patch by Paul Ganssle) + +.. + +.. date: 2023-04-24-00-34-23 +.. gh-issue: 103685 +.. nonce: U14jBM +.. section: Library + +Prepare :meth:`tkinter.Menu.index` for Tk 8.7 so that it does not raise +``TclError: expected integer but got ""`` when it should return ``None``. + +.. + +.. date: 2023-04-23-15-39-17 +.. gh-issue: 81403 +.. nonce: zVz9Td +.. section: Library + +:class:`urllib.request.CacheFTPHandler` no longer raises :class:`URLError` +if a cached FTP instance is reused. ftplib's endtransfer method calls +voidresp to drain the connection to handle FTP instance reuse properly. + +.. + +.. date: 2023-04-22-22-37-39 +.. gh-issue: 103699 +.. nonce: NizCjc +.. section: Library + +Add ``__orig_bases__`` to non-generic TypedDicts, call-based TypedDicts, and +call-based NamedTuples. Other TypedDicts and NamedTuples already had the +attribute. + +.. + +.. date: 2023-04-22-21-34-13 +.. gh-issue: 103693 +.. nonce: SBtuLQ +.. section: Library + +Add convenience variable feature to :mod:`pdb` + +.. + +.. date: 2023-04-22-12-30-10 +.. gh-issue: 92248 +.. nonce: NcVTKR +.. section: Library + +Deprecate ``type``, ``choices``, and ``metavar`` parameters of +``argparse.BooleanOptionalAction``. + +.. + +.. date: 2023-04-22-11-20-27 +.. gh-issue: 89415 +.. nonce: YHk760 +.. section: Library + +Add :mod:`socket` constants for source-specific multicast. Patch by Reese +Hyde. + +.. + +.. date: 2023-04-22-02-41-06 +.. gh-issue: 103673 +.. nonce: oE7S_k +.. section: Library + +:mod:`socketserver` gains ``ForkingUnixStreamServer`` and +``ForkingUnixDatagramServer`` classes. Patch by Jay Berry. + +.. + +.. date: 2023-04-21-10-25-39 +.. gh-issue: 103636 +.. nonce: YK6NEa +.. section: Library + +Added Enum for months and days in the calendar module. + +.. + +.. date: 2023-04-19-16-08-53 +.. gh-issue: 84976 +.. nonce: HwbzlD +.. section: Library + +Create a new ``Lib/_pydatetime.py`` file that defines the Python version of +the ``datetime`` module, and make ``datetime`` import the contents of the +new library only if the C implementation is missing. Currently, the full +Python implementation is defined and then deleted if the C implementation is +not available, slowing down ``import datetime`` unnecessarily. + +.. + +.. date: 2023-04-17-14-47-28 +.. gh-issue: 103596 +.. nonce: ME1y3_ +.. section: Library + +Attributes/methods are no longer shadowed by same-named enum members, +although they may be shadowed by enum.property's. + +.. + +.. date: 2023-04-16-19-48-21 +.. gh-issue: 103584 +.. nonce: 3mBTuM +.. section: Library + +Updated ``importlib.metadata`` with changes from ``importlib_metadata`` 5.2 +through 6.5.0, including: Support ``installed-files.txt`` for +``Distribution.files`` when present. ``PackageMetadata`` now stipulates an +additional ``get`` method allowing for easy querying of metadata keys that +may not be present. ``packages_distributions`` now honors packages and +modules with Python modules that not ``.py`` sources (e.g. ``.pyc``, +``.so``). Expand protocol for ``PackageMetadata.get_all`` to match the +upstream implementation of ``email.message.Message.get_all`` in +python/typeshed#9620. Deprecated use of ``Distribution`` without defining +abstract methods. Deprecated expectation that +``PackageMetadata.__getitem__`` will return ``None`` for missing keys. In +the future, it will raise a ``KeyError``. + +.. + +.. date: 2023-04-16-18-29-04 +.. gh-issue: 103578 +.. nonce: fly1wc +.. section: Library + +Fixed a bug where :mod:`pdb` crashes when reading source file with different +encoding by replacing :func:`io.open` with :func:`io.open_code`. The new +method would also call into the hook set by :func:`PyFile_SetOpenCodeHook`. + +.. + +.. date: 2023-04-15-12-19-14 +.. gh-issue: 103556 +.. nonce: TEf-2m +.. section: Library + +Now creating :class:`inspect.Signature` objects with positional-only +parameter with a default followed by a positional-or-keyword parameter +without one is impossible. + +.. + +.. date: 2023-04-15-11-21-38 +.. gh-issue: 103559 +.. nonce: a9rYHG +.. section: Library + +Update the bundled copy of pip to version 23.1.1. + +.. + +.. date: 2023-04-14-21-16-05 +.. gh-issue: 103548 +.. nonce: lagdpp +.. section: Library + +Improve performance of :meth:`pathlib.Path.absolute` and +:meth:`~pathlib.Path.cwd` by joining paths only when necessary. Also improve +performance of :meth:`pathlib.PurePath.is_absolute` on Posix by skipping +path parsing and normalization. + +.. + +.. date: 2023-04-14-21-12-32 +.. gh-issue: 103538 +.. nonce: M4FK_v +.. section: Library + +Remove ``_tkinter`` module code guarded by definition of the ``TK_AQUA`` +macro which was only needed for Tk 8.4.7 or earlier and was never actually +defined by any build system or documented for manual use. + +.. + +.. date: 2023-04-14-06-32-54 +.. gh-issue: 103533 +.. nonce: n_AfcS +.. section: Library + +Update :mod:`cProfile` to use PEP 669 API + +.. + +.. date: 2023-04-13-19-43-15 +.. gh-issue: 103525 +.. nonce: uY4VYg +.. section: Library + +Fix misleading exception message when mixed ``str`` and ``bytes`` arguments +are supplied to :class:`pathlib.PurePath` and :class:`~pathlib.Path`. + +.. + +.. date: 2023-04-13-13-17-47 +.. gh-issue: 103489 +.. nonce: ZSZgmu +.. section: Library + +Add :meth:`~sqlite3.Connection.getconfig` and +:meth:`~sqlite3.Connection.setconfig` to :class:`~sqlite3.Connection` to +make configuration changes to a database connection. Patch by Erlend E. +Aasland. + +.. + +.. date: 2023-04-12-17-59-55 +.. gh-issue: 103365 +.. nonce: UBEE0U +.. section: Library + +Set default Flag boundary to ``STRICT`` and fix bitwise operations. + +.. + +.. date: 2023-04-12-13-04-16 +.. gh-issue: 103472 +.. nonce: C6bOHv +.. section: Library + +Avoid a potential :exc:`ResourceWarning` in +:class:`http.client.HTTPConnection` by closing the proxy / tunnel's CONNECT +response explicitly. + +.. + +.. date: 2023-04-12-06-00-02 +.. gh-issue: 103462 +.. nonce: w6yBlM +.. section: Library + +Fixed an issue with using :meth:`~asyncio.WriteTransport.writelines` in +:mod:`asyncio` to send very large payloads that exceed the amount of data +that can be written in one call to :meth:`socket.socket.send` or +:meth:`socket.socket.sendmsg`, resulting in the remaining buffer being left +unwritten. + +.. + +.. date: 2023-04-11-21-38-39 +.. gh-issue: 103449 +.. nonce: -nxmhb +.. section: Library + +Fix a bug in doc string generation in :func:`dataclasses.dataclass`. + +.. + +.. date: 2023-04-09-06-59-36 +.. gh-issue: 103092 +.. nonce: vskbro +.. section: Library + +Isolate :mod:`!_collections` (apply :pep:`687`). Patch by Erlend E. Aasland. + +.. + +.. date: 2023-04-08-01-33-12 +.. gh-issue: 103357 +.. nonce: vjin28 +.. section: Library + +Added support for :class:`logging.Formatter` ``defaults`` parameter to +:func:`logging.config.dictConfig` and :func:`logging.config.fileConfig`. +Patch by Bar Harel. + +.. + +.. date: 2023-04-08-00-48-40 +.. gh-issue: 103092 +.. nonce: 5EFts0 +.. section: Library + +Adapt the :mod:`winreg` extension module to :pep:`687`. + +.. + +.. date: 2023-04-07-15-15-40 +.. gh-issue: 74690 +.. nonce: un84hh +.. section: Library + +The performance of :func:`isinstance` checks against +:func:`runtime-checkable protocols ` has been +considerably improved for protocols that only have a few members. To achieve +this improvement, several internal implementation details of the +:mod:`typing` module have been refactored, including +``typing._ProtocolMeta.__instancecheck__``, +``typing._is_callable_members_only``, and ``typing._get_protocol_attrs``. +Patches by Alex Waygood. + +.. + +.. date: 2023-04-07-15-09-26 +.. gh-issue: 74690 +.. nonce: 0f886b +.. section: Library + +The members of a runtime-checkable protocol are now considered "frozen" at +runtime as soon as the class has been created. See :ref:`"What's new in +Python 3.12" ` for more details. + +.. + +.. date: 2023-04-06-17-28-36 +.. gh-issue: 103256 +.. nonce: 1syxfs +.. section: Library + +Fixed a bug that caused :mod:`hmac` to raise an exception when the requested +hash algorithm was not available in OpenSSL despite being available +separately as part of ``hashlib`` itself. It now falls back properly to the +built-in. This could happen when, for example, your OpenSSL does not include +SHA3 support and you want to compute ``hmac.digest(b'K', b'M', +'sha3_256')``. + +.. + +.. date: 2023-04-06-16-55-51 +.. gh-issue: 102778 +.. nonce: BWeAmE +.. section: Library + +Support ``sys.last_exc`` in :mod:`idlelib`. + +.. + +.. date: 2023-04-06-04-35-59 +.. gh-issue: 103285 +.. nonce: rCZ9-G +.. section: Library + +Improve performance of :func:`ast.get_source_segment`. + +.. + +.. date: 2023-04-05-01-28-53 +.. gh-issue: 103225 +.. nonce: QD3JVU +.. section: Library + +Fix a bug in :mod:`pdb` when displaying line numbers of module-level source +code. + +.. + +.. date: 2023-04-04-21-44-25 +.. gh-issue: 103092 +.. nonce: Dz0_Xn +.. section: Library + +Adapt the :mod:`msvcrt` extension module to :pep:`687`. + +.. + +.. date: 2023-04-04-21-27-51 +.. gh-issue: 103092 +.. nonce: 7s7Bzf +.. section: Library + +Adapt the :mod:`winsound` extension module to :pep:`687`. + +.. + +.. date: 2023-04-04-12-43-38 +.. gh-issue: 93910 +.. nonce: jurMzv +.. section: Library + +Remove deprecation of enum ``memmber.member`` access. + +.. + +.. date: 2023-04-03-23-44-34 +.. gh-issue: 102978 +.. nonce: gy9eVk +.. section: Library + +Fixes :func:`unittest.mock.patch` not enforcing function signatures for +methods decorated with ``@classmethod`` or ``@staticmethod`` when patch is +called with ``autospec=True``. + +.. + +.. date: 2023-04-03-23-43-12 +.. gh-issue: 103092 +.. nonce: 3xqk4y +.. section: Library + +Isolate :mod:`!_socket` (apply :pep:`687`). Patch by Erlend E. Aasland. + +.. + +.. date: 2023-04-03-22-02-35 +.. gh-issue: 100479 +.. nonce: kNBjQm +.. section: Library + +Add :meth:`pathlib.PurePath.with_segments`, which creates a path object from +arguments. This method is called whenever a derivative path is created, such +as from :attr:`pathlib.PurePath.parent`. Subclasses may override this method +to share information between path objects. + +.. + +.. date: 2023-04-03-21-08-53 +.. gh-issue: 103220 +.. nonce: OW_Bj5 +.. section: Library + +Fix issue where :func:`os.path.join` added a slash when joining onto an +incomplete UNC drive with a trailing slash on Windows. + +.. + +.. date: 2023-04-02-23-05-22 +.. gh-issue: 103204 +.. nonce: bbDmu0 +.. section: Library + +Fixes :mod:`http.server` accepting HTTP requests with HTTP version numbers +preceded by '+', or '-', or with digit-separating '_' characters. The +length of the version numbers is also constrained. + +.. + +.. date: 2023-04-02-22-04-26 +.. gh-issue: 75586 +.. nonce: 526iJm +.. section: Library + +Fix various Windows-specific issues with ``shutil.which``. + +.. + +.. date: 2023-04-02-17-51-08 +.. gh-issue: 103193 +.. nonce: xrZbM1 +.. section: Library + +Improve performance of :func:`inspect.getattr_static`. Patch by Alex +Waygood. + +.. + +.. date: 2023-04-01-23-01-31 +.. gh-issue: 103176 +.. nonce: FBsdxa +.. section: Library + +:func:`sys._current_exceptions` now returns a mapping from thread-id to an +exception instance, rather than to a ``(typ, exc, tb)`` tuple. + +.. + +.. date: 2023-03-31-01-13-00 +.. gh-issue: 103143 +.. nonce: 6eMluy +.. section: Library + +Polish the help messages and docstrings of :mod:`pdb`. + +.. + +.. date: 2023-03-28-09-13-31 +.. gh-issue: 103015 +.. nonce: ETTfNf +.. section: Library + +Add *entrypoint* keyword-only parameter to +:meth:`sqlite3.Connection.load_extension`, for overriding the SQLite +extension entry point. Patch by Erlend E. Aasland. + +.. + +.. date: 2023-03-24-20-49-48 +.. gh-issue: 103000 +.. nonce: 6eVNZI +.. section: Library + +Improve performance of :func:`dataclasses.astuple` and +:func:`dataclasses.asdict` in cases where the contents are common Python +types. + +.. + +.. date: 2023-03-23-15-24-38 +.. gh-issue: 102953 +.. nonce: YR4KaK +.. section: Library + +The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`, +have a new a *filter* argument that allows limiting tar features than may be +surprising or dangerous, such as creating files outside the destination +directory. See :ref:`tarfile-extraction-filter` for details. + +.. + +.. date: 2023-03-15-12-18-07 +.. gh-issue: 97696 +.. nonce: DtnpIC +.. section: Library + +Implemented an eager task factory in asyncio. When used as a task factory on +an event loop, it performs eager execution of coroutines. Coroutines that +are able to complete synchronously (e.g. return or raise without blocking) +are returned immediately as a finished task, and the task is never scheduled +to the event loop. If the coroutine blocks, the (pending) task is scheduled +and returned. + +.. + +.. date: 2023-03-15-00-37-43 +.. gh-issue: 81079 +.. nonce: heTAod +.. section: Library + +Add *case_sensitive* keyword-only argument to :meth:`pathlib.Path.glob` and +:meth:`~pathlib.Path.rglob`. + +.. + +.. date: 2023-03-14-11-20-19 +.. gh-issue: 101819 +.. nonce: 0-h0it +.. section: Library + +Isolate the :mod:`io` extension module by applying :pep:`687`. Patch by +Kumar Aditya, Victor Stinner, and Erlend E. Aasland. + +.. + +.. date: 2023-03-08-02-45-46 +.. gh-issue: 91896 +.. nonce: kgON_a +.. section: Library + +Deprecate :class:`collections.abc.ByteString` + +.. + +.. date: 2023-03-06-18-49-57 +.. gh-issue: 101362 +.. nonce: eSSy6L +.. section: Library + +Speed up :class:`pathlib.Path` construction by omitting the path anchor from +the internal list of path parts. + +.. + +.. date: 2023-02-21-14-57-34 +.. gh-issue: 102114 +.. nonce: uUDQzb +.. section: Library + +Functions in the :mod:`dis` module that accept a source code string as +argument now print a more concise traceback when the string contains a +syntax or indentation error. + +.. + +.. date: 2023-02-19-12-37-08 +.. gh-issue: 62432 +.. nonce: GnBFIB +.. section: Library + +The :mod:`unittest` runner will now exit with status code 5 if no tests were +run. It is common for test runner misconfiguration to fail to find any +tests, this should be an error. + +.. + +.. date: 2023-02-17-21-14-40 +.. gh-issue: 78079 +.. nonce: z3Szr6 +.. section: Library + +Fix incorrect normalization of UNC device path roots, and partial UNC share +path roots, in :class:`pathlib.PurePath`. Pathlib no longer appends a +trailing slash to such paths. + +.. + +.. date: 2023-02-11-21-18-10 +.. gh-issue: 85984 +.. nonce: nvzOD0 +.. section: Library + +Add :func:`tty.cfmakeraw` and :func:`tty.cfmakecbreak` to :mod:`tty` and +modernize, the behavior of :func:`tty.setraw` and :func:`tty.setcbreak` to +use POSIX.1-2017 Chapter 11 "General Terminal Interface" flag masks by +default. + +.. + +.. date: 2023-02-11-15-01-32 +.. gh-issue: 101688 +.. nonce: kwXmfM +.. section: Library + +Implement :func:`types.get_original_bases` to provide further introspection +for types. + +.. + +.. date: 2023-02-09-22-24-34 +.. gh-issue: 101640 +.. nonce: oFuEpB +.. section: Library + +:class:`argparse.ArgumentParser` now catches errors when writing messages, +such as when :data:`sys.stderr` is ``None``. Patch by Oleg Iarygin. + +.. + +.. date: 2023-02-06-16-45-18 +.. gh-issue: 83861 +.. nonce: mMbIU3 +.. section: Library + +Fix datetime.astimezone method return value when invoked on a naive datetime +instance that represents local time falling in a timezone transition gap. +PEP 495 requires that instances with fold=1 produce earlier times than those +with fold=0 in this case. + +.. + +.. date: 2023-01-22-14-53-12 +.. gh-issue: 89550 +.. nonce: c1U23f +.. section: Library + +Decrease execution time of some :mod:`gzip` file writes by 15% by adding +more appropriate buffering. + +.. + +.. date: 2023-01-14-17-54-56 +.. gh-issue: 95299 +.. nonce: vUhpKz +.. section: Library + +Remove the bundled setuptools wheel from ``ensurepip``, and stop installing +setuptools in environments created by ``venv``. + +.. + +.. date: 2022-11-10-16-26-47 +.. gh-issue: 99353 +.. nonce: DQFjnt +.. section: Library + +Respect the :class:`http.client.HTTPConnection` ``.debuglevel`` flag in +:class:`urllib.request.AbstractHTTPHandler` when its constructor parameter +``debuglevel`` is not set. And do the same for ``*HTTPS*``. + +.. + +.. date: 2022-10-21-17-20-57 +.. gh-issue: 98040 +.. nonce: 3btbmA +.. section: Library + +Remove the long-deprecated ``imp`` module. + +.. + +.. date: 2022-10-21-16-23-31 +.. gh-issue: 97850 +.. nonce: N46coo +.. section: Library + +Deprecate :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader` in +favor of :func:`importlib.util.find_spec`. + +.. + +.. date: 2022-10-20-14-03-58 +.. gh-issue: 94473 +.. nonce: pzGX73 +.. section: Library + +Flatten arguments in :meth:`tkinter.Canvas.coords`. It now accepts not only +``x1, y1, x2, y2, ...`` and ``[x1, y1, x2, y2, ...]``, but also ``(x1, y1), +(x2, y2), ...`` and ``[(x1, y1), (x2, y2), ...]``. + +.. + +.. date: 2022-10-09-14-47-42 +.. gh-issue: 98040 +.. nonce: IN3qab +.. section: Library + +Remove more deprecated importlib APIs: ``find_loader()``, ``find_module()``, +``importlib.abc.Finder``, ``pkgutil.ImpImporter``, ``pkgutil.ImpLoader``. + +.. + +.. date: 2022-09-07-09-32-07 +.. gh-issue: 96522 +.. nonce: t73oqp +.. section: Library + +Fix potential deadlock in pty.spawn() + +.. + +.. date: 2022-09-03-09-24-02 +.. gh-issue: 96534 +.. nonce: EU4Oxv +.. section: Library + +Support divert(4) added in FreeBSD 14. + +.. + +.. date: 2022-08-27-21-41-41 +.. gh-issue: 87474 +.. nonce: 9X-kxt +.. section: Library + +Fix potential file descriptor leaks in :class:`subprocess.Popen`. + +.. + +.. date: 2022-07-16-17-15-29 +.. gh-issue: 94906 +.. nonce: C4G8DG +.. section: Library + +Support multiple steps in :func:`math.nextafter`. Patch by Shantanu Jain and +Matthias Gorgens. + +.. + +.. date: 2022-07-06-11-10-37 +.. gh-issue: 51574 +.. nonce: sveUeD +.. section: Library + +Make :func:`tempfile.mkdtemp` return absolute paths when its *dir* parameter +is relative. + +.. + +.. date: 2022-07-03-23-13-28 +.. gh-issue: 94518 +.. nonce: 511Tbh +.. section: Library + +Convert private :meth:`_posixsubprocess.fork_exec` to use Argument Clinic. + +.. + +.. date: 2022-05-02-16-21-05 +.. gh-issue: 92184 +.. nonce: hneGVW +.. section: Library + +When creating zip files using :mod:`zipfile`, ``os.altsep``, if not +``None``, will always be treated as a path separator even when it is not +``/``. Patch by Carey Metcalfe. + +.. + +.. bpo: 46797 +.. date: 2022-02-19-14-19-34 +.. nonce: 6BXZX4 +.. section: Library + +Deprecation warnings are now emitted for :class:`!ast.Num`, +:class:`!ast.Bytes`, :class:`!ast.Str`, :class:`!ast.NameConstant` and +:class:`!ast.Ellipsis`. These have been documented as deprecated since +Python 3.8, and will be removed in Python 3.14. + +.. + +.. bpo: 44844 +.. date: 2021-12-03-23-00-56 +.. nonce: tvg2VY +.. section: Library + +Enables :mod:`webbrowser` to detect and launch Microsoft Edge browser. + +.. + +.. bpo: 45606 +.. date: 2021-11-19-23-37-18 +.. nonce: UW5XE1 +.. section: Library + +Fixed the bug in :meth:`pathlib.Path.glob` -- previously a dangling symlink +would not be found by this method when the pattern is an exact match, but +would be found when the pattern contains a wildcard or the recursive +wildcard (``**``). With this change, a dangling symlink will be found in +both cases. + +.. + +.. bpo: 23041 +.. date: 2021-11-07-15-31-25 +.. nonce: 564i32 +.. section: Library + +Add :data:`~csv.QUOTE_STRINGS` and :data:`~csv.QUOTE_NOTNULL` to the suite +of :mod:`csv` module quoting styles. + +.. + +.. bpo: 24964 +.. date: 2021-05-16-14-28-30 +.. nonce: Oa5Ie_ +.. section: Library + +Added :meth:`http.client.HTTPConnection.get_proxy_response_headers` that +provides access to the HTTP headers on a proxy server response to the +``CONNECT`` request. + +.. + +.. bpo: 17258 +.. date: 2020-05-25-12-42-36 +.. nonce: lf2554 +.. section: Library + +:mod:`multiprocessing` now supports stronger HMAC algorithms for +inter-process connection authentication rather than only HMAC-MD5. + +.. + +.. bpo: 39744 +.. date: 2020-02-25-00-43-22 +.. nonce: hgK689 +.. section: Library + +Make :func:`asyncio.subprocess.Process.communicate` close the subprocess's +stdin even when called with ``input=None``. + +.. + +.. bpo: 22708 +.. date: 2018-07-16-14-10-29 +.. nonce: 592iRR +.. section: Library + +http.client CONNECT method tunnel improvements: Use HTTP 1.1 protocol; send +a matching Host: header with CONNECT, if one is not provided; convert IDN +domain names to Punycode. Patch by Michael Handler. + +.. + +.. date: 2023-05-14-12-11-28 +.. gh-issue: 67056 +.. nonce: nVC2Rf +.. section: Documentation + +Document that the effect of registering or unregistering an :mod:`atexit` +cleanup function from within a registered cleanup function is undefined. + +.. + +.. date: 2023-04-26-23-55-31 +.. gh-issue: 103629 +.. nonce: -0reqn +.. section: Documentation + +Mention the new way of typing ``**kwargs`` with ``Unpack`` and ``TypedDict`` +introduced in :pep:`692`. + +.. + +.. date: 2023-04-25-22-58-08 +.. gh-issue: 48241 +.. nonce: l1Gxxh +.. section: Documentation + +Clarifying documentation about the url parameter to urllib.request.urlopen +and urllib.request.Requst needing to be encoded properly. + +.. + +.. date: 2023-03-10-04-59-35 +.. gh-issue: 86094 +.. nonce: zOYdy8 +.. section: Documentation + +Add support for Unicode Path Extra Field in ZipFile. Patch by Yeojin Kim and +Andrea Giudiceandrea + +.. + +.. date: 2023-03-07-23-30-29 +.. gh-issue: 99202 +.. nonce: hhiAJF +.. section: Documentation + +Fix extension type from documentation for compiling in C++20 mode + +.. + +.. date: 2023-05-15-02-22-44 +.. gh-issue: 104494 +.. nonce: Bkrbfn +.. section: Tests + +Update ``test_pack_configure_in`` and ``test_place_configure_in`` for +changes to error message formatting in Tk 8.7. + +.. + +.. date: 2023-05-14-03-00-00 +.. gh-issue: 104461 +.. nonce: Rmex11 +.. section: Tests + +Run test_configure_screen on X11 only, since the ``DISPLAY`` environment +variable and ``-screen`` option for toplevels are not useful on Tk for Win32 +or Aqua. + +.. + +.. date: 2023-04-25-12-19-37 +.. gh-issue: 86275 +.. nonce: -RoLIt +.. section: Tests + +Added property-based tests to the :mod:`zoneinfo` tests, along with stubs +for the ``hypothesis`` interface. (Patch by Paul Ganssle) + +.. + +.. date: 2023-04-08-00-50-23 +.. gh-issue: 103329 +.. nonce: M38tqF +.. section: Tests + +Regression tests for the behaviour of ``unittest.mock.PropertyMock`` were +added. + +.. + +.. date: 2023-03-17-22-00-47 +.. gh-issue: 102795 +.. nonce: z21EoC +.. section: Tests + +fix use of poll in test_epoll's test_control_and_wait + +.. + +.. date: 2022-11-06-18-42-38 +.. gh-issue: 75729 +.. nonce: uGYJrv +.. section: Tests + +Fix the :func:`os.spawn* ` tests failing on Windows when the +working directory or interpreter path contains spaces. + +.. + +.. date: 2023-05-20-16-09-59 +.. gh-issue: 101282 +.. nonce: FvRARb +.. section: Build + +BOLT optimization is now applied to the libpython shared library if building +a shared library. BOLT instrumentation and application settings can now be +influenced via the ``BOLT_INSTRUMENT_FLAGS`` and ``BOLT_APPLY_FLAGS`` +configure variables. + +.. + +.. date: 2023-05-15-09-34-08 +.. gh-issue: 99017 +.. nonce: nToOQu +.. section: Build + +``PYTHON_FOR_REGEN`` now require Python 3.10 or newer. + +.. + +.. date: 2023-05-14-19-00-19 +.. gh-issue: 104490 +.. nonce: 1tA4AF +.. section: Build + +Define ``.PHONY`` / virtual make targets consistently and properly. + +.. + +.. date: 2023-05-04-10-56-14 +.. gh-issue: 104106 +.. nonce: -W9BJS +.. section: Build + +Add gcc fallback of mkfifoat/mknodat for macOS. Patch by Dong-hee Na. + +.. + +.. date: 2023-04-14-10-24-37 +.. gh-issue: 103532 +.. nonce: H1djkd +.. section: Build + +The ``TKINTER_PROTECT_LOADTK`` macro is no longer defined or used in the +``_tkinter`` module. It was previously only defined when building against +Tk 8.4.13 and older, but Tk older than 8.5.12 has been unsupported since +gh-issue-91152. + +.. + +.. date: 2023-02-11-05-31-05 +.. gh-issue: 99069 +.. nonce: X4LDvY +.. section: Build + +Extended workaround defining ``static_assert`` when missing from the libc +headers to all clang and gcc builds. In particular, this fixes building on +macOS <= 10.10. + +.. + +.. date: 2022-12-18-07-24-44 +.. gh-issue: 100220 +.. nonce: BgSV7C +.. section: Build + +Changed the default value of the ``SHELL`` Makefile variable from +``/bin/sh`` to ``/bin/sh -e`` to ensure that complex recipes correctly fail +after an error. Previously, ``make install`` could fail to install some +files and yet return a successful result. + +.. + +.. date: 2022-06-20-15-15-11 +.. gh-issue: 90656 +.. nonce: kFBbKe +.. section: Build + +Add platform triplets for 64-bit LoongArch: + +* loongarch64-linux-gnusf +* loongarch64-linux-gnuf32 +* loongarch64-linux-gnu + +Patch by Zhang Na. + +.. + +.. date: 2023-05-18-22-46-03 +.. gh-issue: 104623 +.. nonce: HJZhm1 +.. section: Windows + +Update Windows installer to use SQLite 3.42.0. + +.. + +.. date: 2023-04-24-15-51-11 +.. gh-issue: 82814 +.. nonce: GI3UkZ +.. section: Windows + +Fix a potential ``[Errno 13] Permission denied`` when using +:func:`shutil.copystat` within Windows Subsystem for Linux (WSL) on a +mounted filesystem by adding ``errno.EACCES`` to the list of ignored errors +within the internal implementation. + +.. + +.. date: 2023-04-12-10-49-21 +.. gh-issue: 103088 +.. nonce: Yjj-qJ +.. section: Windows + +Fix virtual environment :file:`activate` script having incorrect line +endings for Cygwin. + +.. + +.. date: 2023-04-11-09-22-22 +.. gh-issue: 103088 +.. nonce: 6AJEuR +.. section: Windows + +Fixes venvs not working in bash on Windows across different disks + +.. + +.. date: 2023-03-24-11-25-28 +.. gh-issue: 102997 +.. nonce: dredy2 +.. section: Windows + +Update Windows installer to use SQLite 3.41.2. + +.. + +.. date: 2023-03-18-21-38-00 +.. gh-issue: 88013 +.. nonce: Z3loxC +.. section: Windows + +Fixed a bug where :exc:`TypeError` was raised when calling +:func:`ntpath.realpath` with a bytes parameter in some cases. + +.. + +.. date: 2023-05-21-23-54-52 +.. gh-issue: 99834 +.. nonce: 6ANPts +.. section: macOS + +Update macOS installer to Tcl/Tk 8.6.13. + +.. + +.. date: 2023-05-18-22-31-49 +.. gh-issue: 104623 +.. nonce: 6h7Xfx +.. section: macOS + +Update macOS installer to SQLite 3.42.0. + +.. + +.. date: 2023-05-18-08-52-04 +.. gh-issue: 103545 +.. nonce: pi5k2N +.. section: macOS + +Add ``os.PRIO_DARWIN_THREAD``, ``os.PRIO_DARWIN_PROCESS``, +``os.PRIO_DARWIN_BG`` and ``os.PRIO_DARWIN_NONUI``. These can be used with +``os.setpriority`` to run the process at a lower priority and make use of +the efficiency cores on Apple Silicon systems. + +.. + +.. date: 2023-05-04-21-47-59 +.. gh-issue: 104180 +.. nonce: lEJCwd +.. section: macOS + +Support reading SOCKS proxy configuration from macOS System Configuration. +Patch by Sam Schott. + +.. + +.. date: 2023-04-24-18-37-48 +.. gh-issue: 60436 +.. nonce: in-IyF +.. section: macOS + +update curses textbox to additionally handle backspace using the +``curses.ascii.DEL`` key press. + +.. + +.. date: 2023-04-04-13-37-28 +.. gh-issue: 103207 +.. nonce: x0vvQp +.. section: macOS + +Add instructions to the macOS installer welcome display on how to workaround +the macOS 13 Ventura “The installer encountered an error” failure. + +.. + +.. date: 2023-03-24-11-20-47 +.. gh-issue: 102997 +.. nonce: ZgQkbq +.. section: macOS + +Update macOS installer to SQLite 3.41.2. + +.. + +.. date: 2023-05-17-17-32-21 +.. gh-issue: 104499 +.. nonce: hNeqV4 +.. section: IDLE + +Fix completions for Tk Aqua 8.7 (currently blank). + +.. + +.. date: 2023-05-17-15-11-11 +.. gh-issue: 104496 +.. nonce: wjav-y +.. section: IDLE + +About prints both tcl and tk versions if different (expected someday). + +.. + +.. date: 2023-04-30-20-01-18 +.. gh-issue: 88496 +.. nonce: y65vUb +.. section: IDLE + +Fix IDLE test hang on macOS. + +.. + +.. date: 2023-05-11-15-12-11 +.. gh-issue: 104389 +.. nonce: EiOhB3 +.. section: Tools/Demos + +Argument Clinic C converters now accept the ``unused`` keyword, for wrapping +a parameter with :c:macro:`Py_UNUSED`. Patch by Erlend E. Aasland. + +.. + +.. date: 2023-05-18-20-53-05 +.. gh-issue: 101291 +.. nonce: ZBh9aR +.. section: C API + +Added unstable C API for extracting the value of "compact" integers: +:c:func:`PyUnstable_Long_IsCompact` and +:c:func:`PyUnstable_Long_CompactValue`. + +.. + +.. date: 2023-05-02-21-05-54 +.. gh-issue: 104109 +.. nonce: 0tnDZV +.. section: C API + +We've added ``Py_NewInterpreterFromConfig()`` and ``PyInterpreterConfig`` to +the public C-API (but not the stable ABI; not yet at least). The new +function may be used to create a new interpreter with various features +configured. The function was added to support PEP 684 (per-interpreter +GIL). + +.. + +.. date: 2023-04-28-18-04-38 +.. gh-issue: 103968 +.. nonce: EnVvOx +.. section: C API + +:c:func:`PyType_FromSpec` and its variants now allow creating classes whose +metaclass overrides :c:member:`~PyTypeObject.tp_new`. The ``tp_new`` is +ignored. This behavior is deprecated and will be disallowed in 3.14+. The +new :c:func:`PyType_FromMetaclass` already disallows it. + +.. + +.. date: 2023-04-24-10-31-59 +.. gh-issue: 103743 +.. nonce: 2xYA1K +.. section: C API + +Add :c:func:`PyUnstable_Object_GC_NewWithExtraData` function that can be +used to allocate additional memory after an object for data not managed by +Python. + +.. + +.. date: 2023-04-14-23-05-52 +.. gh-issue: 103295 +.. nonce: GRHY1Z +.. section: C API + +Introduced :c:func:`PyUnstable_WritePerfMapEntry`, +:c:func:`PyUnstable_PerfMapState_Init` and +:c:func:`PyUnstable_PerfMapState_Fini`. These allow extension modules (JIT +compilers in particular) to write to perf-map files in a thread safe manner. +The :doc:`../howto/perf_profiling` also uses these APIs to write entries in +the perf-map file. + +.. + +.. date: 2023-04-13-16-54-00 +.. gh-issue: 103509 +.. nonce: A26Qu8 +.. section: C API + +Added C API for extending types whose instance memory layout is opaque: +:c:member:`PyType_Spec.basicsize` can now be zero or negative, +:c:func:`PyObject_GetTypeData` can be used to get subclass-specific data, +and :c:macro:`Py_TPFLAGS_ITEMS_AT_END` can be used to safely extend +variable-size objects. See :pep:`697` for details. + +.. + +.. date: 2023-03-28-12-31-51 +.. gh-issue: 103091 +.. nonce: CzZyaZ +.. section: C API + +Add a new C-API function to eagerly assign a version tag to a PyTypeObject: +``PyUnstable_Type_AssignVersionTag()``. + +.. + +.. date: 2023-02-09-23-09-29 +.. gh-issue: 101408 +.. nonce: _paFIF +.. section: C API + +:c:func:`PyObject_GC_Resize` should calculate preheader size if needed. +Patch by Dong-hee Na. + +.. + +.. date: 2022-10-29-10-13-20 +.. gh-issue: 98836 +.. nonce: Cy5h_z +.. section: C API + +Add support of more formatting options (left aligning, octals, uppercase +hexadecimals, :c:expr:`intmax_t`, :c:expr:`ptrdiff_t`, :c:expr:`wchar_t` C +strings, variable width and precision) in :c:func:`PyUnicode_FromFormat` and +:c:func:`PyUnicode_FromFormatV`. + +.. + +.. date: 2022-09-15-15-21-34 +.. gh-issue: 96803 +.. nonce: ynBKIS +.. section: C API + +Add unstable C-API functions to get the code object, lasti and line number +from the internal ``_PyInterpreterFrame`` in the limited API. The functions +are: + +* ``PyCodeObject * PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)`` +* ``int PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)`` +* ``int PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame)`` diff --git a/Misc/NEWS.d/3.8.0a1.rst b/Misc/NEWS.d/3.8.0a1.rst index 854458f2d1a994..2564167cdf0895 100644 --- a/Misc/NEWS.d/3.8.0a1.rst +++ b/Misc/NEWS.d/3.8.0a1.rst @@ -2747,7 +2747,7 @@ smaller file). Also, change the default compression level to 6 (tradeoff). .. nonce: xo5LAr .. section: Library -The :term:`2to3` :2to3fixer:`execfile` fixer now opens the file with mode +The 2to3 ``execfile`` fixer now opens the file with mode ``'rb'``. Patch by Zackery Spytz. .. @@ -3817,7 +3817,7 @@ user. .. nonce: w6g7tn .. section: Library -The :2to3fixer:`reload` fixer now uses :func:`importlib.reload` instead of +The ``reload`` fixer now uses :func:`importlib.reload` instead of deprecated :func:`!imp.reload`. .. diff --git a/Misc/NEWS.d/3.9.0a1.rst b/Misc/NEWS.d/3.9.0a1.rst index 0888a5c43087b5..7da4385973185a 100644 --- a/Misc/NEWS.d/3.9.0a1.rst +++ b/Misc/NEWS.d/3.9.0a1.rst @@ -99,7 +99,7 @@ after whitespace, e.g. '127.0.0.1 whatever'. Adds audit events for :mod:`ensurepip`, :mod:`ftplib`, :mod:`glob`, :mod:`imaplib`, :mod:`nntplib`, :mod:`pdb`, :mod:`poplib`, :mod:`shutil`, -:mod:`smtplib`, :mod:`sqlite3`, :mod:`subprocess`, :mod:`telnetlib`, +:mod:`smtplib`, :mod:`sqlite3`, :mod:`subprocess`, :mod:`!telnetlib`, :mod:`tempfile` and :mod:`webbrowser`, as well as :func:`os.listdir`, :func:`os.scandir` and :func:`breakpoint`. diff --git a/Misc/NEWS.d/3.9.0a3.rst b/Misc/NEWS.d/3.9.0a3.rst index 54b61ca3b7785f..b05b4c3d7204c0 100644 --- a/Misc/NEWS.d/3.9.0a3.rst +++ b/Misc/NEWS.d/3.9.0a3.rst @@ -571,7 +571,7 @@ new task spawning before exception raising. .. section: Library Correctly parenthesize filter-based statements that contain lambda -expressions in mod:`lib2to3`. Patch by Dong-hee Na. +expressions in mod:`!lib2to3`. Patch by Dong-hee Na. .. diff --git a/Misc/NEWS.d/3.9.0a6.rst b/Misc/NEWS.d/3.9.0a6.rst index af2cc7c3e97889..9594964917f390 100644 --- a/Misc/NEWS.d/3.9.0a6.rst +++ b/Misc/NEWS.d/3.9.0a6.rst @@ -343,7 +343,7 @@ https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242274 .. nonce: Er8sv- .. section: Library -The :mod:`lib2to3` module is pending deprecation due to :pep:`617`. +The :mod:`!lib2to3` module is pending deprecation due to :pep:`617`. .. diff --git a/Misc/NEWS.d/next/Build/2022-06-20-15-15-11.gh-issue-90656.kFBbKe.rst b/Misc/NEWS.d/next/Build/2022-06-20-15-15-11.gh-issue-90656.kFBbKe.rst deleted file mode 100644 index dfe71a5552070d..00000000000000 --- a/Misc/NEWS.d/next/Build/2022-06-20-15-15-11.gh-issue-90656.kFBbKe.rst +++ /dev/null @@ -1,7 +0,0 @@ -Add platform triplets for 64-bit LoongArch: - -* loongarch64-linux-gnusf -* loongarch64-linux-gnuf32 -* loongarch64-linux-gnu - -Patch by Zhang Na. diff --git a/Misc/NEWS.d/next/Build/2022-12-18-07-24-44.gh-issue-100220.BgSV7C.rst b/Misc/NEWS.d/next/Build/2022-12-18-07-24-44.gh-issue-100220.BgSV7C.rst deleted file mode 100644 index 7135317cd06fa2..00000000000000 --- a/Misc/NEWS.d/next/Build/2022-12-18-07-24-44.gh-issue-100220.BgSV7C.rst +++ /dev/null @@ -1,4 +0,0 @@ -Changed the default value of the ``SHELL`` Makefile variable from ``/bin/sh`` -to ``/bin/sh -e`` to ensure that complex recipes correctly fail after an error. -Previously, ``make install`` could fail to install some files and yet return -a successful result. diff --git a/Misc/NEWS.d/next/Build/2023-02-11-05-31-05.gh-issue-99069.X4LDvY.rst b/Misc/NEWS.d/next/Build/2023-02-11-05-31-05.gh-issue-99069.X4LDvY.rst deleted file mode 100644 index ae9b4d59ca8cec..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-02-11-05-31-05.gh-issue-99069.X4LDvY.rst +++ /dev/null @@ -1 +0,0 @@ -Extended workaround defining ``static_assert`` when missing from the libc headers to all clang and gcc builds. In particular, this fixes building on macOS <= 10.10. diff --git a/Misc/NEWS.d/next/Build/2023-04-14-10-24-37.gh-issue-103532.H1djkd.rst b/Misc/NEWS.d/next/Build/2023-04-14-10-24-37.gh-issue-103532.H1djkd.rst deleted file mode 100644 index 255c9833282c2f..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-04-14-10-24-37.gh-issue-103532.H1djkd.rst +++ /dev/null @@ -1,4 +0,0 @@ -The ``TKINTER_PROTECT_LOADTK`` macro is no longer defined or used in the -``_tkinter`` module. It was previously only defined when building against -Tk 8.4.13 and older, but Tk older than 8.5.12 has been unsupported since -gh-issue-91152. diff --git a/Misc/NEWS.d/next/Build/2023-05-04-10-56-14.gh-issue-104106.-W9BJS.rst b/Misc/NEWS.d/next/Build/2023-05-04-10-56-14.gh-issue-104106.-W9BJS.rst deleted file mode 100644 index 900e5bd61d6033..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-05-04-10-56-14.gh-issue-104106.-W9BJS.rst +++ /dev/null @@ -1 +0,0 @@ -Add gcc fallback of mkfifoat/mknodat for macOS. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Build/2023-05-14-19-00-19.gh-issue-104490.1tA4AF.rst b/Misc/NEWS.d/next/Build/2023-05-14-19-00-19.gh-issue-104490.1tA4AF.rst deleted file mode 100644 index 1315b5cb3c1969..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-05-14-19-00-19.gh-issue-104490.1tA4AF.rst +++ /dev/null @@ -1 +0,0 @@ -Define ``.PHONY`` / virtual make targets consistently and properly. diff --git a/Misc/NEWS.d/next/Build/2023-05-15-09-34-08.gh-issue-99017.nToOQu.rst b/Misc/NEWS.d/next/Build/2023-05-15-09-34-08.gh-issue-99017.nToOQu.rst deleted file mode 100644 index a3517ac0204b1d..00000000000000 --- a/Misc/NEWS.d/next/Build/2023-05-15-09-34-08.gh-issue-99017.nToOQu.rst +++ /dev/null @@ -1 +0,0 @@ -``PYTHON_FOR_REGEN`` now require Python 3.10 or newer. diff --git a/Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst b/Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst deleted file mode 100644 index 6fc56d2249f581..00000000000000 --- a/Misc/NEWS.d/next/C API/2022-09-15-15-21-34.gh-issue-96803.ynBKIS.rst +++ /dev/null @@ -1,6 +0,0 @@ -Add unstable C-API functions to get the code object, lasti and line number from -the internal ``_PyInterpreterFrame`` in the limited API. The functions are: - -* ``PyCodeObject * PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)`` -* ``int PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)`` -* ``int PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame)`` diff --git a/Misc/NEWS.d/next/C API/2023-02-09-23-09-29.gh-issue-101408._paFIF.rst b/Misc/NEWS.d/next/C API/2023-02-09-23-09-29.gh-issue-101408._paFIF.rst deleted file mode 100644 index 172d66163d42e6..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-02-09-23-09-29.gh-issue-101408._paFIF.rst +++ /dev/null @@ -1,2 +0,0 @@ -:c:func:`PyObject_GC_Resize` should calculate preheader size if needed. -Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/C API/2023-03-28-12-31-51.gh-issue-103091.CzZyaZ.rst b/Misc/NEWS.d/next/C API/2023-03-28-12-31-51.gh-issue-103091.CzZyaZ.rst deleted file mode 100644 index 28c77b6816af87..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-03-28-12-31-51.gh-issue-103091.CzZyaZ.rst +++ /dev/null @@ -1 +0,0 @@ -Add a new C-API function to eagerly assign a version tag to a PyTypeObject: ``PyUnstable_Type_AssignVersionTag()``. diff --git a/Misc/NEWS.d/next/C API/2023-04-13-16-54-00.gh-issue-103509.A26Qu8.rst b/Misc/NEWS.d/next/C API/2023-04-13-16-54-00.gh-issue-103509.A26Qu8.rst deleted file mode 100644 index af630c3aafa940..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-04-13-16-54-00.gh-issue-103509.A26Qu8.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added C API for extending types whose instance memory layout is opaque: -:c:member:`PyType_Spec.basicsize` can now be zero or negative, -:c:func:`PyObject_GetTypeData` can be used to get subclass-specific data, -and :c:macro:`Py_TPFLAGS_ITEMS_AT_END` can be used to safely extend -variable-size objects. See :pep:`697` for details. diff --git a/Misc/NEWS.d/next/C API/2023-04-24-10-31-59.gh-issue-103743.2xYA1K.rst b/Misc/NEWS.d/next/C API/2023-04-24-10-31-59.gh-issue-103743.2xYA1K.rst deleted file mode 100644 index d074350ed3ebbe..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-04-24-10-31-59.gh-issue-103743.2xYA1K.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :c:func:`PyUnstable_Object_GC_NewWithExtraData` function that can be used to -allocate additional memory after an object for data not managed by Python. diff --git a/Misc/NEWS.d/next/C API/2023-04-28-18-04-38.gh-issue-103968.EnVvOx.rst b/Misc/NEWS.d/next/C API/2023-04-28-18-04-38.gh-issue-103968.EnVvOx.rst deleted file mode 100644 index 5e4270f82afd84..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-04-28-18-04-38.gh-issue-103968.EnVvOx.rst +++ /dev/null @@ -1,4 +0,0 @@ -:c:func:`PyType_FromSpec` and its variants now allow creating classes whose -metaclass overrides :c:member:`~PyTypeObject.tp_new`. The ``tp_new`` is -ignored. This behavior is deprecated and will be disallowed in 3.14+. The -new :c:func:`PyType_FromMetaclass` already disallows it. diff --git a/Misc/NEWS.d/next/C API/2023-05-02-21-05-54.gh-issue-104109.0tnDZV.rst b/Misc/NEWS.d/next/C API/2023-05-02-21-05-54.gh-issue-104109.0tnDZV.rst deleted file mode 100644 index 2ffc0fa81c014a..00000000000000 --- a/Misc/NEWS.d/next/C API/2023-05-02-21-05-54.gh-issue-104109.0tnDZV.rst +++ /dev/null @@ -1,5 +0,0 @@ -We've added ``Py_NewInterpreterFromConfig()`` and ``PyInterpreterConfig`` to -the public C-API (but not the stable ABI; not yet at least). The new -function may be used to create a new interpreter with various features -configured. The function was added to support PEP 684 (per-interpreter -GIL). diff --git a/Misc/NEWS.d/next/C API/2023-05-19-10-22-34.gh-issue-104668.MLX1g9.rst b/Misc/NEWS.d/next/C API/2023-05-19-10-22-34.gh-issue-104668.MLX1g9.rst new file mode 100644 index 00000000000000..7b882afd7f81a0 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-05-19-10-22-34.gh-issue-104668.MLX1g9.rst @@ -0,0 +1,5 @@ +Don't call :c:var:`PyOS_InputHook` or :c:var:`PyOS_ReadlineFunctionPointer` +in subinterpreters, since it's generally difficult to avoid using global +state in their registered callbacks. This also avoids situations where +extensions may find themselves running in a subinterpreter they don't +support (or haven't yet been loaded in). diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst deleted file mode 100644 index 13c054fdd68276..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-12-01-12-58-31.bpo-31821.1FNmwk.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :func:`!pause_reading` to work when called from :func:`!connection_made` in :mod:`asyncio`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-11-15-54-40.bpo-39610.fvgsCl.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-11-15-54-40.bpo-39610.fvgsCl.rst deleted file mode 100644 index d65e0f3db9d6f5..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-02-11-15-54-40.bpo-39610.fvgsCl.rst +++ /dev/null @@ -1,2 +0,0 @@ -``len()`` for 0-dimensional :class:`memoryview`` objects (such as ``memoryview(ctypes.c_uint8(42))``) now raises a :exc:`TypeError`. -Previously this returned ``1``, which was not consistent with ``mem_0d[0]`` raising an :exc:`IndexError``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-10-06-23-32-11.gh-issue-98003.xWE0Yu.rst b/Misc/NEWS.d/next/Core and Builtins/2022-10-06-23-32-11.gh-issue-98003.xWE0Yu.rst deleted file mode 100644 index f9e71bc1344bb3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2022-10-06-23-32-11.gh-issue-98003.xWE0Yu.rst +++ /dev/null @@ -1,3 +0,0 @@ -Complex function calls are now faster and consume no C stack -space. - diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-08-12-36-25.gh-issue-99184.KIaqzz.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-08-12-36-25.gh-issue-99184.KIaqzz.rst deleted file mode 100644 index 80076831badfea..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2022-11-08-12-36-25.gh-issue-99184.KIaqzz.rst +++ /dev/null @@ -1,2 +0,0 @@ -Bypass instance attribute access of ``__name__`` in ``repr`` of -:class:`weakref.ref`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-15-40-29.gh-issue-97933.nUlp3r.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-30-15-40-29.gh-issue-97933.nUlp3r.rst deleted file mode 100644 index 2eec05cb3ace5c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-15-40-29.gh-issue-97933.nUlp3r.rst +++ /dev/null @@ -1,2 +0,0 @@ -:pep:`709`: inline list, dict and set comprehensions to improve performance -and reduce bytecode size. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-03-07-17-37-00.gh-issue-102500.RUSQhz.rst b/Misc/NEWS.d/next/Core and Builtins/2023-03-07-17-37-00.gh-issue-102500.RUSQhz.rst deleted file mode 100644 index e03113ba05cd7d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-03-07-17-37-00.gh-issue-102500.RUSQhz.rst +++ /dev/null @@ -1,3 +0,0 @@ -Make the buffer protocol accessible in Python code using the new -``__buffer__`` and ``__release_buffer__`` magic methods. See :pep:`688` for -details. Patch by Jelle Zijlstra. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-03-25-23-24-38.gh-issue-88691.2SWBd1.rst b/Misc/NEWS.d/next/Core and Builtins/2023-03-25-23-24-38.gh-issue-88691.2SWBd1.rst deleted file mode 100644 index 761d45b0a3a84f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-03-25-23-24-38.gh-issue-88691.2SWBd1.rst +++ /dev/null @@ -1 +0,0 @@ -Reduce the number of inline :opcode:`CACHE` entries for :opcode:`CALL`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-03-31-17-24-03.gh-issue-103082.isRUcV.rst b/Misc/NEWS.d/next/Core and Builtins/2023-03-31-17-24-03.gh-issue-103082.isRUcV.rst deleted file mode 100644 index 631ef4c7890450..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-03-31-17-24-03.gh-issue-103082.isRUcV.rst +++ /dev/null @@ -1 +0,0 @@ -Implement :pep:`669` Low Impact Monitoring for CPython. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-01-00-46-31.gh-issue-102700.493NB4.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-01-00-46-31.gh-issue-102700.493NB4.rst deleted file mode 100644 index 46951486e4f9c9..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-01-00-46-31.gh-issue-102700.493NB4.rst +++ /dev/null @@ -1 +0,0 @@ -Allow built-in modules to be submodules. This allows submodules to be statically linked into a CPython binary. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-02-22-14-57.gh-issue-84436.hvMgwF.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-02-22-14-57.gh-issue-84436.hvMgwF.rst deleted file mode 100644 index c4d8ce75b35a30..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-02-22-14-57.gh-issue-84436.hvMgwF.rst +++ /dev/null @@ -1,3 +0,0 @@ -The implementation of PEP-683 which adds Immortal Objects by using a fixed -reference count that skips reference counting to make objects truly -immutable. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-07-12-18-41.gh-issue-103323.9802br.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-07-12-18-41.gh-issue-103323.9802br.rst deleted file mode 100644 index 347c91d973e5ce..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-07-12-18-41.gh-issue-103323.9802br.rst +++ /dev/null @@ -1,3 +0,0 @@ -We've replaced our use of ``_PyRuntime.tstate_current`` with a thread-local -variable. This is a fairly low-level implementation detail, and there -should be no change in behavior. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-08-17-13-07.gh-issue-103242.ysI1b3.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-08-17-13-07.gh-issue-103242.ysI1b3.rst deleted file mode 100644 index 38b107f3be174f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-08-17-13-07.gh-issue-103242.ysI1b3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Migrate :meth:`~ssl.SSLContext.set_ecdh_curve` method not to use deprecated -OpenSSL APIs. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-09-04-30-02.gh-issue-103333.gKOetS.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-09-04-30-02.gh-issue-103333.gKOetS.rst deleted file mode 100644 index 793f02c2afdcff..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-09-04-30-02.gh-issue-103333.gKOetS.rst +++ /dev/null @@ -1 +0,0 @@ -:exc:`AttributeError` now retains the ``name`` attribute when pickled and unpickled. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-09-22-21-57.gh-issue-77757._Ow-u2.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-09-22-21-57.gh-issue-77757._Ow-u2.rst deleted file mode 100644 index 85c8ecf7de8d1b..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-09-22-21-57.gh-issue-77757._Ow-u2.rst +++ /dev/null @@ -1,3 +0,0 @@ -Exceptions raised in a typeobject's ``__set_name__`` method are no longer -wrapped by a :exc:`RuntimeError`. Context information is added to the -exception as a :pep:`678` note. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-12-19-55-24.gh-issue-82012.FlcJAh.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-12-19-55-24.gh-issue-82012.FlcJAh.rst deleted file mode 100644 index 819a2359bf6fae..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-12-19-55-24.gh-issue-82012.FlcJAh.rst +++ /dev/null @@ -1,5 +0,0 @@ -The bitwise inversion operator (``~``) on bool is deprecated. -It returns the bitwise inversion of the underlying ``int`` representation such that -``bool(~True) == True``, which can be confusing. Use ``not`` for logical negation -of bools. In the rare case that you really need the bitwise inversion of the underlying ``int``, -convert to int explicitly ``~int(x)``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-12-20-18-51.gh-issue-103488.vYvlHD.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-12-20-18-51.gh-issue-103488.vYvlHD.rst deleted file mode 100644 index e7daa104e57105..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-12-20-18-51.gh-issue-103488.vYvlHD.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change the internal offset distinguishing yield and return target addresses, -so that the instruction pointer is correct for exception handling and other -stack unwinding. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-12-20-22-03.gh-issue-87729.99A7UO.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-12-20-22-03.gh-issue-87729.99A7UO.rst deleted file mode 100644 index 9d75de1565a170..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-12-20-22-03.gh-issue-87729.99A7UO.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add :opcode:`LOAD_SUPER_ATTR` (and a specialization for ``super().method()``) to -speed up ``super().method()`` and ``super().attr``. This makes -``super().method()`` roughly 2.3x faster and brings it within 20% of the -performance of a simple method call. Patch by Vladimir Matveev and Carl Meyer. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-13-00-58-55.gh-issue-103492.P4k0Ay.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-13-00-58-55.gh-issue-103492.P4k0Ay.rst deleted file mode 100644 index 929650968173e7..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-13-00-58-55.gh-issue-103492.P4k0Ay.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify :exc:`SyntaxWarning` with literal ``is`` comparison by specifying which literal is problematic, since comparisons using ``is`` with e.g. None and bool literals are idiomatic. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-14-22-35-23.gh-issue-101517.5EqM-S.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-14-22-35-23.gh-issue-101517.5EqM-S.rst deleted file mode 100644 index 730c6cd40d7235..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-14-22-35-23.gh-issue-101517.5EqM-S.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug in line numbers of instructions emitted for :keyword:`except* `. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-16-14-38-39.gh-issue-100530.OR6-sn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-16-14-38-39.gh-issue-100530.OR6-sn.rst deleted file mode 100644 index 5b1bcc4a680fc3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-16-14-38-39.gh-issue-100530.OR6-sn.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify the error message raised when the called part of a class pattern isn't actually a class. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-17-16-00-32.gh-issue-102856.UunJ7y.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-17-16-00-32.gh-issue-102856.UunJ7y.rst deleted file mode 100644 index 35eceb83816bcb..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-17-16-00-32.gh-issue-102856.UunJ7y.rst +++ /dev/null @@ -1 +0,0 @@ -Implement the required C tokenizer changes for PEP 701. Patch by Pablo Galindo Salgado, Lysandros Nikolaou, Batuhan Taskaya, Marta Gómez Macías and sunmy2019. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-20-16-17-51.gh-issue-103650.K1MFXR.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-20-16-17-51.gh-issue-103650.K1MFXR.rst deleted file mode 100644 index 5434660e9d6ffb..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-20-16-17-51.gh-issue-103650.K1MFXR.rst +++ /dev/null @@ -1 +0,0 @@ -Change the perf map format to remove the '0x' prefix from the addresses diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-21-16-12-41.gh-issue-103590.7DHDOE.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-21-16-12-41.gh-issue-103590.7DHDOE.rst deleted file mode 100644 index af733a8207a2c1..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-21-16-12-41.gh-issue-103590.7DHDOE.rst +++ /dev/null @@ -1 +0,0 @@ -Do not wrap a single exception raised from a ``try-except*`` construct in an :exc:`ExceptionGroup`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-21-17-03-14.gh-issue-102310.anLjDx.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-21-17-03-14.gh-issue-102310.anLjDx.rst deleted file mode 100644 index 15cb6c64adbab1..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-21-17-03-14.gh-issue-102310.anLjDx.rst +++ /dev/null @@ -1 +0,0 @@ -Change the error range for invalid bytes literals. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-24-14-38-16.gh-issue-103793.kqoH6Q.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-24-14-38-16.gh-issue-103793.kqoH6Q.rst deleted file mode 100644 index c48348798e7142..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-24-14-38-16.gh-issue-103793.kqoH6Q.rst +++ /dev/null @@ -1,3 +0,0 @@ -Optimized asyncio Task creation by deferring expensive string formatting -(task name generation) from Task creation to the first time ``get_name`` is -called. This makes asyncio benchmarks up to 5% faster. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-24-21-47-38.gh-issue-103801.WaBanq.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-24-21-47-38.gh-issue-103801.WaBanq.rst deleted file mode 100644 index 6f07d72fafdfc3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-24-21-47-38.gh-issue-103801.WaBanq.rst +++ /dev/null @@ -1 +0,0 @@ -Adds three minor linting fixes to the wasm module caught that were caught by ruff. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-25-20-56-01.gh-issue-103845.V7NYFn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-25-20-56-01.gh-issue-103845.V7NYFn.rst deleted file mode 100644 index e8434854cde632..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-25-20-56-01.gh-issue-103845.V7NYFn.rst +++ /dev/null @@ -1 +0,0 @@ -Remove both line and instruction instrumentation before adding new ones for monitoring, to avoid newly added instrumentation being removed immediately. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-26-15-14-23.gh-issue-103899.1pqKPF.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-26-15-14-23.gh-issue-103899.1pqKPF.rst deleted file mode 100644 index c12a6b9cb841f2..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-26-15-14-23.gh-issue-103899.1pqKPF.rst +++ /dev/null @@ -1,3 +0,0 @@ -Provide a helpful hint in the :exc:`TypeError` message when accidentally -calling a :term:`module` object that has a callable attribute of the same -name (such as :func:`dis.dis` or :class:`datetime.datetime`). diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-26-17-56-18.gh-issue-103895.ESB6tn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-26-17-56-18.gh-issue-103895.ESB6tn.rst deleted file mode 100644 index 6fed304c9132b3..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-04-26-17-56-18.gh-issue-103895.ESB6tn.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improve handling of edge cases in showing ``Exception.__notes__``. Ensures -that the messages always end with a newline and that string/bytes are not -exploded over multiple lines. Patch by Carey Metcalfe. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-08-08-05.gh-issue-102213.nfH-4C.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-01-08-08-05.gh-issue-102213.nfH-4C.rst deleted file mode 100644 index 997bef226e713f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-08-08-05.gh-issue-102213.nfH-4C.rst +++ /dev/null @@ -1 +0,0 @@ -Fix performance loss when accessing an object's attributes with ``__getattr__`` defined. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-12-03-52.gh-issue-104018.PFxGS4.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-01-12-03-52.gh-issue-104018.PFxGS4.rst deleted file mode 100644 index f3cadaee0e32d9..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-12-03-52.gh-issue-104018.PFxGS4.rst +++ /dev/null @@ -1 +0,0 @@ -Disallow the "z" format specifier in %-format of bytes objects. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-14-10-38.gh-issue-104028.dxfh13.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-01-14-10-38.gh-issue-104028.dxfh13.rst deleted file mode 100644 index 9c35ea88499dce..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-14-10-38.gh-issue-104028.dxfh13.rst +++ /dev/null @@ -1,2 +0,0 @@ -Reduce object creation while calling callback function from gc. -Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-14-48-29.gh-issue-104066.pzoUZQ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-01-14-48-29.gh-issue-104066.pzoUZQ.rst deleted file mode 100644 index 97e0c01689cb6f..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-14-48-29.gh-issue-104066.pzoUZQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve the performance of :func:`hasattr` for module objects with a missing -attribute. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-21-05-47.gh-issue-104078.vRaBsU.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-01-21-05-47.gh-issue-104078.vRaBsU.rst deleted file mode 100644 index 6f24529bac3e0c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-01-21-05-47.gh-issue-104078.vRaBsU.rst +++ /dev/null @@ -1 +0,0 @@ -Improve the performance of :c:func:`PyObject_HasAttrString` diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst deleted file mode 100644 index 6a19ae84057f4c..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-02-18-29-49.gh-issue-104142._5Et6I.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue where :class:`list` or :class:`tuple` repetition could fail to -respect :pep:`683`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-03-17-46-47.gh-issue-104108.GOxAYt.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-03-17-46-47.gh-issue-104108.GOxAYt.rst deleted file mode 100644 index dad843636493ae..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-03-17-46-47.gh-issue-104108.GOxAYt.rst +++ /dev/null @@ -1,6 +0,0 @@ -Multi-phase init extension modules may now indicate whether or not they -actually support multiple interpreters. By default such modules are -expected to support use in multiple interpreters. In the uncommon case that -one does not, it may use the new ``Py_mod_multiple_interpreters`` module def -slot. A value of ``0`` means the module does not support them. ``1`` means -it does. The default is ``1``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-05-12-14-47.gh-issue-99113.-RAdnv.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-05-12-14-47.gh-issue-99113.-RAdnv.rst deleted file mode 100644 index 42e26cb27b6e01..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-05-12-14-47.gh-issue-99113.-RAdnv.rst +++ /dev/null @@ -1,6 +0,0 @@ -The GIL is now (optionally) per-interpreter. This is the fundamental change -for PEP 684. This is all made possible by virtue of the isolated state of -each interpreter in the process. The behavior of the main interpreter -remains unchanged. Likewise, interpreters created using -``Py_NewInterpreter()`` are not affected. To get an interpreter with its -own GIL, call ``Py_NewInterpreterFromConfig()``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-05-13-18-56.gh-issue-99113.hT1ajK.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-05-13-18-56.gh-issue-99113.hT1ajK.rst deleted file mode 100644 index afd26750846167..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-05-13-18-56.gh-issue-99113.hT1ajK.rst +++ /dev/null @@ -1,11 +0,0 @@ -Multi-phase init extension modules may now indicate that they support -running in subinterpreters that have their own GIL. This is done by using -``Py_MOD_PER_INTERPRETER_GIL_SUPPORTED`` as the value for the -``Py_mod_multiple_interpreters`` module def slot. Otherwise the module, by -default, cannot be imported in such subinterpreters. (This does not affect -the main interpreter or subinterpreters that do not have their own GIL.) In -addition to the isolation that multi-phase init already normally requires, -support for per-interpreter GIL involves one additional constraint: -thread-safety. If the module has external (linked) dependencies and those -libraries have any state that isn't thread-safe then the module must do the -additional work to add thread-safety. This should be an uncommon case. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-08-10-34-55.gh-issue-104263.ctHWI8.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-08-10-34-55.gh-issue-104263.ctHWI8.rst deleted file mode 100644 index 342467cfcd4e75..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-08-10-34-55.gh-issue-104263.ctHWI8.rst +++ /dev/null @@ -1,6 +0,0 @@ -Fix ``float("nan")`` to produce a quiet NaN on platforms (like MIPS) where -the meaning of the signalling / quiet bit is inverted from its usual -meaning. Also introduce a new macro ``Py_INFINITY`` matching C99's -``INFINITY``, and refactor internals to rely on C99's ``NAN`` and -``INFINITY`` macros instead of hard-coding bit patterns for infinities and -NaNs. Thanks Sebastian Berg. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-10-20-52-29.gh-issue-103082.y3LG5Q.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-10-20-52-29.gh-issue-103082.y3LG5Q.rst deleted file mode 100644 index 40eee64dfa717d..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-10-20-52-29.gh-issue-103082.y3LG5Q.rst +++ /dev/null @@ -1,5 +0,0 @@ -Change behavior of ``sys.monitoring.events.LINE`` events in -``sys.monitoring``: Line events now occur when a new line is reached -dynamically, instead of using a static approximation, as before. This makes -the behavior very similar to that of "line" events in ``sys.settrace``. This -should ease porting of tools from 3.11 to 3.12. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-11-15-56-07.gh-issue-104405.tXV5fn.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-11-15-56-07.gh-issue-104405.tXV5fn.rst deleted file mode 100644 index 06ec5d7b0f0cc9..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-05-11-15-56-07.gh-issue-104405.tXV5fn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix an issue where some :term:`bytecode` instructions could ignore -:pep:`523` when "inlining" calls. diff --git a/Misc/NEWS.d/next/Documentation/2023-03-07-23-30-29.gh-issue-99202.hhiAJF.rst b/Misc/NEWS.d/next/Documentation/2023-03-07-23-30-29.gh-issue-99202.hhiAJF.rst deleted file mode 100644 index 1569e815ee50fa..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-03-07-23-30-29.gh-issue-99202.hhiAJF.rst +++ /dev/null @@ -1 +0,0 @@ -Fix extension type from documentation for compiling in C++20 mode diff --git a/Misc/NEWS.d/next/Documentation/2023-03-10-04-59-35.gh-issue-86094.zOYdy8.rst b/Misc/NEWS.d/next/Documentation/2023-03-10-04-59-35.gh-issue-86094.zOYdy8.rst deleted file mode 100644 index 39461f3f84c9ac..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-03-10-04-59-35.gh-issue-86094.zOYdy8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add support for Unicode Path Extra Field in ZipFile. Patch by Yeojin Kim -and Andrea Giudiceandrea diff --git a/Misc/NEWS.d/next/Documentation/2023-04-25-22-58-08.gh-issue-48241.l1Gxxh.rst b/Misc/NEWS.d/next/Documentation/2023-04-25-22-58-08.gh-issue-48241.l1Gxxh.rst deleted file mode 100644 index 619505cf6ee5b8..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-04-25-22-58-08.gh-issue-48241.l1Gxxh.rst +++ /dev/null @@ -1 +0,0 @@ -Clarifying documentation about the url parameter to urllib.request.urlopen and urllib.request.Requst needing to be encoded properly. diff --git a/Misc/NEWS.d/next/Documentation/2023-04-26-23-55-31.gh-issue-103629.-0reqn.rst b/Misc/NEWS.d/next/Documentation/2023-04-26-23-55-31.gh-issue-103629.-0reqn.rst deleted file mode 100644 index 6dc0a1cb5a3e4f..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-04-26-23-55-31.gh-issue-103629.-0reqn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Mention the new way of typing ``**kwargs`` with ``Unpack`` and ``TypedDict`` -introduced in :pep:`692`. diff --git a/Misc/NEWS.d/next/Documentation/2023-05-14-12-11-28.gh-issue-67056.nVC2Rf.rst b/Misc/NEWS.d/next/Documentation/2023-05-14-12-11-28.gh-issue-67056.nVC2Rf.rst deleted file mode 100644 index 2c6ef17810723d..00000000000000 --- a/Misc/NEWS.d/next/Documentation/2023-05-14-12-11-28.gh-issue-67056.nVC2Rf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document that the effect of registering or unregistering an :mod:`atexit` -cleanup function from within a registered cleanup function is undefined. diff --git a/Misc/NEWS.d/next/IDLE/2023-04-30-20-01-18.gh-issue-88496.y65vUb.rst b/Misc/NEWS.d/next/IDLE/2023-04-30-20-01-18.gh-issue-88496.y65vUb.rst deleted file mode 100644 index 4f390d189d23b5..00000000000000 --- a/Misc/NEWS.d/next/IDLE/2023-04-30-20-01-18.gh-issue-88496.y65vUb.rst +++ /dev/null @@ -1 +0,0 @@ -Fix IDLE test hang on macOS. diff --git a/Misc/NEWS.d/next/Library/2018-07-16-14-10-29.bpo-22708.592iRR.rst b/Misc/NEWS.d/next/Library/2018-07-16-14-10-29.bpo-22708.592iRR.rst deleted file mode 100644 index 00bcf38bbcdf51..00000000000000 --- a/Misc/NEWS.d/next/Library/2018-07-16-14-10-29.bpo-22708.592iRR.rst +++ /dev/null @@ -1,3 +0,0 @@ -http.client CONNECT method tunnel improvements: Use HTTP 1.1 protocol; send -a matching Host: header with CONNECT, if one is not provided; convert IDN -domain names to Punycode. Patch by Michael Handler. diff --git a/Misc/NEWS.d/next/Library/2020-02-25-00-43-22.bpo-39744.hgK689.rst b/Misc/NEWS.d/next/Library/2020-02-25-00-43-22.bpo-39744.hgK689.rst deleted file mode 100644 index 6e690f996569a4..00000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-25-00-43-22.bpo-39744.hgK689.rst +++ /dev/null @@ -1 +0,0 @@ -Make :func:`asyncio.subprocess.Process.communicate` close the subprocess's stdin even when called with ``input=None``. diff --git a/Misc/NEWS.d/next/Library/2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst b/Misc/NEWS.d/next/Library/2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst deleted file mode 100644 index ba113673b7fbe5..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-05-16-14-28-30.bpo-24964.Oa5Ie_.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added attribute '_proxy_response_headers' to HTTPConnection class. This -attribute contains the headers of the proxy server response to the CONNECT -request. diff --git a/Misc/NEWS.d/next/Library/2021-11-07-15-31-25.bpo-23041.564i32.rst b/Misc/NEWS.d/next/Library/2021-11-07-15-31-25.bpo-23041.564i32.rst deleted file mode 100644 index 53c32d397b206b..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-07-15-31-25.bpo-23041.564i32.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :data:`~csv.QUOTE_STRINGS` and :data:`~csv.QUOTE_NOTNULL` to the suite -of :mod:`csv` module quoting styles. diff --git a/Misc/NEWS.d/next/Library/2021-11-19-23-37-18.bpo-45606.UW5XE1.rst b/Misc/NEWS.d/next/Library/2021-11-19-23-37-18.bpo-45606.UW5XE1.rst deleted file mode 100644 index 531f4729220036..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-11-19-23-37-18.bpo-45606.UW5XE1.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fixed the bug in :meth:`pathlib.Path.glob` -- previously a dangling symlink -would not be found by this method when the pattern is an exact match, but -would be found when the pattern contains a wildcard or the recursive -wildcard (``**``). With this change, a dangling symlink will be found in -both cases. diff --git a/Misc/NEWS.d/next/Library/2021-12-03-23-00-56.bpo-44844.tvg2VY.rst b/Misc/NEWS.d/next/Library/2021-12-03-23-00-56.bpo-44844.tvg2VY.rst deleted file mode 100644 index f0c91236dfdf21..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-12-03-23-00-56.bpo-44844.tvg2VY.rst +++ /dev/null @@ -1 +0,0 @@ -Enables :mod:`webbrowser` to detect and launch Microsoft Edge browser. diff --git a/Misc/NEWS.d/next/Library/2022-02-19-14-19-34.bpo-46797.6BXZX4.rst b/Misc/NEWS.d/next/Library/2022-02-19-14-19-34.bpo-46797.6BXZX4.rst deleted file mode 100644 index 6539efbc9d0eb0..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-02-19-14-19-34.bpo-46797.6BXZX4.rst +++ /dev/null @@ -1,4 +0,0 @@ -Deprecation warnings are now emitted for :class:`!ast.Num`, -:class:`!ast.Bytes`, :class:`!ast.Str`, :class:`!ast.NameConstant` and -:class:`!ast.Ellipsis`. These have been documented as deprecated since Python -3.8, and will be removed in Python 3.14. diff --git a/Misc/NEWS.d/next/Library/2022-05-02-16-21-05.gh-issue-92184.hneGVW.rst b/Misc/NEWS.d/next/Library/2022-05-02-16-21-05.gh-issue-92184.hneGVW.rst deleted file mode 100644 index 65dbdc9f60371e..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-05-02-16-21-05.gh-issue-92184.hneGVW.rst +++ /dev/null @@ -1,3 +0,0 @@ -When creating zip files using :mod:`zipfile`, ``os.altsep``, if not ``None``, -will always be treated as a path separator even when it is not ``/``. -Patch by Carey Metcalfe. diff --git a/Misc/NEWS.d/next/Library/2022-05-17-10-46-44.gh-issue-92871.GVogrT.rst b/Misc/NEWS.d/next/Library/2022-05-17-10-46-44.gh-issue-92871.GVogrT.rst new file mode 100644 index 00000000000000..992f8afadbe912 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-17-10-46-44.gh-issue-92871.GVogrT.rst @@ -0,0 +1,2 @@ +Remove the ``typing.io`` and ``typing.re`` namespaces, deprecated since Python +3.8. All items are still available from the main :mod:`typing` module. diff --git a/Misc/NEWS.d/next/Library/2022-07-03-23-13-28.gh-issue-94518.511Tbh.rst b/Misc/NEWS.d/next/Library/2022-07-03-23-13-28.gh-issue-94518.511Tbh.rst deleted file mode 100644 index 7719b74b8e5ef1..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-07-03-23-13-28.gh-issue-94518.511Tbh.rst +++ /dev/null @@ -1 +0,0 @@ -Convert private :meth:`_posixsubprocess.fork_exec` to use Argument Clinic. diff --git a/Misc/NEWS.d/next/Library/2022-07-06-11-10-37.gh-issue-51574.sveUeD.rst b/Misc/NEWS.d/next/Library/2022-07-06-11-10-37.gh-issue-51574.sveUeD.rst deleted file mode 100644 index 50a3d6a4629182..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-07-06-11-10-37.gh-issue-51574.sveUeD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Make :func:`tempfile.mkdtemp` return absolute paths when its *dir* -parameter is relative. diff --git a/Misc/NEWS.d/next/Library/2022-09-03-09-24-02.gh-issue-96534.EU4Oxv.rst b/Misc/NEWS.d/next/Library/2022-09-03-09-24-02.gh-issue-96534.EU4Oxv.rst deleted file mode 100644 index 0497d9eb69163e..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-09-03-09-24-02.gh-issue-96534.EU4Oxv.rst +++ /dev/null @@ -1 +0,0 @@ -Support divert(4) added in FreeBSD 14. diff --git a/Misc/NEWS.d/next/Library/2022-10-09-14-47-42.gh-issue-98040.IN3qab.rst b/Misc/NEWS.d/next/Library/2022-10-09-14-47-42.gh-issue-98040.IN3qab.rst deleted file mode 100644 index ac185406844153..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-10-09-14-47-42.gh-issue-98040.IN3qab.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove more deprecated importlib APIs: ``find_loader()``, ``find_module()``, -``importlib.abc.Finder``, ``pkgutil.ImpImporter``, ``pkgutil.ImpLoader``. diff --git a/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst b/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst deleted file mode 100644 index e3297d164fff6d..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-10-21-16-23-31.gh-issue-97850.N46coo.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecate :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader` -in favor of :func:`importlib.util.find_spec`. diff --git a/Misc/NEWS.d/next/Library/2022-10-21-17-20-57.gh-issue-98040.3btbmA.rst b/Misc/NEWS.d/next/Library/2022-10-21-17-20-57.gh-issue-98040.3btbmA.rst deleted file mode 100644 index f67bffcb0ddc6c..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-10-21-17-20-57.gh-issue-98040.3btbmA.rst +++ /dev/null @@ -1 +0,0 @@ -Remove the long-deprecated ``imp`` module. diff --git a/Misc/NEWS.d/next/Library/2022-11-10-16-26-47.gh-issue-99353.DQFjnt.rst b/Misc/NEWS.d/next/Library/2022-11-10-16-26-47.gh-issue-99353.DQFjnt.rst deleted file mode 100644 index 1ad42d5c9aa53d..00000000000000 --- a/Misc/NEWS.d/next/Library/2022-11-10-16-26-47.gh-issue-99353.DQFjnt.rst +++ /dev/null @@ -1,3 +0,0 @@ -Respect the :class:`http.client.HTTPConnection` ``.debuglevel`` flag -in :class:`urllib.request.AbstractHTTPHandler` when its constructor -parameter ``debuglevel`` is not set. And do the same for ``*HTTPS*``. diff --git a/Misc/NEWS.d/next/Library/2023-01-14-17-54-56.gh-issue-95299.vUhpKz.rst b/Misc/NEWS.d/next/Library/2023-01-14-17-54-56.gh-issue-95299.vUhpKz.rst deleted file mode 100644 index 29c30848e09a83..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-14-17-54-56.gh-issue-95299.vUhpKz.rst +++ /dev/null @@ -1 +0,0 @@ -Remove the bundled setuptools wheel from ``ensurepip``, and stop installing setuptools in environments created by ``venv``. diff --git a/Misc/NEWS.d/next/Library/2023-01-22-14-53-12.gh-issue-89550.c1U23f.rst b/Misc/NEWS.d/next/Library/2023-01-22-14-53-12.gh-issue-89550.c1U23f.rst deleted file mode 100644 index 556db0eae00c0b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-01-22-14-53-12.gh-issue-89550.c1U23f.rst +++ /dev/null @@ -1,2 +0,0 @@ -Decrease execution time of some :mod:`gzip` file writes by 15% by -adding more appropriate buffering. diff --git a/Misc/NEWS.d/next/Library/2023-02-06-16-45-18.gh-issue-83861.mMbIU3.rst b/Misc/NEWS.d/next/Library/2023-02-06-16-45-18.gh-issue-83861.mMbIU3.rst deleted file mode 100644 index e85e7a4ff2e73a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-06-16-45-18.gh-issue-83861.mMbIU3.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix datetime.astimezone method return value when invoked on a naive datetime -instance that represents local time falling in a timezone transition gap. -PEP 495 requires that instances with fold=1 produce earlier times than those -with fold=0 in this case. diff --git a/Misc/NEWS.d/next/Library/2023-02-09-22-24-34.gh-issue-101640.oFuEpB.rst b/Misc/NEWS.d/next/Library/2023-02-09-22-24-34.gh-issue-101640.oFuEpB.rst deleted file mode 100644 index 917cf0f97b9e06..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-09-22-24-34.gh-issue-101640.oFuEpB.rst +++ /dev/null @@ -1 +0,0 @@ -:class:`argparse.ArgumentParser` now catches errors when writing messages, such as when :data:`sys.stderr` is ``None``. Patch by Oleg Iarygin. diff --git a/Misc/NEWS.d/next/Library/2023-02-11-15-01-32.gh-issue-101688.kwXmfM.rst b/Misc/NEWS.d/next/Library/2023-02-11-15-01-32.gh-issue-101688.kwXmfM.rst deleted file mode 100644 index 6df69463931494..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-11-15-01-32.gh-issue-101688.kwXmfM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Implement :func:`types.get_original_bases` to provide further introspection -for types. diff --git a/Misc/NEWS.d/next/Library/2023-02-17-21-14-40.gh-issue-78079.z3Szr6.rst b/Misc/NEWS.d/next/Library/2023-02-17-21-14-40.gh-issue-78079.z3Szr6.rst deleted file mode 100644 index bbb9ac3e3f8faa..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-17-21-14-40.gh-issue-78079.z3Szr6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix incorrect normalization of UNC device path roots, and partial UNC share -path roots, in :class:`pathlib.PurePath`. Pathlib no longer appends a -trailing slash to such paths. diff --git a/Misc/NEWS.d/next/Library/2023-02-19-12-37-08.gh-issue-62432.GnBFIB.rst b/Misc/NEWS.d/next/Library/2023-02-19-12-37-08.gh-issue-62432.GnBFIB.rst deleted file mode 100644 index a8d66ea48c3278..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-19-12-37-08.gh-issue-62432.GnBFIB.rst +++ /dev/null @@ -1,3 +0,0 @@ -The :mod:`unittest` runner will now exit with status code 5 if no tests -were run. It is common for test runner misconfiguration to fail to find -any tests, this should be an error. diff --git a/Misc/NEWS.d/next/Library/2023-02-21-14-57-34.gh-issue-102114.uUDQzb.rst b/Misc/NEWS.d/next/Library/2023-02-21-14-57-34.gh-issue-102114.uUDQzb.rst deleted file mode 100644 index 4140c9a96cd272..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-02-21-14-57-34.gh-issue-102114.uUDQzb.rst +++ /dev/null @@ -1 +0,0 @@ -Functions in the :mod:`dis` module that accept a source code string as argument now print a more concise traceback when the string contains a syntax or indentation error. diff --git a/Misc/NEWS.d/next/Library/2023-03-06-18-49-57.gh-issue-101362.eSSy6L.rst b/Misc/NEWS.d/next/Library/2023-03-06-18-49-57.gh-issue-101362.eSSy6L.rst deleted file mode 100644 index 87617a503c0dba..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-06-18-49-57.gh-issue-101362.eSSy6L.rst +++ /dev/null @@ -1,2 +0,0 @@ -Speed up :class:`pathlib.Path` construction by omitting the path anchor from -the internal list of path parts. diff --git a/Misc/NEWS.d/next/Library/2023-03-08-02-45-46.gh-issue-91896.kgON_a.rst b/Misc/NEWS.d/next/Library/2023-03-08-02-45-46.gh-issue-91896.kgON_a.rst deleted file mode 100644 index b5282d3d612916..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-08-02-45-46.gh-issue-91896.kgON_a.rst +++ /dev/null @@ -1 +0,0 @@ -Deprecate :class:`collections.abc.ByteString` diff --git a/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst b/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst deleted file mode 100644 index 4a73bbf32b370e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-14-11-20-19.gh-issue-101819.0-h0it.rst +++ /dev/null @@ -1,2 +0,0 @@ -Isolate the :mod:`io` extension module by applying :pep:`687`. Patch by -Kumar Aditya, Victor Stinner, and Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-03-15-00-37-43.gh-issue-81079.heTAod.rst b/Misc/NEWS.d/next/Library/2023-03-15-00-37-43.gh-issue-81079.heTAod.rst deleted file mode 100644 index ef5690533985d5..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-15-00-37-43.gh-issue-81079.heTAod.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add *case_sensitive* keyword-only argument to :meth:`pathlib.Path.glob` and -:meth:`~pathlib.Path.rglob`. diff --git a/Misc/NEWS.d/next/Library/2023-03-15-12-18-07.gh-issue-97696.DtnpIC.rst b/Misc/NEWS.d/next/Library/2023-03-15-12-18-07.gh-issue-97696.DtnpIC.rst deleted file mode 100644 index 0b3854d74eb991..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-15-12-18-07.gh-issue-97696.DtnpIC.rst +++ /dev/null @@ -1,6 +0,0 @@ -Implemented an eager task factory in asyncio. -When used as a task factory on an event loop, it performs eager execution of -coroutines. Coroutines that are able to complete synchronously (e.g. return or -raise without blocking) are returned immediately as a finished task, and the -task is never scheduled to the event loop. If the coroutine blocks, the -(pending) task is scheduled and returned. diff --git a/Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst b/Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst deleted file mode 100644 index 48a105a4a17b29..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-23-15-24-38.gh-issue-102953.YR4KaK.rst +++ /dev/null @@ -1,4 +0,0 @@ -The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`, -have a new a *filter* argument that allows limiting tar features than may be -surprising or dangerous, such as creating files outside the destination -directory. See :ref:`tarfile-extraction-filter` for details. diff --git a/Misc/NEWS.d/next/Library/2023-03-24-20-49-48.gh-issue-103000.6eVNZI.rst b/Misc/NEWS.d/next/Library/2023-03-24-20-49-48.gh-issue-103000.6eVNZI.rst deleted file mode 100644 index 15f16d9eb4c1bf..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-24-20-49-48.gh-issue-103000.6eVNZI.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve performance of :func:`dataclasses.astuple` and -:func:`dataclasses.asdict` in cases where the contents are common Python types. diff --git a/Misc/NEWS.d/next/Library/2023-03-28-09-13-31.gh-issue-103015.ETTfNf.rst b/Misc/NEWS.d/next/Library/2023-03-28-09-13-31.gh-issue-103015.ETTfNf.rst deleted file mode 100644 index dcac1a28ca5847..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-28-09-13-31.gh-issue-103015.ETTfNf.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add *entrypoint* keyword-only parameter to -:meth:`sqlite3.Connection.load_extension`, for overriding the SQLite -extension entry point. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-03-31-01-13-00.gh-issue-103143.6eMluy.rst b/Misc/NEWS.d/next/Library/2023-03-31-01-13-00.gh-issue-103143.6eMluy.rst deleted file mode 100644 index 32bd62d27c7c6d..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-03-31-01-13-00.gh-issue-103143.6eMluy.rst +++ /dev/null @@ -1 +0,0 @@ -Polish the help messages and docstrings of :mod:`pdb`. diff --git a/Misc/NEWS.d/next/Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst b/Misc/NEWS.d/next/Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst deleted file mode 100644 index b89f9bae595457..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-01-23-01-31.gh-issue-103176.FBsdxa.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`sys._current_exceptions` now returns a mapping from thread-id to an -exception instance, rather than to a ``(typ, exc, tb)`` tuple. diff --git a/Misc/NEWS.d/next/Library/2023-04-02-17-51-08.gh-issue-103193.xrZbM1.rst b/Misc/NEWS.d/next/Library/2023-04-02-17-51-08.gh-issue-103193.xrZbM1.rst deleted file mode 100644 index f0b76a605a5610..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-02-17-51-08.gh-issue-103193.xrZbM1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve performance of :func:`inspect.getattr_static`. Patch by Alex -Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-04-02-22-04-26.gh-issue-75586.526iJm.rst b/Misc/NEWS.d/next/Library/2023-04-02-22-04-26.gh-issue-75586.526iJm.rst deleted file mode 100644 index 8ec568ec4e4775..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-02-22-04-26.gh-issue-75586.526iJm.rst +++ /dev/null @@ -1 +0,0 @@ -Fix various Windows-specific issues with ``shutil.which``. diff --git a/Misc/NEWS.d/next/Library/2023-04-02-23-05-22.gh-issue-103204.bbDmu0.rst b/Misc/NEWS.d/next/Library/2023-04-02-23-05-22.gh-issue-103204.bbDmu0.rst deleted file mode 100644 index f8b3aa5151b622..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-02-23-05-22.gh-issue-103204.bbDmu0.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixes :mod:`http.server` accepting HTTP requests with HTTP version numbers -preceded by '+', or '-', or with digit-separating '_' characters. The length -of the version numbers is also constrained. diff --git a/Misc/NEWS.d/next/Library/2023-04-03-21-08-53.gh-issue-103220.OW_Bj5.rst b/Misc/NEWS.d/next/Library/2023-04-03-21-08-53.gh-issue-103220.OW_Bj5.rst deleted file mode 100644 index 9cf26c26873b2a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-03-21-08-53.gh-issue-103220.OW_Bj5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix issue where :func:`os.path.join` added a slash when joining onto an -incomplete UNC drive with a trailing slash on Windows. diff --git a/Misc/NEWS.d/next/Library/2023-04-03-22-02-35.gh-issue-100479.kNBjQm.rst b/Misc/NEWS.d/next/Library/2023-04-03-22-02-35.gh-issue-100479.kNBjQm.rst deleted file mode 100644 index 58db90480d2ff0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-03-22-02-35.gh-issue-100479.kNBjQm.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add :meth:`pathlib.PurePath.with_segments`, which creates a path object from -arguments. This method is called whenever a derivative path is created, such -as from :attr:`pathlib.PurePath.parent`. Subclasses may override this method -to share information between path objects. diff --git a/Misc/NEWS.d/next/Library/2023-04-03-23-43-12.gh-issue-103092.3xqk4y.rst b/Misc/NEWS.d/next/Library/2023-04-03-23-43-12.gh-issue-103092.3xqk4y.rst deleted file mode 100644 index e7586a223c1415..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-03-23-43-12.gh-issue-103092.3xqk4y.rst +++ /dev/null @@ -1 +0,0 @@ -Isolate :mod:`!_socket` (apply :pep:`687`). Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-04-03-23-44-34.gh-issue-102978.gy9eVk.rst b/Misc/NEWS.d/next/Library/2023-04-03-23-44-34.gh-issue-102978.gy9eVk.rst deleted file mode 100644 index df63af10a385eb..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-03-23-44-34.gh-issue-102978.gy9eVk.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixes :func:`unittest.mock.patch` not enforcing function signatures for methods -decorated with ``@classmethod`` or ``@staticmethod`` when patch is called with -``autospec=True``. diff --git a/Misc/NEWS.d/next/Library/2023-04-04-12-43-38.gh-issue-93910.jurMzv.rst b/Misc/NEWS.d/next/Library/2023-04-04-12-43-38.gh-issue-93910.jurMzv.rst deleted file mode 100644 index 783aefae0770a9..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-04-12-43-38.gh-issue-93910.jurMzv.rst +++ /dev/null @@ -1 +0,0 @@ -Remove deprecation of enum ``memmber.member`` access. diff --git a/Misc/NEWS.d/next/Library/2023-04-04-21-27-51.gh-issue-103092.7s7Bzf.rst b/Misc/NEWS.d/next/Library/2023-04-04-21-27-51.gh-issue-103092.7s7Bzf.rst deleted file mode 100644 index 39c62ffbe8c659..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-04-21-27-51.gh-issue-103092.7s7Bzf.rst +++ /dev/null @@ -1 +0,0 @@ -Adapt the :mod:`winsound` extension module to :pep:`687`. diff --git a/Misc/NEWS.d/next/Library/2023-04-04-21-44-25.gh-issue-103092.Dz0_Xn.rst b/Misc/NEWS.d/next/Library/2023-04-04-21-44-25.gh-issue-103092.Dz0_Xn.rst deleted file mode 100644 index 7bd191e3c22b2b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-04-21-44-25.gh-issue-103092.Dz0_Xn.rst +++ /dev/null @@ -1 +0,0 @@ -Adapt the :mod:`msvcrt` extension module to :pep:`687`. diff --git a/Misc/NEWS.d/next/Library/2023-04-05-01-28-53.gh-issue-103225.QD3JVU.rst b/Misc/NEWS.d/next/Library/2023-04-05-01-28-53.gh-issue-103225.QD3JVU.rst deleted file mode 100644 index 5d1a063acdeb8c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-05-01-28-53.gh-issue-103225.QD3JVU.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a bug in :mod:`pdb` when displaying line numbers of module-level source code. diff --git a/Misc/NEWS.d/next/Library/2023-04-06-04-35-59.gh-issue-103285.rCZ9-G.rst b/Misc/NEWS.d/next/Library/2023-04-06-04-35-59.gh-issue-103285.rCZ9-G.rst deleted file mode 100644 index 62b4364c2b1665..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-06-04-35-59.gh-issue-103285.rCZ9-G.rst +++ /dev/null @@ -1 +0,0 @@ -Improve performance of :func:`ast.get_source_segment`. diff --git a/Misc/NEWS.d/next/Library/2023-04-06-16-55-51.gh-issue-102778.BWeAmE.rst b/Misc/NEWS.d/next/Library/2023-04-06-16-55-51.gh-issue-102778.BWeAmE.rst deleted file mode 100644 index 64ae5b5b6d564b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-06-16-55-51.gh-issue-102778.BWeAmE.rst +++ /dev/null @@ -1 +0,0 @@ -Support ``sys.last_exc`` in :mod:`idlelib`. diff --git a/Misc/NEWS.d/next/Library/2023-04-06-17-28-36.gh-issue-103256.1syxfs.rst b/Misc/NEWS.d/next/Library/2023-04-06-17-28-36.gh-issue-103256.1syxfs.rst deleted file mode 100644 index 894c046dcdf0fd..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-06-17-28-36.gh-issue-103256.1syxfs.rst +++ /dev/null @@ -1,6 +0,0 @@ -Fixed a bug that caused :mod:`hmac` to raise an exception when the requested -hash algorithm was not available in OpenSSL despite being available -separately as part of ``hashlib`` itself. It now falls back properly to the -built-in. This could happen when, for example, your OpenSSL does not include -SHA3 support and you want to compute ``hmac.digest(b'K', b'M', -'sha3_256')``. diff --git a/Misc/NEWS.d/next/Library/2023-04-07-15-09-26.gh-issue-74690.0f886b.rst b/Misc/NEWS.d/next/Library/2023-04-07-15-09-26.gh-issue-74690.0f886b.rst deleted file mode 100644 index 0a103ae11970d4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-07-15-09-26.gh-issue-74690.0f886b.rst +++ /dev/null @@ -1,3 +0,0 @@ -The members of a runtime-checkable protocol are now considered "frozen" at -runtime as soon as the class has been created. See -:ref:`"What's new in Python 3.12" ` for more details. diff --git a/Misc/NEWS.d/next/Library/2023-04-07-15-15-40.gh-issue-74690.un84hh.rst b/Misc/NEWS.d/next/Library/2023-04-07-15-15-40.gh-issue-74690.un84hh.rst deleted file mode 100644 index 48f11aac692ddb..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-07-15-15-40.gh-issue-74690.un84hh.rst +++ /dev/null @@ -1,8 +0,0 @@ -The performance of :func:`isinstance` checks against -:func:`runtime-checkable protocols ` has been -considerably improved for protocols that only have a few members. To achieve -this improvement, several internal implementation details of the -:mod:`typing` module have been refactored, including -``typing._ProtocolMeta.__instancecheck__``, -``typing._is_callable_members_only``, and ``typing._get_protocol_attrs``. -Patches by Alex Waygood. diff --git a/Misc/NEWS.d/next/Library/2023-04-08-00-48-40.gh-issue-103092.5EFts0.rst b/Misc/NEWS.d/next/Library/2023-04-08-00-48-40.gh-issue-103092.5EFts0.rst deleted file mode 100644 index 0f2108fee763d0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-08-00-48-40.gh-issue-103092.5EFts0.rst +++ /dev/null @@ -1 +0,0 @@ -Adapt the :mod:`winreg` extension module to :pep:`687`. diff --git a/Misc/NEWS.d/next/Library/2023-04-08-01-33-12.gh-issue-103357.vjin28.rst b/Misc/NEWS.d/next/Library/2023-04-08-01-33-12.gh-issue-103357.vjin28.rst deleted file mode 100644 index 83dce56ed0b7c5..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-08-01-33-12.gh-issue-103357.vjin28.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added support for :class:`logging.Formatter` ``defaults`` parameter to -:func:`logging.config.dictConfig` and :func:`logging.config.fileConfig`. -Patch by Bar Harel. diff --git a/Misc/NEWS.d/next/Library/2023-04-09-06-59-36.gh-issue-103092.vskbro.rst b/Misc/NEWS.d/next/Library/2023-04-09-06-59-36.gh-issue-103092.vskbro.rst deleted file mode 100644 index 6977c1489a29cb..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-09-06-59-36.gh-issue-103092.vskbro.rst +++ /dev/null @@ -1 +0,0 @@ -Isolate :mod:`!_collections` (apply :pep:`687`). Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-04-11-21-38-39.gh-issue-103449.-nxmhb.rst b/Misc/NEWS.d/next/Library/2023-04-11-21-38-39.gh-issue-103449.-nxmhb.rst deleted file mode 100644 index 0b2b47af1cbaab..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-11-21-38-39.gh-issue-103449.-nxmhb.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a bug in doc string generation in :func:`dataclasses.dataclass`. diff --git a/Misc/NEWS.d/next/Library/2023-04-12-06-00-02.gh-issue-103462.w6yBlM.rst b/Misc/NEWS.d/next/Library/2023-04-12-06-00-02.gh-issue-103462.w6yBlM.rst deleted file mode 100644 index 50758c89cc2856..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-12-06-00-02.gh-issue-103462.w6yBlM.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fixed an issue with using :meth:`~asyncio.WriteTransport.writelines` in :mod:`asyncio` to send very -large payloads that exceed the amount of data that can be written in one -call to :meth:`socket.socket.send` or :meth:`socket.socket.sendmsg`, -resulting in the remaining buffer being left unwritten. diff --git a/Misc/NEWS.d/next/Library/2023-04-12-13-04-16.gh-issue-103472.C6bOHv.rst b/Misc/NEWS.d/next/Library/2023-04-12-13-04-16.gh-issue-103472.C6bOHv.rst deleted file mode 100644 index 01d84f024bd4a6..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-12-13-04-16.gh-issue-103472.C6bOHv.rst +++ /dev/null @@ -1,2 +0,0 @@ -Avoid a potential :exc:`ResourceWarning` in :class:`http.client.HTTPConnection` -by closing the proxy / tunnel's CONNECT response explicitly. diff --git a/Misc/NEWS.d/next/Library/2023-04-12-17-59-55.gh-issue-103365.UBEE0U.rst b/Misc/NEWS.d/next/Library/2023-04-12-17-59-55.gh-issue-103365.UBEE0U.rst deleted file mode 100644 index 4d69f6f6fff713..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-12-17-59-55.gh-issue-103365.UBEE0U.rst +++ /dev/null @@ -1 +0,0 @@ -Set default Flag boundary to ``STRICT`` and fix bitwise operations. diff --git a/Misc/NEWS.d/next/Library/2023-04-13-13-17-47.gh-issue-103489.ZSZgmu.rst b/Misc/NEWS.d/next/Library/2023-04-13-13-17-47.gh-issue-103489.ZSZgmu.rst deleted file mode 100644 index 264564d018ceb4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-13-13-17-47.gh-issue-103489.ZSZgmu.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add :meth:`~sqlite3.Connection.getconfig` and -:meth:`~sqlite3.Connection.setconfig` to :class:`~sqlite3.Connection` to -make configuration changes to a database connection. Patch by Erlend E. -Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst b/Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst deleted file mode 100644 index 1414cb07dd9155..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-13-19-43-15.gh-issue-103525.uY4VYg.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix misleading exception message when mixed ``str`` and ``bytes`` arguments -are supplied to :class:`pathlib.PurePath` and :class:`~pathlib.Path`. diff --git a/Misc/NEWS.d/next/Library/2023-04-14-06-32-54.gh-issue-103533.n_AfcS.rst b/Misc/NEWS.d/next/Library/2023-04-14-06-32-54.gh-issue-103533.n_AfcS.rst deleted file mode 100644 index 1008ea076c71a0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-14-06-32-54.gh-issue-103533.n_AfcS.rst +++ /dev/null @@ -1 +0,0 @@ -Update :mod:`cProfile` to use PEP 669 API diff --git a/Misc/NEWS.d/next/Library/2023-04-14-21-12-32.gh-issue-103538.M4FK_v.rst b/Misc/NEWS.d/next/Library/2023-04-14-21-12-32.gh-issue-103538.M4FK_v.rst deleted file mode 100644 index 32788307d6f33b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-14-21-12-32.gh-issue-103538.M4FK_v.rst +++ /dev/null @@ -1,3 +0,0 @@ -Remove ``_tkinter`` module code guarded by definition of the ``TK_AQUA`` macro -which was only needed for Tk 8.4.7 or earlier and was never actually defined by -any build system or documented for manual use. diff --git a/Misc/NEWS.d/next/Library/2023-04-14-21-16-05.gh-issue-103548.lagdpp.rst b/Misc/NEWS.d/next/Library/2023-04-14-21-16-05.gh-issue-103548.lagdpp.rst deleted file mode 100644 index 238f2868867472..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-14-21-16-05.gh-issue-103548.lagdpp.rst +++ /dev/null @@ -1,4 +0,0 @@ -Improve performance of :meth:`pathlib.Path.absolute` and -:meth:`~pathlib.Path.cwd` by joining paths only when necessary. Also improve -performance of :meth:`pathlib.PurePath.is_absolute` on Posix by skipping path -parsing and normalization. diff --git a/Misc/NEWS.d/next/Library/2023-04-15-11-21-38.gh-issue-103559.a9rYHG.rst b/Misc/NEWS.d/next/Library/2023-04-15-11-21-38.gh-issue-103559.a9rYHG.rst deleted file mode 100644 index 2c9d67e2c4bf71..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-15-11-21-38.gh-issue-103559.a9rYHG.rst +++ /dev/null @@ -1 +0,0 @@ -Update the bundled copy of pip to version 23.1.1. diff --git a/Misc/NEWS.d/next/Library/2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst b/Misc/NEWS.d/next/Library/2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst deleted file mode 100644 index fe2267b7b79019..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-15-12-19-14.gh-issue-103556.TEf-2m.rst +++ /dev/null @@ -1,3 +0,0 @@ -Now creating :class:`inspect.Signature` objects with positional-only -parameter with a default followed by a positional-or-keyword parameter -without one is impossible. diff --git a/Misc/NEWS.d/next/Library/2023-04-16-18-29-04.gh-issue-103578.fly1wc.rst b/Misc/NEWS.d/next/Library/2023-04-16-18-29-04.gh-issue-103578.fly1wc.rst deleted file mode 100644 index 69986c2a15b39e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-16-18-29-04.gh-issue-103578.fly1wc.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a bug where :mod:`pdb` crashes when reading source file with different encoding by replacing :func:`io.open` with :func:`io.open_code`. The new method would also call into the hook set by :func:`PyFile_SetOpenCodeHook`. diff --git a/Misc/NEWS.d/next/Library/2023-04-16-19-48-21.gh-issue-103584.3mBTuM.rst b/Misc/NEWS.d/next/Library/2023-04-16-19-48-21.gh-issue-103584.3mBTuM.rst deleted file mode 100644 index 6d7c93ade9cd94..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-16-19-48-21.gh-issue-103584.3mBTuM.rst +++ /dev/null @@ -1,12 +0,0 @@ -Updated ``importlib.metadata`` with changes from ``importlib_metadata`` 5.2 -through 6.5.0, including: Support ``installed-files.txt`` for -``Distribution.files`` when present. ``PackageMetadata`` now stipulates an -additional ``get`` method allowing for easy querying of metadata keys that -may not be present. ``packages_distributions`` now honors packages and -modules with Python modules that not ``.py`` sources (e.g. ``.pyc``, -``.so``). Expand protocol for ``PackageMetadata.get_all`` to match the -upstream implementation of ``email.message.Message.get_all`` in -python/typeshed#9620. Deprecated use of ``Distribution`` without defining -abstract methods. Deprecated expectation that -``PackageMetadata.__getitem__`` will return ``None`` for missing keys. In -the future, it will raise a ``KeyError``. diff --git a/Misc/NEWS.d/next/Library/2023-04-17-14-47-28.gh-issue-103596.ME1y3_.rst b/Misc/NEWS.d/next/Library/2023-04-17-14-47-28.gh-issue-103596.ME1y3_.rst deleted file mode 100644 index 2fa27e60b58efe..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-17-14-47-28.gh-issue-103596.ME1y3_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Attributes/methods are no longer shadowed by same-named enum members, -although they may be shadowed by enum.property's. diff --git a/Misc/NEWS.d/next/Library/2023-04-19-16-08-53.gh-issue-84976.HwbzlD.rst b/Misc/NEWS.d/next/Library/2023-04-19-16-08-53.gh-issue-84976.HwbzlD.rst deleted file mode 100644 index 8658627aeba434..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-19-16-08-53.gh-issue-84976.HwbzlD.rst +++ /dev/null @@ -1,5 +0,0 @@ -Create a new ``Lib/_pydatetime.py`` file that defines the Python version of -the ``datetime`` module, and make ``datetime`` import the contents of the -new library only if the C implementation is missing. Currently, the full -Python implementation is defined and then deleted if the C implementation is -not available, slowing down ``import datetime`` unnecessarily. diff --git a/Misc/NEWS.d/next/Library/2023-04-21-10-25-39.gh-issue-103636.YK6NEa.rst b/Misc/NEWS.d/next/Library/2023-04-21-10-25-39.gh-issue-103636.YK6NEa.rst deleted file mode 100644 index b3b5085250f078..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-21-10-25-39.gh-issue-103636.YK6NEa.rst +++ /dev/null @@ -1 +0,0 @@ -Added Enum for months and days in the calendar module. diff --git a/Misc/NEWS.d/next/Library/2023-04-22-02-41-06.gh-issue-103673.oE7S_k.rst b/Misc/NEWS.d/next/Library/2023-04-22-02-41-06.gh-issue-103673.oE7S_k.rst deleted file mode 100644 index bd5317744ff140..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-22-02-41-06.gh-issue-103673.oE7S_k.rst +++ /dev/null @@ -1,2 +0,0 @@ -:mod:`socketserver` gains ``ForkingUnixStreamServer`` and -``ForkingUnixDatagramServer`` classes. Patch by Jay Berry. diff --git a/Misc/NEWS.d/next/Library/2023-04-22-11-20-27.gh-issue-89415.YHk760.rst b/Misc/NEWS.d/next/Library/2023-04-22-11-20-27.gh-issue-89415.YHk760.rst deleted file mode 100644 index a5b99a2f1360f0..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-22-11-20-27.gh-issue-89415.YHk760.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add :mod:`socket` constants for source-specific multicast. -Patch by Reese Hyde. diff --git a/Misc/NEWS.d/next/Library/2023-04-22-21-34-13.gh-issue-103693.SBtuLQ.rst b/Misc/NEWS.d/next/Library/2023-04-22-21-34-13.gh-issue-103693.SBtuLQ.rst deleted file mode 100644 index 52c68bfc9ceea4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-22-21-34-13.gh-issue-103693.SBtuLQ.rst +++ /dev/null @@ -1 +0,0 @@ -Add convenience variable feature to :mod:`pdb` diff --git a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst b/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst deleted file mode 100644 index 60547a25a109bc..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-22-22-37-39.gh-issue-103699.NizCjc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add ``__orig_bases__`` to non-generic TypedDicts, call-based TypedDicts, and -call-based NamedTuples. Other TypedDicts and NamedTuples already had the attribute. diff --git a/Misc/NEWS.d/next/Library/2023-04-23-15-39-17.gh-issue-81403.zVz9Td.rst b/Misc/NEWS.d/next/Library/2023-04-23-15-39-17.gh-issue-81403.zVz9Td.rst deleted file mode 100644 index 6adb71f7677229..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-23-15-39-17.gh-issue-81403.zVz9Td.rst +++ /dev/null @@ -1,3 +0,0 @@ -:class:`urllib.request.CacheFTPHandler` no longer raises :class:`URLError` -if a cached FTP instance is reused. ftplib's endtransfer method calls -voidresp to drain the connection to handle FTP instance reuse properly. diff --git a/Misc/NEWS.d/next/Library/2023-04-24-00-34-23.gh-issue-103685.U14jBM.rst b/Misc/NEWS.d/next/Library/2023-04-24-00-34-23.gh-issue-103685.U14jBM.rst deleted file mode 100644 index 31df04790721a8..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-24-00-34-23.gh-issue-103685.U14jBM.rst +++ /dev/null @@ -1 +0,0 @@ -Prepare :meth:`tkinter.Menu.index` for Tk 8.7 so that it does not raise ``TclError: expected integer but got ""`` when it should return ``None``. diff --git a/Misc/NEWS.d/next/Library/2023-04-24-16-00-28.gh-issue-90750.da0Xi8.rst b/Misc/NEWS.d/next/Library/2023-04-24-16-00-28.gh-issue-90750.da0Xi8.rst deleted file mode 100644 index 99e10f140f5049..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-24-16-00-28.gh-issue-90750.da0Xi8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Use :meth:`datetime.datetime.fromisocalendar` in the implementation of -:meth:`datetime.datetime.strptime`, which should now accept only valid ISO -dates. (Patch by Paul Ganssle) diff --git a/Misc/NEWS.d/next/Library/2023-04-24-23-07-56.gh-issue-103791.bBPWdS.rst b/Misc/NEWS.d/next/Library/2023-04-24-23-07-56.gh-issue-103791.bBPWdS.rst deleted file mode 100644 index f00384cde9706e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-24-23-07-56.gh-issue-103791.bBPWdS.rst +++ /dev/null @@ -1,3 +0,0 @@ -:class:`contextlib.suppress` now supports suppressing exceptions raised as -part of an :exc:`ExceptionGroup`. If other exceptions exist on the group, they -are re-raised in a group that does not contain the suppressed exceptions. diff --git a/Misc/NEWS.d/next/Library/2023-04-25-17-03-18.gh-issue-103857.Mr2Cak.rst b/Misc/NEWS.d/next/Library/2023-04-25-17-03-18.gh-issue-103857.Mr2Cak.rst deleted file mode 100644 index 3bd370dabf4ed5..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-25-17-03-18.gh-issue-103857.Mr2Cak.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecated :meth:`datetime.datetime.utcnow` and -:meth:`datetime.datetime.utcfromtimestamp`. (Patch by Paul Ganssle) diff --git a/Misc/NEWS.d/next/Library/2023-04-25-22-06-00.gh-issue-74940.TOacQ9.rst b/Misc/NEWS.d/next/Library/2023-04-25-22-06-00.gh-issue-74940.TOacQ9.rst deleted file mode 100644 index c37d795f3eb33d..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-25-22-06-00.gh-issue-74940.TOacQ9.rst +++ /dev/null @@ -1,2 +0,0 @@ -The C.UTF-8 locale is no longer converted to en_US.UTF-8, enabling the use -of UTF-8 encoding on systems which have no locales installed. diff --git a/Misc/NEWS.d/next/Library/2023-04-25-22-59-06.gh-issue-99944.pst8iT.rst b/Misc/NEWS.d/next/Library/2023-04-25-22-59-06.gh-issue-99944.pst8iT.rst deleted file mode 100644 index 80238a65e32a41..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-25-22-59-06.gh-issue-99944.pst8iT.rst +++ /dev/null @@ -1 +0,0 @@ -Make :mod:`dis` display the value of oparg of :opcode:`KW_NAMES`. diff --git a/Misc/NEWS.d/next/Library/2023-04-26-09-38-47.gh-issue-103872.8LBsDz.rst b/Misc/NEWS.d/next/Library/2023-04-26-09-38-47.gh-issue-103872.8LBsDz.rst deleted file mode 100644 index b840f9f5769f08..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-26-09-38-47.gh-issue-103872.8LBsDz.rst +++ /dev/null @@ -1 +0,0 @@ -Update the bundled copy of pip to version 23.1.2. diff --git a/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst b/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst deleted file mode 100644 index 81e5904aa6cca2..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add checks to ensure that ``[`` bracketed ``]`` hosts found by -:func:`urllib.parse.urlsplit` are of IPv6 or IPvFuture format. diff --git a/Misc/NEWS.d/next/Library/2023-04-26-15-14-36.gh-issue-103583.iCMDFt.rst b/Misc/NEWS.d/next/Library/2023-04-26-15-14-36.gh-issue-103583.iCMDFt.rst deleted file mode 100644 index 8c92ee40831619..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-26-15-14-36.gh-issue-103583.iCMDFt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Isolate :mod:`!_multibytecodec` and codecs extension modules. Patches by -Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-04-26-18-12-13.gh-issue-103636.-KvCgO.rst b/Misc/NEWS.d/next/Library/2023-04-26-18-12-13.gh-issue-103636.-KvCgO.rst deleted file mode 100644 index a05a6f5cbcdb99..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-26-18-12-13.gh-issue-103636.-KvCgO.rst +++ /dev/null @@ -1 +0,0 @@ -Module-level attributes ``January`` and ``February`` are deprecated from :mod:`calendar`. diff --git a/Misc/NEWS.d/next/Library/2023-04-27-00-05-32.gh-issue-102628.X230E-.rst b/Misc/NEWS.d/next/Library/2023-04-27-00-05-32.gh-issue-102628.X230E-.rst deleted file mode 100644 index eaaca5b41ba5e2..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-27-00-05-32.gh-issue-102628.X230E-.rst +++ /dev/null @@ -1,2 +0,0 @@ -Substitute CTRL-D with CTRL-Z in :mod:`sqlite3` CLI banner when running on -Windows. diff --git a/Misc/NEWS.d/next/Library/2023-04-27-00-45-41.gh-issue-100370.MgZ3KY.rst b/Misc/NEWS.d/next/Library/2023-04-27-00-45-41.gh-issue-100370.MgZ3KY.rst deleted file mode 100644 index 9022d55c48cb11..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-27-00-45-41.gh-issue-100370.MgZ3KY.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix potential :exc:`OverflowError` in :meth:`sqlite3.Connection.blobopen` -for 32-bit builds. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Library/2023-04-27-18-46-31.gh-issue-68968.E3tnhy.rst b/Misc/NEWS.d/next/Library/2023-04-27-18-46-31.gh-issue-68968.E3tnhy.rst deleted file mode 100644 index bf29b64793b933..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-27-18-46-31.gh-issue-68968.E3tnhy.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed garbled output of :meth:`~unittest.TestCase.assertEqual` when an input lacks final newline. diff --git a/Misc/NEWS.d/next/Library/2023-04-27-20-03-08.gh-issue-103935.Uaf2M0.rst b/Misc/NEWS.d/next/Library/2023-04-27-20-03-08.gh-issue-103935.Uaf2M0.rst deleted file mode 100644 index 71b2d87249c47b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-27-20-03-08.gh-issue-103935.Uaf2M0.rst +++ /dev/null @@ -1 +0,0 @@ -Use :func:`io.open_code` for files to be executed instead of raw :func:`open` diff --git a/Misc/NEWS.d/next/Library/2023-04-28-18-04-23.gh-issue-88773.xXCNJw.rst b/Misc/NEWS.d/next/Library/2023-04-28-18-04-23.gh-issue-88773.xXCNJw.rst deleted file mode 100644 index f14c9533f3af87..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-28-18-04-23.gh-issue-88773.xXCNJw.rst +++ /dev/null @@ -1 +0,0 @@ -Added :func:`turtle.teleport` to the :mod:`turtle` module to move a turtle to a new point without tracing a line, visible or invisible. Patch by Liam Gersten. diff --git a/Misc/NEWS.d/next/Library/2023-04-28-19-08-50.gh-issue-103977.msF70A.rst b/Misc/NEWS.d/next/Library/2023-04-28-19-08-50.gh-issue-103977.msF70A.rst deleted file mode 100644 index ff4005774a95d2..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-04-28-19-08-50.gh-issue-103977.msF70A.rst +++ /dev/null @@ -1 +0,0 @@ -Improve import time of :mod:`platform` module. diff --git a/Misc/NEWS.d/next/Library/2023-05-01-16-43-28.gh-issue-104035.MrJBw8.rst b/Misc/NEWS.d/next/Library/2023-05-01-16-43-28.gh-issue-104035.MrJBw8.rst deleted file mode 100644 index 8c8e3d6ba5fbc1..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-01-16-43-28.gh-issue-104035.MrJBw8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Do not ignore user-defined ``__getstate__`` and ``__setstate__`` methods for -slotted frozen dataclasses. diff --git a/Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst b/Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst deleted file mode 100644 index cb06ad5d22e8a9..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-01-17-58-28.gh-issue-103963.XWlHx7.rst +++ /dev/null @@ -1 +0,0 @@ -Make :mod:`dis` display the names of the args for :opcode:`CALL_INTRINSIC_*`. diff --git a/Misc/NEWS.d/next/Library/2023-05-01-19-10-05.gh-issue-103629.81bpZz.rst b/Misc/NEWS.d/next/Library/2023-05-01-19-10-05.gh-issue-103629.81bpZz.rst deleted file mode 100644 index 7971ab66359c3d..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-01-19-10-05.gh-issue-103629.81bpZz.rst +++ /dev/null @@ -1 +0,0 @@ -Update the ``repr`` of :class:`typing.Unpack` according to :pep:`692`. diff --git a/Misc/NEWS.d/next/Library/2023-05-02-04-49-45.gh-issue-103822.m0QdAO.rst b/Misc/NEWS.d/next/Library/2023-05-02-04-49-45.gh-issue-103822.m0QdAO.rst deleted file mode 100644 index 3daf9cc093807b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-02-04-49-45.gh-issue-103822.m0QdAO.rst +++ /dev/null @@ -1 +0,0 @@ -Update the return type of ``weekday`` to the newly added Day attribute diff --git a/Misc/NEWS.d/next/Library/2023-05-02-20-43-03.gh-issue-104102.vgSdEJ.rst b/Misc/NEWS.d/next/Library/2023-05-02-20-43-03.gh-issue-104102.vgSdEJ.rst deleted file mode 100644 index 7101de908a5004..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-02-20-43-03.gh-issue-104102.vgSdEJ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve performance of :meth:`pathlib.Path.glob` when evaluating patterns -that contain ``'../'`` segments. diff --git a/Misc/NEWS.d/next/Library/2023-05-02-21-05-30.gh-issue-104104.9tjplT.rst b/Misc/NEWS.d/next/Library/2023-05-02-21-05-30.gh-issue-104104.9tjplT.rst deleted file mode 100644 index 935a0e2a2bff18..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-02-21-05-30.gh-issue-104104.9tjplT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve performance of :meth:`pathlib.Path.glob` by using -:data:`re.IGNORECASE` to implement case-insensitive matching. diff --git a/Misc/NEWS.d/next/Library/2023-05-03-03-14-33.gh-issue-104114.RG26RD.rst b/Misc/NEWS.d/next/Library/2023-05-03-03-14-33.gh-issue-104114.RG26RD.rst deleted file mode 100644 index e705fea8326e7a..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-03-03-14-33.gh-issue-104114.RG26RD.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix issue where :meth:`pathlib.Path.glob` returns paths using the case of -non-wildcard segments for corresponding path segments, rather than the real -filesystem case. diff --git a/Misc/NEWS.d/next/Library/2023-05-03-16-50-24.gh-issue-104144.yNkjL8.rst b/Misc/NEWS.d/next/Library/2023-05-03-16-50-24.gh-issue-104144.yNkjL8.rst deleted file mode 100644 index b975d48ed3385c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-03-16-50-24.gh-issue-104144.yNkjL8.rst +++ /dev/null @@ -1,3 +0,0 @@ -Optimize :func:`asyncio.gather` when using :func:`asyncio.eager_task_factory` -to complete eagerly if all fututres completed eagerly. -Avoid scheduling done callbacks for futures that complete eagerly. diff --git a/Misc/NEWS.d/next/Library/2023-05-03-16-51-53.gh-issue-104144.653Q0P.rst b/Misc/NEWS.d/next/Library/2023-05-03-16-51-53.gh-issue-104144.653Q0P.rst deleted file mode 100644 index ced3b7cea04954..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-03-16-51-53.gh-issue-104144.653Q0P.rst +++ /dev/null @@ -1,2 +0,0 @@ -Optimize :class:`asyncio.TaskGroup` when using :func:`asyncio.eager_task_factory`. -Skip scheduling a done callback if a TaskGroup task completes eagerly. diff --git a/Misc/NEWS.d/next/Library/2023-05-03-19-22-24.gh-issue-90208.tI00da.rst b/Misc/NEWS.d/next/Library/2023-05-03-19-22-24.gh-issue-90208.tI00da.rst deleted file mode 100644 index 1fd9588bebd5d8..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-03-19-22-24.gh-issue-90208.tI00da.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fixed issue where :meth:`pathlib.Path.glob` returned incomplete results when -it encountered a :exc:`PermissionError`. This method now suppresses all -:exc:`OSError` exceptions, except those raised from calling -:meth:`~pathlib.Path.is_dir` on the top-level path. diff --git a/Misc/NEWS.d/next/Library/2023-05-05-18-52-22.gh-issue-65772.w5P5Wv.rst b/Misc/NEWS.d/next/Library/2023-05-05-18-52-22.gh-issue-65772.w5P5Wv.rst deleted file mode 100644 index 54b0190192863c..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-05-18-52-22.gh-issue-65772.w5P5Wv.rst +++ /dev/null @@ -1 +0,0 @@ -Remove unneeded comments and code in turtle.py. diff --git a/Misc/NEWS.d/next/Library/2023-05-06-20-37-46.gh-issue-102613.QZG9iX.rst b/Misc/NEWS.d/next/Library/2023-05-06-20-37-46.gh-issue-102613.QZG9iX.rst deleted file mode 100644 index 01f8b948d2cb65..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-06-20-37-46.gh-issue-102613.QZG9iX.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improve performance of :meth:`pathlib.Path.glob` when expanding recursive -wildcards ("``**``") by merging adjacent wildcards and de-duplicating -results only when necessary. diff --git a/Misc/NEWS.d/next/Library/2023-05-07-19-56-45.gh-issue-104265.fVblry.rst b/Misc/NEWS.d/next/Library/2023-05-07-19-56-45.gh-issue-104265.fVblry.rst deleted file mode 100644 index 9c582844bf909b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-07-19-56-45.gh-issue-104265.fVblry.rst +++ /dev/null @@ -1,4 +0,0 @@ -Prevent possible crash by disallowing instantiation of the -:class:`!_csv.Reader` and :class:`!_csv.Writer` types. -The regression was introduced in 3.10.0a4 with PR 23224 (:issue:`14935`). -Patch by Radislav Chugunov. diff --git a/Misc/NEWS.d/next/Library/2023-05-08-15-39-00.gh-issue-87695.f6iO7v.rst b/Misc/NEWS.d/next/Library/2023-05-08-15-39-00.gh-issue-87695.f6iO7v.rst deleted file mode 100644 index 7b677656bea308..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-08-15-39-00.gh-issue-87695.f6iO7v.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix issue where :meth:`pathlib.Path.glob` raised :exc:`OSError` when it -encountered a symlink to an overly long path. diff --git a/Misc/NEWS.d/next/Library/2023-05-08-15-50-59.gh-issue-104310.fXVSPY.rst b/Misc/NEWS.d/next/Library/2023-05-08-15-50-59.gh-issue-104310.fXVSPY.rst deleted file mode 100644 index 3743d569995f2e..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-08-15-50-59.gh-issue-104310.fXVSPY.rst +++ /dev/null @@ -1,3 +0,0 @@ -Users may now use ``importlib.util.allowing_all_extensions()`` (a context -manager) to temporarily disable the strict compatibility checks for -importing extension modules in subinterpreters. diff --git a/Misc/NEWS.d/next/Library/2023-05-08-20-57-17.gh-issue-104307.DSB93G.rst b/Misc/NEWS.d/next/Library/2023-05-08-20-57-17.gh-issue-104307.DSB93G.rst deleted file mode 100644 index 03775845450caa..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-08-20-57-17.gh-issue-104307.DSB93G.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`socket.getnameinfo` now releases the GIL while contacting the DNS server diff --git a/Misc/NEWS.d/next/Library/2023-05-08-23-01-59.gh-issue-104139.83Tnt-.rst b/Misc/NEWS.d/next/Library/2023-05-08-23-01-59.gh-issue-104139.83Tnt-.rst deleted file mode 100644 index 145e75f6dea6f4..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-08-23-01-59.gh-issue-104139.83Tnt-.rst +++ /dev/null @@ -1,3 +0,0 @@ -Teach :func:`urllib.parse.unsplit` to retain the ``"//"`` when assembling -``itms-services://?action=generate-bugs`` style `Apple Platform Deployment -`_ URLs. diff --git a/Misc/NEWS.d/next/Library/2023-05-09-18-46-24.gh-issue-104301.gNnbId.rst b/Misc/NEWS.d/next/Library/2023-05-09-18-46-24.gh-issue-104301.gNnbId.rst deleted file mode 100644 index a44ad765e62458..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-09-18-46-24.gh-issue-104301.gNnbId.rst +++ /dev/null @@ -1 +0,0 @@ -Allow leading whitespace in disambiguated statements in :mod:`pdb`. diff --git a/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst b/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst deleted file mode 100644 index f84ec5c8b3caf6..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-10-19-33-36.gh-issue-103000.j0KSfD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improve performance of :func:`dataclasses.asdict` for the common case where -*dict_factory* is ``dict``. Patch by David C Ellis. diff --git a/Misc/NEWS.d/next/Library/2023-05-11-01-07-42.gh-issue-102613.uMsokt.rst b/Misc/NEWS.d/next/Library/2023-05-11-01-07-42.gh-issue-102613.uMsokt.rst deleted file mode 100644 index 3b06964dc8d233..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-11-01-07-42.gh-issue-102613.uMsokt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix issue where :meth:`pathlib.Path.glob` raised :exc:`RecursionError` when -walking deep directory trees. diff --git a/Misc/NEWS.d/next/Library/2023-05-11-07-50-00.gh-issue-104392.YSllzt.rst b/Misc/NEWS.d/next/Library/2023-05-11-07-50-00.gh-issue-104392.YSllzt.rst deleted file mode 100644 index b441b2acd19f1b..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-11-07-50-00.gh-issue-104392.YSllzt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove undocumented and unused ``_paramspec_tvars`` attribute from some -classes in :mod:`typing`. diff --git a/Misc/NEWS.d/next/Library/2023-05-12-19-29-28.gh-issue-103857.0IzSxr.rst b/Misc/NEWS.d/next/Library/2023-05-12-19-29-28.gh-issue-103857.0IzSxr.rst deleted file mode 100644 index 6e8162d9ecc286..00000000000000 --- a/Misc/NEWS.d/next/Library/2023-05-12-19-29-28.gh-issue-103857.0IzSxr.rst +++ /dev/null @@ -1 +0,0 @@ -Update datetime deprecations' stracktrace to point to the calling line diff --git a/Misc/NEWS.d/next/Library/2023-05-19-19-46-22.gh-issue-99108.wqCg0t.rst b/Misc/NEWS.d/next/Library/2023-05-19-19-46-22.gh-issue-99108.wqCg0t.rst new file mode 100644 index 00000000000000..b595f1893609cc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-19-19-46-22.gh-issue-99108.wqCg0t.rst @@ -0,0 +1,3 @@ +We now release the GIL around built-in :mod:`hashlib` computations of +reasonable size for the SHA families and MD5 hash functions, matching +what our OpenSSL backed hash computations already does. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-02-20-13.gh-issue-104773.7K59zr.rst b/Misc/NEWS.d/next/Library/2023-05-23-02-20-13.gh-issue-104773.7K59zr.rst new file mode 100644 index 00000000000000..0f3162ef509a82 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-23-02-20-13.gh-issue-104773.7K59zr.rst @@ -0,0 +1,2 @@ +:pep:`594`: Remove the :mod:`!telnetlib` module, deprecated in Python 3.11. +Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2023-05-23-03-36-47.gh-issue-104780.P4e3Yf.rst b/Misc/NEWS.d/next/Library/2023-05-23-03-36-47.gh-issue-104780.P4e3Yf.rst new file mode 100644 index 00000000000000..acdca53b4bb7d4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-23-03-36-47.gh-issue-104780.P4e3Yf.rst @@ -0,0 +1,2 @@ +Remove the ``2to3`` program and the :mod:`!lib2to3` module, deprecated in +Python 3.11. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Security/2023-04-17-14-38-12.gh-issue-99108.720lG8.rst b/Misc/NEWS.d/next/Security/2023-04-17-14-38-12.gh-issue-99108.720lG8.rst deleted file mode 100644 index f259acf753831c..00000000000000 --- a/Misc/NEWS.d/next/Security/2023-04-17-14-38-12.gh-issue-99108.720lG8.rst +++ /dev/null @@ -1,2 +0,0 @@ -Upgrade built-in :mod:`hashlib` SHA3 implementation to a verified implementation -from the ``HACL*`` project. Used when OpenSSL is not present or lacks SHA3. diff --git a/Misc/NEWS.d/next/Security/2023-05-01-15-03-25.gh-issue-104049.b01Y3g.rst b/Misc/NEWS.d/next/Security/2023-05-01-15-03-25.gh-issue-104049.b01Y3g.rst deleted file mode 100644 index 969deb26bfeb95..00000000000000 --- a/Misc/NEWS.d/next/Security/2023-05-01-15-03-25.gh-issue-104049.b01Y3g.rst +++ /dev/null @@ -1,2 +0,0 @@ -Do not expose the local on-disk location in directory indexes -produced by :class:`http.client.SimpleHTTPRequestHandler`. diff --git a/Misc/NEWS.d/next/Security/2023-05-02-17-56-32.gh-issue-99889.l664SU.rst b/Misc/NEWS.d/next/Security/2023-05-02-17-56-32.gh-issue-99889.l664SU.rst deleted file mode 100644 index b7002e81b6b677..00000000000000 --- a/Misc/NEWS.d/next/Security/2023-05-02-17-56-32.gh-issue-99889.l664SU.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a security in flaw in :func:`uu.decode` that could allow for -directory traversal based on the input if no ``out_file`` was specified. diff --git a/Misc/NEWS.d/next/Tests/2022-11-06-18-42-38.gh-issue-75729.uGYJrv.rst b/Misc/NEWS.d/next/Tests/2022-11-06-18-42-38.gh-issue-75729.uGYJrv.rst deleted file mode 100644 index 8baecdfc31881f..00000000000000 --- a/Misc/NEWS.d/next/Tests/2022-11-06-18-42-38.gh-issue-75729.uGYJrv.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the :func:`os.spawn* ` tests failing on Windows -when the working directory or interpreter path contains spaces. diff --git a/Misc/NEWS.d/next/Tests/2023-03-17-22-00-47.gh-issue-102795.z21EoC.rst b/Misc/NEWS.d/next/Tests/2023-03-17-22-00-47.gh-issue-102795.z21EoC.rst deleted file mode 100644 index fe2afff91ece7a..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-03-17-22-00-47.gh-issue-102795.z21EoC.rst +++ /dev/null @@ -1 +0,0 @@ -fix use of poll in test_epoll's test_control_and_wait diff --git a/Misc/NEWS.d/next/Tests/2023-04-08-00-50-23.gh-issue-103329.M38tqF.rst b/Misc/NEWS.d/next/Tests/2023-04-08-00-50-23.gh-issue-103329.M38tqF.rst deleted file mode 100644 index 79448ed728040d..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-04-08-00-50-23.gh-issue-103329.M38tqF.rst +++ /dev/null @@ -1 +0,0 @@ -Regression tests for the behaviour of ``unittest.mock.PropertyMock`` were added. diff --git a/Misc/NEWS.d/next/Tests/2023-04-25-12-19-37.gh-issue-86275.-RoLIt.rst b/Misc/NEWS.d/next/Tests/2023-04-25-12-19-37.gh-issue-86275.-RoLIt.rst deleted file mode 100644 index 37ab74ffc441ed..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-04-25-12-19-37.gh-issue-86275.-RoLIt.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added property-based tests to the :mod:`zoneinfo` tests, along with stubs -for the ``hypothesis`` interface. (Patch by Paul Ganssle) diff --git a/Misc/NEWS.d/next/Tests/2023-05-15-02-22-44.gh-issue-104494.Bkrbfn.rst b/Misc/NEWS.d/next/Tests/2023-05-15-02-22-44.gh-issue-104494.Bkrbfn.rst deleted file mode 100644 index a320c48428b58b..00000000000000 --- a/Misc/NEWS.d/next/Tests/2023-05-15-02-22-44.gh-issue-104494.Bkrbfn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update ``test_pack_configure_in`` and ``test_place_configure_in`` -for changes to error message formatting in Tk 8.7. diff --git a/Misc/NEWS.d/next/Tests/2023-05-19-08-06-06.gh-issue-81005.-q7m9W.rst b/Misc/NEWS.d/next/Tests/2023-05-19-08-06-06.gh-issue-81005.-q7m9W.rst new file mode 100644 index 00000000000000..dfb653241e2607 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2023-05-19-08-06-06.gh-issue-81005.-q7m9W.rst @@ -0,0 +1,2 @@ +String tests are modified to reflect that ``str`` and ``unicode`` are merged +in Python 3. Patch by Daniel Fortunov. diff --git a/Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst b/Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst deleted file mode 100644 index 854e1cca967c42..00000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2023-05-11-15-12-11.gh-issue-104389.EiOhB3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Argument Clinic C converters now accept the ``unused`` keyword, for wrapping -a parameter with :c:macro:`Py_UNUSED`. Patch by Erlend E. Aasland. diff --git a/Misc/NEWS.d/next/Windows/2023-03-18-21-38-00.gh-issue-88013.Z3loxC.rst b/Misc/NEWS.d/next/Windows/2023-03-18-21-38-00.gh-issue-88013.Z3loxC.rst deleted file mode 100644 index 4ca3185ea1f65e..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-03-18-21-38-00.gh-issue-88013.Z3loxC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a bug where :exc:`TypeError` was raised when calling -:func:`ntpath.realpath` with a bytes parameter in some cases. diff --git a/Misc/NEWS.d/next/Windows/2023-03-24-11-25-28.gh-issue-102997.dredy2.rst b/Misc/NEWS.d/next/Windows/2023-03-24-11-25-28.gh-issue-102997.dredy2.rst deleted file mode 100644 index c8f7259aecba6f..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-03-24-11-25-28.gh-issue-102997.dredy2.rst +++ /dev/null @@ -1 +0,0 @@ -Update Windows installer to use SQLite 3.41.2. diff --git a/Misc/NEWS.d/next/Windows/2023-04-11-09-22-22.gh-issue-103088.6AJEuR.rst b/Misc/NEWS.d/next/Windows/2023-04-11-09-22-22.gh-issue-103088.6AJEuR.rst deleted file mode 100644 index f9f5343f4210dc..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-04-11-09-22-22.gh-issue-103088.6AJEuR.rst +++ /dev/null @@ -1 +0,0 @@ -Fixes venvs not working in bash on Windows across different disks diff --git a/Misc/NEWS.d/next/Windows/2023-04-12-10-49-21.gh-issue-103088.Yjj-qJ.rst b/Misc/NEWS.d/next/Windows/2023-04-12-10-49-21.gh-issue-103088.Yjj-qJ.rst deleted file mode 100644 index 1fee99da240378..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-04-12-10-49-21.gh-issue-103088.Yjj-qJ.rst +++ /dev/null @@ -1 +0,0 @@ -Fix virtual environment :file:`activate` script having incorrect line endings for Cygwin. diff --git a/Misc/NEWS.d/next/Windows/2023-04-24-15-51-11.gh-issue-82814.GI3UkZ.rst b/Misc/NEWS.d/next/Windows/2023-04-24-15-51-11.gh-issue-82814.GI3UkZ.rst deleted file mode 100644 index 5bd005ffacb800..00000000000000 --- a/Misc/NEWS.d/next/Windows/2023-04-24-15-51-11.gh-issue-82814.GI3UkZ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a potential ``[Errno 13] Permission denied`` when using :func:`shutil.copystat` -within Windows Subsystem for Linux (WSL) on a mounted filesystem by adding -``errno.EACCES`` to the list of ignored errors within the internal implementation. diff --git a/Misc/NEWS.d/next/macOS/2023-03-24-11-20-47.gh-issue-102997.ZgQkbq.rst b/Misc/NEWS.d/next/macOS/2023-03-24-11-20-47.gh-issue-102997.ZgQkbq.rst deleted file mode 100644 index d0b390a896b743..00000000000000 --- a/Misc/NEWS.d/next/macOS/2023-03-24-11-20-47.gh-issue-102997.ZgQkbq.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS installer to SQLite 3.41.2. diff --git a/Misc/NEWS.d/next/macOS/2023-04-04-13-37-28.gh-issue-103207.x0vvQp.rst b/Misc/NEWS.d/next/macOS/2023-04-04-13-37-28.gh-issue-103207.x0vvQp.rst deleted file mode 100644 index 3c176e3a6b5310..00000000000000 --- a/Misc/NEWS.d/next/macOS/2023-04-04-13-37-28.gh-issue-103207.x0vvQp.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add instructions to the macOS installer welcome display on how to workaround -the macOS 13 Ventura “The installer encountered an error” failure. diff --git a/Misc/NEWS.d/next/macOS/2023-04-24-18-37-48.gh-issue-60436.in-IyF.rst b/Misc/NEWS.d/next/macOS/2023-04-24-18-37-48.gh-issue-60436.in-IyF.rst deleted file mode 100644 index f274d3b898f15d..00000000000000 --- a/Misc/NEWS.d/next/macOS/2023-04-24-18-37-48.gh-issue-60436.in-IyF.rst +++ /dev/null @@ -1 +0,0 @@ -update curses textbox to additionally handle backspace using the ``curses.ascii.DEL`` key press. diff --git a/Misc/NEWS.d/next/macOS/2023-05-04-21-47-59.gh-issue-104180.lEJCwd.rst b/Misc/NEWS.d/next/macOS/2023-05-04-21-47-59.gh-issue-104180.lEJCwd.rst deleted file mode 100644 index b6b18dcfd81394..00000000000000 --- a/Misc/NEWS.d/next/macOS/2023-05-04-21-47-59.gh-issue-104180.lEJCwd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Support reading SOCKS proxy configuration from macOS System Configuration. -Patch by Sam Schott. diff --git a/Modules/Setup.bootstrap.in b/Modules/Setup.bootstrap.in index e3e9b96b0630df..8ef0f203a82a8e 100644 --- a/Modules/Setup.bootstrap.in +++ b/Modules/Setup.bootstrap.in @@ -21,6 +21,7 @@ itertools itertoolsmodule.c _sre _sre/sre.c _thread _threadmodule.c time timemodule.c +_typing _typingmodule.c _weakref _weakref.c # commonly used core modules diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 95409d48c0da02..6db567d713090d 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -41,7 +41,6 @@ @MODULE__QUEUE_TRUE@_queue _queuemodule.c @MODULE__RANDOM_TRUE@_random _randommodule.c @MODULE__STRUCT_TRUE@_struct _struct.c -@MODULE__TYPING_TRUE@_typing _typingmodule.c @MODULE__XXSUBINTERPRETERS_TRUE@_xxsubinterpreters _xxsubinterpretersmodule.c @MODULE__XXINTERPCHANNELS_TRUE@_xxinterpchannels _xxinterpchannelsmodule.c @MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 3830245abe87b3..7e33558dba3e32 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -526,7 +526,7 @@ future_init(FutureObj *fut, PyObject *loop) if (is_true < 0) { return -1; } - if (is_true && !_Py_IsFinalizing()) { + if (is_true && !_Py_IsInterpreterFinalizing(PyInterpreterState_Get())) { /* Only try to capture the traceback if the interpreter is not being finalized. The original motivation to add a `_Py_IsFinalizing()` call was to prevent SIGSEGV when a Future is created in a __del__ diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 8b417bdd0fb5b6..19e11780ec6e19 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5190,7 +5190,7 @@ datetime_utcfromtimestamp(PyObject *cls, PyObject *args) if (PyErr_WarnEx(PyExc_DeprecationWarning, "datetime.utcfromtimestamp() is deprecated and scheduled for removal " "in a future version. Use timezone-aware objects to represent " - "datetimes in UTC: datetime.now(datetime.UTC).", 1)) + "datetimes in UTC: datetime.fromtimestamp(timestamp, datetime.UTC).", 1)) { return NULL; } diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 42de3c675c2e5a..00d9f647ccfdf3 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -15,6 +15,8 @@ #include "Python.h" #include "structmember.h" // PyMemberDef +#include "expat.h" +#include "pyexpat.h" /* -------------------------------------------------------------------- */ /* configuration */ @@ -90,6 +92,8 @@ typedef struct { PyTypeObject *ElementIter_Type; PyTypeObject *TreeBuilder_Type; PyTypeObject *XMLParser_Type; + + struct PyExpat_CAPI *expat_capi; } elementtreestate; static struct PyModuleDef elementtreemodule; @@ -146,6 +150,8 @@ elementtree_clear(PyObject *m) Py_CLEAR(st->ElementIter_Type); Py_CLEAR(st->TreeBuilder_Type); Py_CLEAR(st->XMLParser_Type); + + st->expat_capi = NULL; return 0; } @@ -3031,14 +3037,7 @@ _elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag, /* ==================================================================== */ /* the expat interface */ -#include "expat.h" -#include "pyexpat.h" - -/* The PyExpat_CAPI structure is an immutable dispatch table, so it can be - * cached globally without being in per-module state. - */ -static struct PyExpat_CAPI *expat_capi; -#define EXPAT(func) (expat_capi->func) +#define EXPAT(st, func) ((st)->expat_capi->func) static XML_Memory_Handling_Suite ExpatMemoryHandler = { PyObject_Malloc, PyObject_Realloc, PyObject_Free}; @@ -3147,7 +3146,7 @@ expat_set_error(elementtreestate *st, enum XML_Error error_code, PyObject *errmsg, *error, *position, *code; errmsg = PyUnicode_FromFormat("%s: line %zd, column %zd", - message ? message : EXPAT(ErrorString)(error_code), + message ? message : EXPAT(st, ErrorString)(error_code), line, column); if (errmsg == NULL) return; @@ -3227,8 +3226,8 @@ expat_default_handler(XMLParserObject* self, const XML_Char* data_in, expat_set_error( st, XML_ERROR_UNDEFINED_ENTITY, - EXPAT(GetErrorLineNumber)(self->parser), - EXPAT(GetErrorColumnNumber)(self->parser), + EXPAT(st, GetErrorLineNumber)(self->parser), + EXPAT(st, GetErrorColumnNumber)(self->parser), message ); } @@ -3648,8 +3647,8 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, Py_CLEAR(self->entity); return -1; } - - self->parser = EXPAT(ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}"); + elementtreestate *st = self->state; + self->parser = EXPAT(st, ParserCreate_MM)(encoding, &ExpatMemoryHandler, "}"); if (!self->parser) { Py_CLEAR(self->entity); Py_CLEAR(self->names); @@ -3657,15 +3656,14 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, return -1; } /* expat < 2.1.0 has no XML_SetHashSalt() */ - if (EXPAT(SetHashSalt) != NULL) { - EXPAT(SetHashSalt)(self->parser, + if (EXPAT(st, SetHashSalt) != NULL) { + EXPAT(st, SetHashSalt)(self->parser, (unsigned long)_Py_HashSecret.expat.hashsalt); } if (target != Py_None) { Py_INCREF(target); } else { - elementtreestate *st = self->state; target = treebuilder_new(st->TreeBuilder_Type, NULL, NULL); if (!target) { Py_CLEAR(self->entity); @@ -3713,43 +3711,43 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target, } /* configure parser */ - EXPAT(SetUserData)(self->parser, self); + EXPAT(st, SetUserData)(self->parser, self); if (self->handle_start_ns || self->handle_end_ns) - EXPAT(SetNamespaceDeclHandler)( + EXPAT(st, SetNamespaceDeclHandler)( self->parser, (XML_StartNamespaceDeclHandler) expat_start_ns_handler, (XML_EndNamespaceDeclHandler) expat_end_ns_handler ); - EXPAT(SetElementHandler)( + EXPAT(st, SetElementHandler)( self->parser, (XML_StartElementHandler) expat_start_handler, (XML_EndElementHandler) expat_end_handler ); - EXPAT(SetDefaultHandlerExpand)( + EXPAT(st, SetDefaultHandlerExpand)( self->parser, (XML_DefaultHandler) expat_default_handler ); - EXPAT(SetCharacterDataHandler)( + EXPAT(st, SetCharacterDataHandler)( self->parser, (XML_CharacterDataHandler) expat_data_handler ); if (self->handle_comment) - EXPAT(SetCommentHandler)( + EXPAT(st, SetCommentHandler)( self->parser, (XML_CommentHandler) expat_comment_handler ); if (self->handle_pi) - EXPAT(SetProcessingInstructionHandler)( + EXPAT(st, SetProcessingInstructionHandler)( self->parser, (XML_ProcessingInstructionHandler) expat_pi_handler ); - EXPAT(SetStartDoctypeDeclHandler)( + EXPAT(st, SetStartDoctypeDeclHandler)( self->parser, (XML_StartDoctypeDeclHandler) expat_start_doctype_handler ); - EXPAT(SetUnknownEncodingHandler)( + EXPAT(st, SetUnknownEncodingHandler)( self->parser, - EXPAT(DefaultUnknownEncodingHandler), NULL + EXPAT(st, DefaultUnknownEncodingHandler), NULL ); return 0; @@ -3779,10 +3777,11 @@ xmlparser_gc_traverse(XMLParserObject *self, visitproc visit, void *arg) static int xmlparser_gc_clear(XMLParserObject *self) { + elementtreestate *st = self->state; if (self->parser != NULL) { XML_Parser parser = self->parser; self->parser = NULL; - EXPAT(ParserFree)(parser); + EXPAT(st, ParserFree)(parser); } Py_CLEAR(self->handle_close); @@ -3830,7 +3829,7 @@ expat_parse(elementtreestate *st, XMLParserObject *self, const char *data, int ok; assert(!PyErr_Occurred()); - ok = EXPAT(Parse)(self->parser, data, data_len, final); + ok = EXPAT(st, Parse)(self->parser, data, data_len, final); if (PyErr_Occurred()) return NULL; @@ -3838,9 +3837,9 @@ expat_parse(elementtreestate *st, XMLParserObject *self, const char *data, if (!ok) { expat_set_error( st, - EXPAT(GetErrorCode)(self->parser), - EXPAT(GetErrorLineNumber)(self->parser), - EXPAT(GetErrorColumnNumber)(self->parser), + EXPAT(st, GetErrorCode)(self->parser), + EXPAT(st, GetErrorLineNumber)(self->parser), + EXPAT(st, GetErrorColumnNumber)(self->parser), NULL ); return NULL; @@ -3911,7 +3910,7 @@ _elementtree_XMLParser_feed(XMLParserObject *self, PyObject *data) return NULL; } /* Explicitly set UTF-8 encoding. Return code ignored. */ - (void)EXPAT(SetEncoding)(self->parser, "utf-8"); + (void)EXPAT(st, SetEncoding)(self->parser, "utf-8"); return expat_parse(st, self, data_ptr, (int)data_len, 0); } @@ -4099,27 +4098,27 @@ _elementtree_XMLParser__setevents_impl(XMLParserObject *self, Py_XSETREF(target->end_event_obj, Py_NewRef(event_name_obj)); } else if (strcmp(event_name, "start-ns") == 0) { Py_XSETREF(target->start_ns_event_obj, Py_NewRef(event_name_obj)); - EXPAT(SetNamespaceDeclHandler)( + EXPAT(st, SetNamespaceDeclHandler)( self->parser, (XML_StartNamespaceDeclHandler) expat_start_ns_handler, (XML_EndNamespaceDeclHandler) expat_end_ns_handler ); } else if (strcmp(event_name, "end-ns") == 0) { Py_XSETREF(target->end_ns_event_obj, Py_NewRef(event_name_obj)); - EXPAT(SetNamespaceDeclHandler)( + EXPAT(st, SetNamespaceDeclHandler)( self->parser, (XML_StartNamespaceDeclHandler) expat_start_ns_handler, (XML_EndNamespaceDeclHandler) expat_end_ns_handler ); } else if (strcmp(event_name, "comment") == 0) { Py_XSETREF(target->comment_event_obj, Py_NewRef(event_name_obj)); - EXPAT(SetCommentHandler)( + EXPAT(st, SetCommentHandler)( self->parser, (XML_CommentHandler) expat_comment_handler ); } else if (strcmp(event_name, "pi") == 0) { Py_XSETREF(target->pi_event_obj, Py_NewRef(event_name_obj)); - EXPAT(SetProcessingInstructionHandler)( + EXPAT(st, SetProcessingInstructionHandler)( self->parser, (XML_ProcessingInstructionHandler) expat_pi_handler ); @@ -4344,14 +4343,14 @@ module_exec(PyObject *m) goto error; /* link against pyexpat */ - expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); - if (expat_capi) { + st->expat_capi = PyCapsule_Import(PyExpat_CAPSULE_NAME, 0); + if (st->expat_capi) { /* check that it's usable */ - if (strcmp(expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || - (size_t)expat_capi->size < sizeof(struct PyExpat_CAPI) || - expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || - expat_capi->MINOR_VERSION != XML_MINOR_VERSION || - expat_capi->MICRO_VERSION != XML_MICRO_VERSION) { + if (strcmp(st->expat_capi->magic, PyExpat_CAPI_MAGIC) != 0 || + (size_t)st->expat_capi->size < sizeof(struct PyExpat_CAPI) || + st->expat_capi->MAJOR_VERSION != XML_MAJOR_VERSION || + st->expat_capi->MINOR_VERSION != XML_MINOR_VERSION || + st->expat_capi->MICRO_VERSION != XML_MICRO_VERSION) { PyErr_SetString(PyExc_ImportError, "pyexpat version is incompatible"); goto error; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 99d0b72819137e..4b425f4147513e 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -227,12 +227,16 @@ get_hashlib_state(PyObject *module) typedef struct { PyObject_HEAD EVP_MD_CTX *ctx; /* OpenSSL message digest context */ + // Prevents undefined behavior via multiple threads entering the C API. + // The lock will be NULL before threaded access has been enabled. PyThread_type_lock lock; /* OpenSSL context lock */ } EVPobject; typedef struct { PyObject_HEAD HMAC_CTX *ctx; /* OpenSSL hmac context */ + // Prevents undefined behavior via multiple threads entering the C API. + // The lock will be NULL before threaded access has been enabled. PyThread_type_lock lock; /* HMAC context lock */ } HMACobject; @@ -896,6 +900,8 @@ py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj, if (view.buf && view.len) { if (view.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ Py_BEGIN_ALLOW_THREADS result = EVP_hash(self, view.buf, view.len); Py_END_ALLOW_THREADS diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 6f291c34496064..f30d54a5e11b0a 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -293,7 +293,8 @@ _enter_buffered_busy(buffered *self) "reentrant call inside %R", self); return 0; } - relax_locking = _Py_IsFinalizing(); + PyInterpreterState *interp = PyInterpreterState_Get(); + relax_locking = _Py_IsInterpreterFinalizing(interp); Py_BEGIN_ALLOW_THREADS if (!relax_locking) st = PyThread_acquire_lock(self->lock, 1); @@ -2423,13 +2424,6 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, #include "clinic/bufferedio.c.h" #undef clinic_state -static int -bufferediobase_traverse(PyObject *self, visitproc visit, void *arg) -{ - Py_VISIT(Py_TYPE(self)); - return 0; -} - static PyMethodDef bufferediobase_methods[] = { _IO__BUFFEREDIOBASE_DETACH_METHODDEF _IO__BUFFEREDIOBASE_READ_METHODDEF @@ -2443,13 +2437,13 @@ static PyMethodDef bufferediobase_methods[] = { static PyType_Slot bufferediobase_slots[] = { {Py_tp_doc, (void *)bufferediobase_doc}, {Py_tp_methods, bufferediobase_methods}, - {Py_tp_traverse, bufferediobase_traverse}, {0, NULL}, }; +/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */ PyType_Spec bufferediobase_spec = { .name = "_io._BufferedIOBase", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = bufferediobase_slots, }; diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c index 14d48813aefe83..bcb498d9c5b5de 100644 --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -1036,13 +1036,6 @@ rawiobase_write(PyObject *self, PyObject *args) return NULL; } -static int -rawiobase_traverse(PyObject *self, visitproc visit, void *arg) -{ - Py_VISIT(Py_TYPE(self)); - return 0; -} - static PyMethodDef rawiobase_methods[] = { _IO__RAWIOBASE_READ_METHODDEF _IO__RAWIOBASE_READALL_METHODDEF @@ -1054,13 +1047,13 @@ static PyMethodDef rawiobase_methods[] = { static PyType_Slot rawiobase_slots[] = { {Py_tp_doc, (void *)rawiobase_doc}, {Py_tp_methods, rawiobase_methods}, - {Py_tp_traverse, rawiobase_traverse}, {0, NULL}, }; +/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */ PyType_Spec rawiobase_spec = { .name = "_io._RawIOBase", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = rawiobase_slots, }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index e858a1fb498f82..46411c70a96753 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -167,12 +167,6 @@ textiobase_errors_get(PyObject *self, void *context) Py_RETURN_NONE; } -static int -textiobase_traverse(PyObject *self, visitproc visit, void *arg) -{ - Py_VISIT(Py_TYPE(self)); - return 0; -} static PyMethodDef textiobase_methods[] = { _IO__TEXTIOBASE_DETACH_METHODDEF @@ -193,13 +187,13 @@ static PyType_Slot textiobase_slots[] = { {Py_tp_doc, (void *)textiobase_doc}, {Py_tp_methods, textiobase_methods}, {Py_tp_getset, textiobase_getset}, - {Py_tp_traverse, textiobase_traverse}, {0, NULL}, }; +/* Do not set Py_TPFLAGS_HAVE_GC so that tp_traverse and tp_clear are inherited */ PyType_Spec textiobase_spec = { .name = "_io._TextIOBase", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = textiobase_slots, }; diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 2bf83db0e228fb..1b7fe71186a163 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -160,16 +160,17 @@ _sanity_check_python_fd_sequence(PyObject *fd_sequence) /* Is fd found in the sorted Python Sequence? */ static int -_is_fd_in_sorted_fd_sequence(int fd, PyObject *fd_sequence) +_is_fd_in_sorted_fd_sequence(int fd, int *fd_sequence, + Py_ssize_t fd_sequence_len) { /* Binary search. */ Py_ssize_t search_min = 0; - Py_ssize_t search_max = PyTuple_GET_SIZE(fd_sequence) - 1; + Py_ssize_t search_max = fd_sequence_len - 1; if (search_max < 0) return 0; do { long middle = (search_min + search_max) / 2; - long middle_fd = PyLong_AsLong(PyTuple_GET_ITEM(fd_sequence, middle)); + long middle_fd = fd_sequence[middle]; if (fd == middle_fd) return 1; if (fd > middle_fd) @@ -180,8 +181,18 @@ _is_fd_in_sorted_fd_sequence(int fd, PyObject *fd_sequence) return 0; } +/* + * Do all the Python C API calls in the parent process to turn the pass_fds + * "py_fds_to_keep" tuple into a C array. The caller owns allocation and + * freeing of the array. + * + * On error an unknown number of array elements may have been filled in. + * A Python exception has been set when an error is returned. + * + * Returns: -1 on error, 0 on success. + */ static int -make_inheritable(PyObject *py_fds_to_keep, int errpipe_write) +convert_fds_to_keep_to_c(PyObject *py_fds_to_keep, int *c_fds_to_keep) { Py_ssize_t i, len; @@ -189,15 +200,37 @@ make_inheritable(PyObject *py_fds_to_keep, int errpipe_write) for (i = 0; i < len; ++i) { PyObject* fdobj = PyTuple_GET_ITEM(py_fds_to_keep, i); long fd = PyLong_AsLong(fdobj); - assert(!PyErr_Occurred()); - assert(0 <= fd && fd <= INT_MAX); + if (PyErr_Occurred()) { + return -1; + } + if (fd < 0 || fd > INT_MAX) { + PyErr_SetString(PyExc_ValueError, + "fd out of range in fds_to_keep."); + return -1; + } + c_fds_to_keep[i] = (int)fd; + } + return 0; +} + + +/* This function must be async-signal-safe as it is called from child_exec() + * after fork() or vfork(). + */ +static int +make_inheritable(int *c_fds_to_keep, Py_ssize_t len, int errpipe_write) +{ + Py_ssize_t i; + + for (i = 0; i < len; ++i) { + int fd = c_fds_to_keep[i]; if (fd == errpipe_write) { - /* errpipe_write is part of py_fds_to_keep. It must be closed at + /* errpipe_write is part of fds_to_keep. It must be closed at exec(), but kept open in the child process until exec() is called. */ continue; } - if (_Py_set_inheritable_async_safe((int)fd, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe(fd, 1, NULL) < 0) return -1; } return 0; @@ -233,7 +266,7 @@ safe_get_max_fd(void) /* Close all file descriptors in the given range except for those in - * py_fds_to_keep by invoking closer on each subrange. + * fds_to_keep by invoking closer on each subrange. * * If end_fd == -1, it's guessed via safe_get_max_fd(), but it isn't * possible to know for sure what the max fd to go up to is for @@ -243,19 +276,18 @@ safe_get_max_fd(void) static int _close_range_except(int start_fd, int end_fd, - PyObject *py_fds_to_keep, + int *fds_to_keep, + Py_ssize_t fds_to_keep_len, int (*closer)(int, int)) { if (end_fd == -1) { end_fd = Py_MIN(safe_get_max_fd(), INT_MAX); } - Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep); Py_ssize_t keep_seq_idx; - /* As py_fds_to_keep is sorted we can loop through the list closing + /* As fds_to_keep is sorted we can loop through the list closing * fds in between any in the keep list falling within our range. */ - for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) { - PyObject* py_keep_fd = PyTuple_GET_ITEM(py_fds_to_keep, keep_seq_idx); - int keep_fd = PyLong_AsLong(py_keep_fd); + for (keep_seq_idx = 0; keep_seq_idx < fds_to_keep_len; ++keep_seq_idx) { + int keep_fd = fds_to_keep[keep_seq_idx]; if (keep_fd < start_fd) continue; if (closer(start_fd, keep_fd - 1) != 0) @@ -295,7 +327,7 @@ _brute_force_closer(int first, int last) } /* Close all open file descriptors in the range from start_fd and higher - * Do not close any in the sorted py_fds_to_keep list. + * Do not close any in the sorted fds_to_keep list. * * This version is async signal safe as it does not make any unsafe C library * calls, malloc calls or handle any locks. It is _unfortunate_ to be forced @@ -310,14 +342,16 @@ _brute_force_closer(int first, int last) * it with some cpp #define magic to work on other OSes as well if you want. */ static void -_close_open_fds_safe(int start_fd, PyObject* py_fds_to_keep) +_close_open_fds_safe(int start_fd, int *fds_to_keep, Py_ssize_t fds_to_keep_len) { int fd_dir_fd; fd_dir_fd = _Py_open_noraise(FD_DIR, O_RDONLY); if (fd_dir_fd == -1) { /* No way to get a list of open fds. */ - _close_range_except(start_fd, -1, py_fds_to_keep, _brute_force_closer); + _close_range_except(start_fd, -1, + fds_to_keep, fds_to_keep_len, + _brute_force_closer); return; } else { char buffer[sizeof(struct linux_dirent64)]; @@ -336,7 +370,8 @@ _close_open_fds_safe(int start_fd, PyObject* py_fds_to_keep) if ((fd = _pos_int_from_ascii(entry->d_name)) < 0) continue; /* Not a number. */ if (fd != fd_dir_fd && fd >= start_fd && - !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) { + !_is_fd_in_sorted_fd_sequence(fd, fds_to_keep, + fds_to_keep_len)) { close(fd); } } @@ -357,7 +392,7 @@ _unsafe_closer(int first, int last) } /* Close all open file descriptors from start_fd and higher. - * Do not close any in the sorted py_fds_to_keep tuple. + * Do not close any in the sorted fds_to_keep tuple. * * This function violates the strict use of async signal safe functions. :( * It calls opendir(), readdir() and closedir(). Of these, the one most @@ -370,11 +405,13 @@ _unsafe_closer(int first, int last) * http://womble.decadent.org.uk/readdir_r-advisory.html */ static void -_close_open_fds_maybe_unsafe(int start_fd, PyObject* py_fds_to_keep) +_close_open_fds_maybe_unsafe(int start_fd, int *fds_to_keep, + Py_ssize_t fds_to_keep_len) { DIR *proc_fd_dir; #ifndef HAVE_DIRFD - while (_is_fd_in_sorted_fd_sequence(start_fd, py_fds_to_keep)) { + while (_is_fd_in_sorted_fd_sequence(start_fd, fds_to_keep, + fds_to_keep_len)) { ++start_fd; } /* Close our lowest fd before we call opendir so that it is likely to @@ -393,7 +430,8 @@ _close_open_fds_maybe_unsafe(int start_fd, PyObject* py_fds_to_keep) proc_fd_dir = opendir(FD_DIR); if (!proc_fd_dir) { /* No way to get a list of open fds. */ - _close_range_except(start_fd, -1, py_fds_to_keep, _unsafe_closer); + _close_range_except(start_fd, -1, fds_to_keep, fds_to_keep_len, + _unsafe_closer); } else { struct dirent *dir_entry; #ifdef HAVE_DIRFD @@ -407,14 +445,16 @@ _close_open_fds_maybe_unsafe(int start_fd, PyObject* py_fds_to_keep) if ((fd = _pos_int_from_ascii(dir_entry->d_name)) < 0) continue; /* Not a number. */ if (fd != fd_used_by_opendir && fd >= start_fd && - !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) { + !_is_fd_in_sorted_fd_sequence(fd, fds_to_keep, + fds_to_keep_len)) { close(fd); } errno = 0; } if (errno) { /* readdir error, revert behavior. Highly Unlikely. */ - _close_range_except(start_fd, -1, py_fds_to_keep, _unsafe_closer); + _close_range_except(start_fd, -1, fds_to_keep, fds_to_keep_len, + _unsafe_closer); } closedir(proc_fd_dir); } @@ -442,16 +482,16 @@ _close_range_closer(int first, int last) #endif static void -_close_open_fds(int start_fd, PyObject* py_fds_to_keep) +_close_open_fds(int start_fd, int *fds_to_keep, Py_ssize_t fds_to_keep_len) { #ifdef HAVE_ASYNC_SAFE_CLOSE_RANGE if (_close_range_except( - start_fd, INT_MAX, py_fds_to_keep, + start_fd, INT_MAX, fds_to_keep, fds_to_keep_len, _close_range_closer) == 0) { return; } #endif - _close_open_fds_fallback(start_fd, py_fds_to_keep); + _close_open_fds_fallback(start_fd, fds_to_keep, fds_to_keep_len); } #ifdef VFORK_USABLE @@ -544,7 +584,7 @@ child_exec(char *const exec_array[], Py_ssize_t extra_group_size, const gid_t *extra_groups, uid_t uid, int child_umask, const void *child_sigmask, - PyObject *py_fds_to_keep, + int *fds_to_keep, Py_ssize_t fds_to_keep_len, PyObject *preexec_fn, PyObject *preexec_fn_args_tuple) { @@ -554,7 +594,7 @@ child_exec(char *const exec_array[], /* Buffer large enough to hold a hex integer. We can't malloc. */ char hex_errno[sizeof(saved_errno)*2+1]; - if (make_inheritable(py_fds_to_keep, errpipe_write) < 0) + if (make_inheritable(fds_to_keep, fds_to_keep_len, errpipe_write) < 0) goto error; /* Close parent's pipe ends. */ @@ -676,7 +716,7 @@ child_exec(char *const exec_array[], /* close FDs after executing preexec_fn, which might open FDs */ if (close_fds) { /* TODO HP-UX could use pstat_getproc() if anyone cares about it. */ - _close_open_fds(3, py_fds_to_keep); + _close_open_fds(3, fds_to_keep, fds_to_keep_len); } /* This loop matches the Lib/os.py _execvpe()'s PATH search when */ @@ -750,7 +790,7 @@ do_fork_exec(char *const exec_array[], Py_ssize_t extra_group_size, const gid_t *extra_groups, uid_t uid, int child_umask, const void *child_sigmask, - PyObject *py_fds_to_keep, + int *fds_to_keep, Py_ssize_t fds_to_keep_len, PyObject *preexec_fn, PyObject *preexec_fn_args_tuple) { @@ -801,7 +841,8 @@ do_fork_exec(char *const exec_array[], close_fds, restore_signals, call_setsid, pgid_to_set, gid, extra_group_size, extra_groups, uid, child_umask, child_sigmask, - py_fds_to_keep, preexec_fn, preexec_fn_args_tuple); + fds_to_keep, fds_to_keep_len, + preexec_fn, preexec_fn_args_tuple); _exit(255); return 0; /* Dead code to avoid a potential compiler warning. */ } @@ -881,6 +922,8 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, Py_ssize_t extra_group_size = 0; int need_after_fork = 0; int saved_errno = 0; + int *c_fds_to_keep = NULL; + Py_ssize_t fds_to_keep_len = PyTuple_GET_SIZE(py_fds_to_keep); PyInterpreterState *interp = PyInterpreterState_Get(); if ((preexec_fn != Py_None) && (interp != PyInterpreterState_Main())) { @@ -1031,6 +1074,15 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, #endif /* HAVE_SETREUID */ } + c_fds_to_keep = PyMem_Malloc(fds_to_keep_len * sizeof(int)); + if (c_fds_to_keep == NULL) { + PyErr_SetString(PyExc_MemoryError, "failed to malloc c_fds_to_keep"); + goto cleanup; + } + if (convert_fds_to_keep_to_c(py_fds_to_keep, c_fds_to_keep) < 0) { + goto cleanup; + } + /* This must be the last thing done before fork() because we do not * want to call PyOS_BeforeFork() if there is any chance of another * error leading to the cleanup: code without calling fork(). */ @@ -1073,7 +1125,8 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, close_fds, restore_signals, call_setsid, pgid_to_set, gid, extra_group_size, extra_groups, uid, child_umask, old_sigmask, - py_fds_to_keep, preexec_fn, preexec_fn_args_tuple); + c_fds_to_keep, fds_to_keep_len, + preexec_fn, preexec_fn_args_tuple); /* Parent (original) process */ if (pid == (pid_t)-1) { @@ -1103,6 +1156,10 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, PyOS_AfterFork_Parent(); cleanup: + if (c_fds_to_keep != NULL) { + PyMem_Free(c_fds_to_keep); + } + if (saved_errno != 0) { errno = saved_errno; /* We can't call this above as PyOS_AfterFork_Parent() calls back diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 7bbb462ed54dfa..5c57a4101c4a69 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -419,7 +419,7 @@ connection_close(pysqlite_Connection *self) { /* If close is implicitly called as a result of interpreter * tear-down, we must not call back into Python. */ - if (_Py_IsFinalizing()) { + if (_Py_IsInterpreterFinalizing(PyInterpreterState_Get())) { remove_callbacks(self->db); } (void)connection_exec_stmt(self, "ROLLBACK"); diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 016a5a5cbca548..59fd401cac270b 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1330,10 +1330,8 @@ _get_peer_alt_names (_sslmodulestate *state, X509 *certificate) { p[0], p[1], p[2], p[3] ); } else if (name->d.ip->length == 16) { - /* PyUnicode_FromFormat() does not support %X */ unsigned char *p = name->d.ip->data; - len = sprintf( - buf, + v = PyUnicode_FromFormat( "%X:%X:%X:%X:%X:%X:%X:%X", p[0] << 8 | p[1], p[2] << 8 | p[3], @@ -1344,7 +1342,6 @@ _get_peer_alt_names (_sslmodulestate *state, X509 *certificate) { p[12] << 8 | p[13], p[14] << 8 | p[15] ); - v = PyUnicode_FromStringAndSize(buf, len); } else { v = PyUnicode_FromString(""); } @@ -6153,6 +6150,18 @@ sslmodule_init_strings(PyObject *module) return 0; } +static int +sslmodule_init_lock(PyObject *module) +{ + _sslmodulestate *state = get_ssl_state(module); + state->keylog_lock = PyThread_allocate_lock(); + if (state->keylog_lock == NULL) { + PyErr_NoMemory(); + return -1; + } + return 0; +} + static PyModuleDef_Slot sslmodule_slots[] = { {Py_mod_exec, sslmodule_init_types}, {Py_mod_exec, sslmodule_init_exceptions}, @@ -6161,9 +6170,8 @@ static PyModuleDef_Slot sslmodule_slots[] = { {Py_mod_exec, sslmodule_init_constants}, {Py_mod_exec, sslmodule_init_versioninfo}, {Py_mod_exec, sslmodule_init_strings}, - // XXX gh-103092: fix isolation. - {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, - //{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_exec, sslmodule_init_lock}, + {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {0, NULL} }; @@ -6222,6 +6230,8 @@ static void sslmodule_free(void *m) { sslmodule_clear((PyObject *)m); + _sslmodulestate *state = get_ssl_state(m); + PyThread_free_lock(state->keylog_lock); } static struct PyModuleDef _sslmodule_def = { diff --git a/Modules/_ssl.h b/Modules/_ssl.h index c1da8b46b536d3..22d93ddcc6d6eb 100644 --- a/Modules/_ssl.h +++ b/Modules/_ssl.h @@ -33,6 +33,8 @@ typedef struct { PyObject *str_reason; PyObject *str_verify_code; PyObject *str_verify_message; + /* keylog lock */ + PyThread_type_lock keylog_lock; } _sslmodulestate; static struct PyModuleDef _sslmodule_def; diff --git a/Modules/_ssl/debughelpers.c b/Modules/_ssl/debughelpers.c index 217f224942556e..a81f0aad05a802 100644 --- a/Modules/_ssl/debughelpers.c +++ b/Modules/_ssl/debughelpers.c @@ -118,30 +118,22 @@ _PySSL_keylog_callback(const SSL *ssl, const char *line) PyGILState_STATE threadstate; PySSLSocket *ssl_obj = NULL; /* ssl._SSLSocket, borrowed ref */ int res, e; - static PyThread_type_lock *lock = NULL; threadstate = PyGILState_Ensure(); ssl_obj = (PySSLSocket *)SSL_get_app_data(ssl); assert(Py_IS_TYPE(ssl_obj, get_state_sock(ssl_obj)->PySSLSocket_Type)); + PyThread_type_lock lock = get_state_sock(ssl_obj)->keylog_lock; + assert(lock != NULL); if (ssl_obj->ctx->keylog_bio == NULL) { return; } - - /* Allocate a static lock to synchronize writes to keylog file. + /* * The lock is neither released on exit nor on fork(). The lock is * also shared between all SSLContexts although contexts may write to * their own files. IMHO that's good enough for a non-performance * critical debug helper. */ - if (lock == NULL) { - lock = PyThread_allocate_lock(); - if (lock == NULL) { - PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock"); - ssl_obj->exc = PyErr_GetRaisedException(); - return; - } - } PySSL_BEGIN_ALLOW_THREADS PyThread_acquire_lock(lock, 1); diff --git a/Modules/_testcapi/README.txt b/Modules/_testcapi/README.txt index 134b6efc638095..8a65e7abf77009 100644 --- a/Modules/_testcapi/README.txt +++ b/Modules/_testcapi/README.txt @@ -1,3 +1,10 @@ Tests in this directory are compiled into the _testcapi extension. The main file for the extension is Modules/_testcapimodule.c, which calls `_PyTestCapi_Init_*` from these functions. + +General guideline when writing test code for C API. +* Use Argument Clinic to minimise the amount of boilerplate code. +* Add a newline between the argument spec and the docstring. +* If a test description is needed, make sure the added docstring clearly and succinctly describes purpose of the function. +* DRY, use the clone feature of Argument Clinic. +* Try to avoid adding new interned strings; reuse existing parameter names if possible. Use the `as` feature of Argument Clinic to override the C variable name, if needed. diff --git a/Modules/_testcapi/clinic/exceptions.c.h b/Modules/_testcapi/clinic/exceptions.c.h new file mode 100644 index 00000000000000..2cc4ef3dc0d497 --- /dev/null +++ b/Modules/_testcapi/clinic/exceptions.c.h @@ -0,0 +1,398 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(_testcapi_err_set_raised__doc__, +"err_set_raised($module, exception, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_ERR_SET_RAISED_METHODDEF \ + {"err_set_raised", (PyCFunction)_testcapi_err_set_raised, METH_O, _testcapi_err_set_raised__doc__}, + +PyDoc_STRVAR(_testcapi_exception_print__doc__, +"exception_print($module, exception, legacy=False, /)\n" +"--\n" +"\n" +"To test the format of exceptions as printed out."); + +#define _TESTCAPI_EXCEPTION_PRINT_METHODDEF \ + {"exception_print", _PyCFunction_CAST(_testcapi_exception_print), METH_FASTCALL, _testcapi_exception_print__doc__}, + +static PyObject * +_testcapi_exception_print_impl(PyObject *module, PyObject *exc, int legacy); + +static PyObject * +_testcapi_exception_print(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc; + int legacy = 0; + + if (!_PyArg_CheckPositional("exception_print", nargs, 1, 2)) { + goto exit; + } + exc = args[0]; + if (nargs < 2) { + goto skip_optional; + } + legacy = PyObject_IsTrue(args[1]); + if (legacy < 0) { + goto exit; + } +skip_optional: + return_value = _testcapi_exception_print_impl(module, exc, legacy); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_make_exception_with_doc__doc__, +"make_exception_with_doc($module, /, name, doc=,\n" +" base=, dict=)\n" +"--\n" +"\n" +"Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException). Run via Lib/test/test_exceptions.py"); + +#define _TESTCAPI_MAKE_EXCEPTION_WITH_DOC_METHODDEF \ + {"make_exception_with_doc", _PyCFunction_CAST(_testcapi_make_exception_with_doc), METH_FASTCALL|METH_KEYWORDS, _testcapi_make_exception_with_doc__doc__}, + +static PyObject * +_testcapi_make_exception_with_doc_impl(PyObject *module, const char *name, + const char *doc, PyObject *base, + PyObject *dict); + +static PyObject * +_testcapi_make_exception_with_doc(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 4 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(name), &_Py_ID(doc), &_Py_ID(base), &_Py_ID(dict), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", "doc", "base", "dict", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "make_exception_with_doc", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[4]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1; + const char *name; + const char *doc = NULL; + PyObject *base = NULL; + PyObject *dict = NULL; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 4, 0, argsbuf); + if (!args) { + goto exit; + } + if (!PyUnicode_Check(args[0])) { + _PyArg_BadArgument("make_exception_with_doc", "argument 'name'", "str", args[0]); + goto exit; + } + Py_ssize_t name_length; + name = PyUnicode_AsUTF8AndSize(args[0], &name_length); + if (name == NULL) { + goto exit; + } + if (strlen(name) != (size_t)name_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (!noptargs) { + goto skip_optional_pos; + } + if (args[1]) { + if (!PyUnicode_Check(args[1])) { + _PyArg_BadArgument("make_exception_with_doc", "argument 'doc'", "str", args[1]); + goto exit; + } + Py_ssize_t doc_length; + doc = PyUnicode_AsUTF8AndSize(args[1], &doc_length); + if (doc == NULL) { + goto exit; + } + if (strlen(doc) != (size_t)doc_length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + goto exit; + } + if (!--noptargs) { + goto skip_optional_pos; + } + } + if (args[2]) { + base = args[2]; + if (!--noptargs) { + goto skip_optional_pos; + } + } + dict = args[3]; +skip_optional_pos: + return_value = _testcapi_make_exception_with_doc_impl(module, name, doc, base, dict); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_exc_set_object__doc__, +"exc_set_object($module, exception, obj, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_EXC_SET_OBJECT_METHODDEF \ + {"exc_set_object", _PyCFunction_CAST(_testcapi_exc_set_object), METH_FASTCALL, _testcapi_exc_set_object__doc__}, + +static PyObject * +_testcapi_exc_set_object_impl(PyObject *module, PyObject *exc, PyObject *obj); + +static PyObject * +_testcapi_exc_set_object(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc; + PyObject *obj; + + if (!_PyArg_CheckPositional("exc_set_object", nargs, 2, 2)) { + goto exit; + } + exc = args[0]; + obj = args[1]; + return_value = _testcapi_exc_set_object_impl(module, exc, obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_exc_set_object_fetch__doc__, +"exc_set_object_fetch($module, exception, obj, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_EXC_SET_OBJECT_FETCH_METHODDEF \ + {"exc_set_object_fetch", _PyCFunction_CAST(_testcapi_exc_set_object_fetch), METH_FASTCALL, _testcapi_exc_set_object_fetch__doc__}, + +static PyObject * +_testcapi_exc_set_object_fetch_impl(PyObject *module, PyObject *exc, + PyObject *obj); + +static PyObject * +_testcapi_exc_set_object_fetch(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc; + PyObject *obj; + + if (!_PyArg_CheckPositional("exc_set_object_fetch", nargs, 2, 2)) { + goto exit; + } + exc = args[0]; + obj = args[1]; + return_value = _testcapi_exc_set_object_fetch_impl(module, exc, obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_raise_exception__doc__, +"raise_exception($module, exception, num_args, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_RAISE_EXCEPTION_METHODDEF \ + {"raise_exception", _PyCFunction_CAST(_testcapi_raise_exception), METH_FASTCALL, _testcapi_raise_exception__doc__}, + +static PyObject * +_testcapi_raise_exception_impl(PyObject *module, PyObject *exc, int num_args); + +static PyObject * +_testcapi_raise_exception(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc; + int num_args; + + if (!_PyArg_CheckPositional("raise_exception", nargs, 2, 2)) { + goto exit; + } + exc = args[0]; + num_args = _PyLong_AsInt(args[1]); + if (num_args == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _testcapi_raise_exception_impl(module, exc, num_args); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_raise_memoryerror__doc__, +"raise_memoryerror($module, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_RAISE_MEMORYERROR_METHODDEF \ + {"raise_memoryerror", (PyCFunction)_testcapi_raise_memoryerror, METH_NOARGS, _testcapi_raise_memoryerror__doc__}, + +static PyObject * +_testcapi_raise_memoryerror_impl(PyObject *module); + +static PyObject * +_testcapi_raise_memoryerror(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_raise_memoryerror_impl(module); +} + +PyDoc_STRVAR(_testcapi_fatal_error__doc__, +"fatal_error($module, message, release_gil=False, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_FATAL_ERROR_METHODDEF \ + {"fatal_error", _PyCFunction_CAST(_testcapi_fatal_error), METH_FASTCALL, _testcapi_fatal_error__doc__}, + +static PyObject * +_testcapi_fatal_error_impl(PyObject *module, const char *message, + int release_gil); + +static PyObject * +_testcapi_fatal_error(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *message; + int release_gil = 0; + + if (!_PyArg_ParseStack(args, nargs, "y|p:fatal_error", + &message, &release_gil)) { + goto exit; + } + return_value = _testcapi_fatal_error_impl(module, message, release_gil); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_set_exc_info__doc__, +"set_exc_info($module, new_type, new_value, new_tb, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_SET_EXC_INFO_METHODDEF \ + {"set_exc_info", _PyCFunction_CAST(_testcapi_set_exc_info), METH_FASTCALL, _testcapi_set_exc_info__doc__}, + +static PyObject * +_testcapi_set_exc_info_impl(PyObject *module, PyObject *new_type, + PyObject *new_value, PyObject *new_tb); + +static PyObject * +_testcapi_set_exc_info(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *new_type; + PyObject *new_value; + PyObject *new_tb; + + if (!_PyArg_CheckPositional("set_exc_info", nargs, 3, 3)) { + goto exit; + } + new_type = args[0]; + new_value = args[1]; + new_tb = args[2]; + return_value = _testcapi_set_exc_info_impl(module, new_type, new_value, new_tb); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_set_exception__doc__, +"set_exception($module, new_exc, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_SET_EXCEPTION_METHODDEF \ + {"set_exception", (PyCFunction)_testcapi_set_exception, METH_O, _testcapi_set_exception__doc__}, + +PyDoc_STRVAR(_testcapi_write_unraisable_exc__doc__, +"write_unraisable_exc($module, exception, err_msg, obj, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF \ + {"write_unraisable_exc", _PyCFunction_CAST(_testcapi_write_unraisable_exc), METH_FASTCALL, _testcapi_write_unraisable_exc__doc__}, + +static PyObject * +_testcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, + PyObject *err_msg, PyObject *obj); + +static PyObject * +_testcapi_write_unraisable_exc(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *exc; + PyObject *err_msg; + PyObject *obj; + + if (!_PyArg_CheckPositional("write_unraisable_exc", nargs, 3, 3)) { + goto exit; + } + exc = args[0]; + err_msg = args[1]; + obj = args[2]; + return_value = _testcapi_write_unraisable_exc_impl(module, exc, err_msg, obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_traceback_print__doc__, +"traceback_print($module, traceback, file, /)\n" +"--\n" +"\n" +"To test the format of tracebacks as printed out."); + +#define _TESTCAPI_TRACEBACK_PRINT_METHODDEF \ + {"traceback_print", _PyCFunction_CAST(_testcapi_traceback_print), METH_FASTCALL, _testcapi_traceback_print__doc__}, + +static PyObject * +_testcapi_traceback_print_impl(PyObject *module, PyObject *traceback, + PyObject *file); + +static PyObject * +_testcapi_traceback_print(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *traceback; + PyObject *file; + + if (!_PyArg_CheckPositional("traceback_print", nargs, 2, 2)) { + goto exit; + } + traceback = args[0]; + file = args[1]; + return_value = _testcapi_traceback_print_impl(module, traceback, file); + +exit: + return return_value; +} +/*[clinic end generated code: output=ec1b2e62adea9846 input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/clinic/long.c.h b/Modules/_testcapi/clinic/long.c.h new file mode 100644 index 00000000000000..95885e0ae17a6c --- /dev/null +++ b/Modules/_testcapi/clinic/long.c.h @@ -0,0 +1,166 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(_testcapi_test_long_api__doc__, +"test_long_api($module, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_TEST_LONG_API_METHODDEF \ + {"test_long_api", (PyCFunction)_testcapi_test_long_api, METH_NOARGS, _testcapi_test_long_api__doc__}, + +static PyObject * +_testcapi_test_long_api_impl(PyObject *module); + +static PyObject * +_testcapi_test_long_api(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_long_api_impl(module); +} + +PyDoc_STRVAR(_testcapi_test_longlong_api__doc__, +"test_longlong_api($module, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_TEST_LONGLONG_API_METHODDEF \ + {"test_longlong_api", (PyCFunction)_testcapi_test_longlong_api, METH_NOARGS, _testcapi_test_longlong_api__doc__}, + +static PyObject * +_testcapi_test_longlong_api_impl(PyObject *module); + +static PyObject * +_testcapi_test_longlong_api(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_longlong_api_impl(module); +} + +PyDoc_STRVAR(_testcapi_test_long_and_overflow__doc__, +"test_long_and_overflow($module, /)\n" +"--\n" +"\n" +"Test the PyLong_AsLongAndOverflow API.\n" +"\n" +"General conversion to PY_LONG is tested by test_long_api_inner.\n" +"This test will concentrate on proper handling of overflow."); + +#define _TESTCAPI_TEST_LONG_AND_OVERFLOW_METHODDEF \ + {"test_long_and_overflow", (PyCFunction)_testcapi_test_long_and_overflow, METH_NOARGS, _testcapi_test_long_and_overflow__doc__}, + +static PyObject * +_testcapi_test_long_and_overflow_impl(PyObject *module); + +static PyObject * +_testcapi_test_long_and_overflow(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_long_and_overflow_impl(module); +} + +PyDoc_STRVAR(_testcapi_test_long_long_and_overflow__doc__, +"test_long_long_and_overflow($module, /)\n" +"--\n" +"\n" +"Test the PyLong_AsLongLongAndOverflow API.\n" +"\n" +"General conversion to long long is tested by test_long_api_inner.\n" +"This test will concentrate on proper handling of overflow."); + +#define _TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF \ + {"test_long_long_and_overflow", (PyCFunction)_testcapi_test_long_long_and_overflow, METH_NOARGS, _testcapi_test_long_long_and_overflow__doc__}, + +static PyObject * +_testcapi_test_long_long_and_overflow_impl(PyObject *module); + +static PyObject * +_testcapi_test_long_long_and_overflow(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_long_long_and_overflow_impl(module); +} + +PyDoc_STRVAR(_testcapi_test_long_as_size_t__doc__, +"test_long_as_size_t($module, /)\n" +"--\n" +"\n" +"Test the PyLong_As{Size,Ssize}_t API.\n" +"\n" +"At present this just tests that non-integer arguments are handled correctly.\n" +"It should be extended to test overflow handling."); + +#define _TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF \ + {"test_long_as_size_t", (PyCFunction)_testcapi_test_long_as_size_t, METH_NOARGS, _testcapi_test_long_as_size_t__doc__}, + +static PyObject * +_testcapi_test_long_as_size_t_impl(PyObject *module); + +static PyObject * +_testcapi_test_long_as_size_t(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_long_as_size_t_impl(module); +} + +PyDoc_STRVAR(_testcapi_test_long_as_unsigned_long_long_mask__doc__, +"test_long_as_unsigned_long_long_mask($module, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF \ + {"test_long_as_unsigned_long_long_mask", (PyCFunction)_testcapi_test_long_as_unsigned_long_long_mask, METH_NOARGS, _testcapi_test_long_as_unsigned_long_long_mask__doc__}, + +static PyObject * +_testcapi_test_long_as_unsigned_long_long_mask_impl(PyObject *module); + +static PyObject * +_testcapi_test_long_as_unsigned_long_long_mask(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_long_as_unsigned_long_long_mask_impl(module); +} + +PyDoc_STRVAR(_testcapi_test_long_as_double__doc__, +"test_long_as_double($module, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_TEST_LONG_AS_DOUBLE_METHODDEF \ + {"test_long_as_double", (PyCFunction)_testcapi_test_long_as_double, METH_NOARGS, _testcapi_test_long_as_double__doc__}, + +static PyObject * +_testcapi_test_long_as_double_impl(PyObject *module); + +static PyObject * +_testcapi_test_long_as_double(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_long_as_double_impl(module); +} + +PyDoc_STRVAR(_testcapi_test_long_numbits__doc__, +"test_long_numbits($module, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF \ + {"test_long_numbits", (PyCFunction)_testcapi_test_long_numbits, METH_NOARGS, _testcapi_test_long_numbits__doc__}, + +static PyObject * +_testcapi_test_long_numbits_impl(PyObject *module); + +static PyObject * +_testcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _testcapi_test_long_numbits_impl(module); +} + +PyDoc_STRVAR(_testcapi_call_long_compact_api__doc__, +"call_long_compact_api($module, arg, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF \ + {"call_long_compact_api", (PyCFunction)_testcapi_call_long_compact_api, METH_O, _testcapi_call_long_compact_api__doc__}, +/*[clinic end generated code: output=d000a1b58fa81eab input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/clinic/watchers.c.h b/Modules/_testcapi/clinic/watchers.c.h new file mode 100644 index 00000000000000..975244bd59a36b --- /dev/null +++ b/Modules/_testcapi/clinic/watchers.c.h @@ -0,0 +1,198 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(_testcapi_watch_dict__doc__, +"watch_dict($module, watcher_id, dict, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_WATCH_DICT_METHODDEF \ + {"watch_dict", _PyCFunction_CAST(_testcapi_watch_dict), METH_FASTCALL, _testcapi_watch_dict__doc__}, + +static PyObject * +_testcapi_watch_dict_impl(PyObject *module, int watcher_id, PyObject *dict); + +static PyObject * +_testcapi_watch_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int watcher_id; + PyObject *dict; + + if (!_PyArg_CheckPositional("watch_dict", nargs, 2, 2)) { + goto exit; + } + watcher_id = _PyLong_AsInt(args[0]); + if (watcher_id == -1 && PyErr_Occurred()) { + goto exit; + } + dict = args[1]; + return_value = _testcapi_watch_dict_impl(module, watcher_id, dict); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_unwatch_dict__doc__, +"unwatch_dict($module, watcher_id, dict, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_UNWATCH_DICT_METHODDEF \ + {"unwatch_dict", _PyCFunction_CAST(_testcapi_unwatch_dict), METH_FASTCALL, _testcapi_unwatch_dict__doc__}, + +static PyObject * +_testcapi_unwatch_dict_impl(PyObject *module, int watcher_id, PyObject *dict); + +static PyObject * +_testcapi_unwatch_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int watcher_id; + PyObject *dict; + + if (!_PyArg_CheckPositional("unwatch_dict", nargs, 2, 2)) { + goto exit; + } + watcher_id = _PyLong_AsInt(args[0]); + if (watcher_id == -1 && PyErr_Occurred()) { + goto exit; + } + dict = args[1]; + return_value = _testcapi_unwatch_dict_impl(module, watcher_id, dict); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_watch_type__doc__, +"watch_type($module, watcher_id, type, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_WATCH_TYPE_METHODDEF \ + {"watch_type", _PyCFunction_CAST(_testcapi_watch_type), METH_FASTCALL, _testcapi_watch_type__doc__}, + +static PyObject * +_testcapi_watch_type_impl(PyObject *module, int watcher_id, PyObject *type); + +static PyObject * +_testcapi_watch_type(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int watcher_id; + PyObject *type; + + if (!_PyArg_CheckPositional("watch_type", nargs, 2, 2)) { + goto exit; + } + watcher_id = _PyLong_AsInt(args[0]); + if (watcher_id == -1 && PyErr_Occurred()) { + goto exit; + } + type = args[1]; + return_value = _testcapi_watch_type_impl(module, watcher_id, type); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_unwatch_type__doc__, +"unwatch_type($module, watcher_id, type, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_UNWATCH_TYPE_METHODDEF \ + {"unwatch_type", _PyCFunction_CAST(_testcapi_unwatch_type), METH_FASTCALL, _testcapi_unwatch_type__doc__}, + +static PyObject * +_testcapi_unwatch_type_impl(PyObject *module, int watcher_id, PyObject *type); + +static PyObject * +_testcapi_unwatch_type(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int watcher_id; + PyObject *type; + + if (!_PyArg_CheckPositional("unwatch_type", nargs, 2, 2)) { + goto exit; + } + watcher_id = _PyLong_AsInt(args[0]); + if (watcher_id == -1 && PyErr_Occurred()) { + goto exit; + } + type = args[1]; + return_value = _testcapi_unwatch_type_impl(module, watcher_id, type); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_set_func_defaults_via_capi__doc__, +"set_func_defaults_via_capi($module, func, defaults, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_SET_FUNC_DEFAULTS_VIA_CAPI_METHODDEF \ + {"set_func_defaults_via_capi", _PyCFunction_CAST(_testcapi_set_func_defaults_via_capi), METH_FASTCALL, _testcapi_set_func_defaults_via_capi__doc__}, + +static PyObject * +_testcapi_set_func_defaults_via_capi_impl(PyObject *module, PyObject *func, + PyObject *defaults); + +static PyObject * +_testcapi_set_func_defaults_via_capi(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *func; + PyObject *defaults; + + if (!_PyArg_CheckPositional("set_func_defaults_via_capi", nargs, 2, 2)) { + goto exit; + } + func = args[0]; + defaults = args[1]; + return_value = _testcapi_set_func_defaults_via_capi_impl(module, func, defaults); + +exit: + return return_value; +} + +PyDoc_STRVAR(_testcapi_set_func_kwdefaults_via_capi__doc__, +"set_func_kwdefaults_via_capi($module, func, defaults, /)\n" +"--\n" +"\n"); + +#define _TESTCAPI_SET_FUNC_KWDEFAULTS_VIA_CAPI_METHODDEF \ + {"set_func_kwdefaults_via_capi", _PyCFunction_CAST(_testcapi_set_func_kwdefaults_via_capi), METH_FASTCALL, _testcapi_set_func_kwdefaults_via_capi__doc__}, + +static PyObject * +_testcapi_set_func_kwdefaults_via_capi_impl(PyObject *module, PyObject *func, + PyObject *defaults); + +static PyObject * +_testcapi_set_func_kwdefaults_via_capi(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *func; + PyObject *defaults; + + if (!_PyArg_CheckPositional("set_func_kwdefaults_via_capi", nargs, 2, 2)) { + goto exit; + } + func = args[0]; + defaults = args[1]; + return_value = _testcapi_set_func_kwdefaults_via_capi_impl(module, func, defaults); + +exit: + return return_value; +} +/*[clinic end generated code: output=12c375089125d165 input=a9049054013a1b77]*/ diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c index 6099f7d20eb56a..0a9902c135a7e5 100644 --- a/Modules/_testcapi/exceptions.c +++ b/Modules/_testcapi/exceptions.c @@ -1,7 +1,20 @@ #include "parts.h" +#include "clinic/exceptions.c.h" + +/*[clinic input] +module _testcapi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/ + +/*[clinic input] +_testcapi.err_set_raised + exception as exc: object + / +[clinic start generated code]*/ static PyObject * -err_set_raised(PyObject *self, PyObject *exc) +_testcapi_err_set_raised(PyObject *module, PyObject *exc) +/*[clinic end generated code: output=0a0c7743961fcae5 input=c5f7331864a94df9]*/ { Py_INCREF(exc); PyErr_SetRaisedException(exc); @@ -35,16 +48,19 @@ err_restore(PyObject *self, PyObject *args) { return NULL; } -/* To test the format of exceptions as printed out. */ +/*[clinic input] +_testcapi.exception_print + exception as exc: object + legacy: bool = False + / + +To test the format of exceptions as printed out. +[clinic start generated code]*/ + static PyObject * -exception_print(PyObject *self, PyObject *args) +_testcapi_exception_print_impl(PyObject *module, PyObject *exc, int legacy) +/*[clinic end generated code: output=3f04fe0c18412ae0 input=c76f42cb94136dbf]*/ { - PyObject *exc; - int legacy = 0; - - if (!PyArg_ParseTuple(args, "O|i:exception_print", &exc, &legacy)) { - return NULL; - } if (legacy) { PyObject *tb = NULL; if (PyExceptionInstance_Check(exc)) { @@ -59,55 +75,53 @@ exception_print(PyObject *self, PyObject *args) Py_RETURN_NONE; } -/* Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException). - Run via Lib/test/test_exceptions.py */ -static PyObject * -make_exception_with_doc(PyObject *self, PyObject *args, PyObject *kwargs) -{ - const char *name; - const char *doc = NULL; - PyObject *base = NULL; - PyObject *dict = NULL; - - static char *kwlist[] = {"name", "doc", "base", "dict", NULL}; +/*[clinic input] +_testcapi.make_exception_with_doc + name: str + doc: str = NULL + base: object = NULL + dict: object = NULL - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "s|sOO:make_exception_with_doc", kwlist, - &name, &doc, &base, &dict)) - { - return NULL; - } +Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException). Run via Lib/test/test_exceptions.py +[clinic start generated code]*/ +static PyObject * +_testcapi_make_exception_with_doc_impl(PyObject *module, const char *name, + const char *doc, PyObject *base, + PyObject *dict) +/*[clinic end generated code: output=439f0d963c1ce2c4 input=23a73013f8a8795a]*/ +{ return PyErr_NewExceptionWithDoc(name, doc, base, dict); } +/*[clinic input] +_testcapi.exc_set_object + exception as exc: object + obj: object + / +[clinic start generated code]*/ + static PyObject * -exc_set_object(PyObject *self, PyObject *args) +_testcapi_exc_set_object_impl(PyObject *module, PyObject *exc, PyObject *obj) +/*[clinic end generated code: output=34c8c7c83e5c8463 input=fc530aafb1b0a360]*/ { - PyObject *exc; - PyObject *obj; - - if (!PyArg_ParseTuple(args, "OO:exc_set_object", &exc, &obj)) { - return NULL; - } - PyErr_SetObject(exc, obj); return NULL; } +/*[clinic input] +_testcapi.exc_set_object_fetch = _testcapi.exc_set_object +[clinic start generated code]*/ + static PyObject * -exc_set_object_fetch(PyObject *self, PyObject *args) +_testcapi_exc_set_object_fetch_impl(PyObject *module, PyObject *exc, + PyObject *obj) +/*[clinic end generated code: output=7a5ff5f6d3cf687f input=77ec686f1f95fa38]*/ { - PyObject *exc; - PyObject *obj; PyObject *type; PyObject *value; PyObject *tb; - if (!PyArg_ParseTuple(args, "OO:exc_set_object", &exc, &obj)) { - return NULL; - } - PyErr_SetObject(exc, obj); PyErr_Fetch(&type, &value, &tb); Py_XDECREF(type); @@ -115,16 +129,17 @@ exc_set_object_fetch(PyObject *self, PyObject *args) return value; } +/*[clinic input] +_testcapi.raise_exception + exception as exc: object + num_args: int + / +[clinic start generated code]*/ + static PyObject * -raise_exception(PyObject *self, PyObject *args) +_testcapi_raise_exception_impl(PyObject *module, PyObject *exc, int num_args) +/*[clinic end generated code: output=eb0a9c5d69e0542d input=83d6262c3829d088]*/ { - PyObject *exc; - int num_args; - - if (!PyArg_ParseTuple(args, "Oi:raise_exception", &exc, &num_args)) { - return NULL; - } - PyObject *exc_args = PyTuple_New(num_args); if (exc_args == NULL) { return NULL; @@ -142,21 +157,29 @@ raise_exception(PyObject *self, PyObject *args) return NULL; } -/* reliably raise a MemoryError */ +/*[clinic input] +_testcapi.raise_memoryerror +[clinic start generated code]*/ + static PyObject * -raise_memoryerror(PyObject *self, PyObject *Py_UNUSED(ignored)) +_testcapi_raise_memoryerror_impl(PyObject *module) +/*[clinic end generated code: output=dd057803fb0131e6 input=6ca521bd07fb73cb]*/ { return PyErr_NoMemory(); } +/*[clinic input] +_testcapi.fatal_error + message: str(accept={robuffer}) + release_gil: bool = False + / +[clinic start generated code]*/ + static PyObject * -test_fatal_error(PyObject *self, PyObject *args) +_testcapi_fatal_error_impl(PyObject *module, const char *message, + int release_gil) +/*[clinic end generated code: output=9c3237116e6a03e8 input=1be357a2ccb04c8c]*/ { - char *message; - int release_gil = 0; - if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil)) { - return NULL; - } if (release_gil) { Py_BEGIN_ALLOW_THREADS Py_FatalError(message); @@ -169,17 +192,20 @@ test_fatal_error(PyObject *self, PyObject *args) Py_RETURN_NONE; } +/*[clinic input] +_testcapi.set_exc_info + new_type: object + new_value: object + new_tb: object + / +[clinic start generated code]*/ + static PyObject * -test_set_exc_info(PyObject *self, PyObject *args) +_testcapi_set_exc_info_impl(PyObject *module, PyObject *new_type, + PyObject *new_value, PyObject *new_tb) +/*[clinic end generated code: output=b55fa35dec31300e input=ea9f19e0f55fe5b3]*/ { - PyObject *new_type, *new_value, *new_tb; PyObject *type, *value, *tb; - if (!PyArg_ParseTuple(args, "OOO:test_set_exc_info", - &new_type, &new_value, &new_tb)) - { - return NULL; - } - PyErr_GetExcInfo(&type, &value, &tb); Py_INCREF(new_type); @@ -197,23 +223,35 @@ test_set_exc_info(PyObject *self, PyObject *args) return orig_exc; } +/*[clinic input] +_testcapi.set_exception + new_exc: object + / +[clinic start generated code]*/ + static PyObject * -test_set_exception(PyObject *self, PyObject *new_exc) +_testcapi_set_exception(PyObject *module, PyObject *new_exc) +/*[clinic end generated code: output=8b969b35d029e96d input=c89d4ca966c69738]*/ { PyObject *exc = PyErr_GetHandledException(); assert(PyExceptionInstance_Check(exc) || exc == NULL); - PyErr_SetHandledException(new_exc); return exc; } +/*[clinic input] +_testcapi.write_unraisable_exc + exception as exc: object + err_msg: object + obj: object + / +[clinic start generated code]*/ + static PyObject * -test_write_unraisable_exc(PyObject *self, PyObject *args) +_testcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, + PyObject *err_msg, PyObject *obj) +/*[clinic end generated code: output=39827c5e0a8c2092 input=582498da5b2ee6cf]*/ { - PyObject *exc, *err_msg, *obj; - if (!PyArg_ParseTuple(args, "OOO", &exc, &err_msg, &obj)) { - return NULL; - } const char *err_msg_utf8; if (err_msg != Py_None) { @@ -231,19 +269,19 @@ test_write_unraisable_exc(PyObject *self, PyObject *args) Py_RETURN_NONE; } -/* To test the format of tracebacks as printed out. */ +/*[clinic input] +_testcapi.traceback_print + traceback: object + file: object + / +To test the format of tracebacks as printed out. +[clinic start generated code]*/ + static PyObject * -traceback_print(PyObject *self, PyObject *args) +_testcapi_traceback_print_impl(PyObject *module, PyObject *traceback, + PyObject *file) +/*[clinic end generated code: output=17074ecf9d95cf30 input=9423f2857b008ca8]*/ { - PyObject *file; - PyObject *traceback; - - if (!PyArg_ParseTuple(args, "OO:traceback_print", - &traceback, &file)) - { - return NULL; - } - if (PyTraceBack_Print(traceback, file) < 0) { return NULL; } @@ -278,20 +316,18 @@ static PyTypeObject PyRecursingInfinitelyError_Type = { static PyMethodDef test_methods[] = { {"err_restore", err_restore, METH_VARARGS}, - {"err_set_raised", err_set_raised, METH_O}, - {"exception_print", exception_print, METH_VARARGS}, - {"fatal_error", test_fatal_error, METH_VARARGS, - PyDoc_STR("fatal_error(message, release_gil=False): call Py_FatalError(message)")}, - {"make_exception_with_doc", _PyCFunction_CAST(make_exception_with_doc), - METH_VARARGS | METH_KEYWORDS}, - {"exc_set_object", exc_set_object, METH_VARARGS}, - {"exc_set_object_fetch", exc_set_object_fetch, METH_VARARGS}, - {"raise_exception", raise_exception, METH_VARARGS}, - {"raise_memoryerror", raise_memoryerror, METH_NOARGS}, - {"set_exc_info", test_set_exc_info, METH_VARARGS}, - {"set_exception", test_set_exception, METH_O}, - {"traceback_print", traceback_print, METH_VARARGS}, - {"write_unraisable_exc", test_write_unraisable_exc, METH_VARARGS}, + _TESTCAPI_ERR_SET_RAISED_METHODDEF + _TESTCAPI_EXCEPTION_PRINT_METHODDEF + _TESTCAPI_FATAL_ERROR_METHODDEF + _TESTCAPI_MAKE_EXCEPTION_WITH_DOC_METHODDEF + _TESTCAPI_EXC_SET_OBJECT_METHODDEF + _TESTCAPI_EXC_SET_OBJECT_FETCH_METHODDEF + _TESTCAPI_RAISE_EXCEPTION_METHODDEF + _TESTCAPI_RAISE_MEMORYERROR_METHODDEF + _TESTCAPI_SET_EXC_INFO_METHODDEF + _TESTCAPI_SET_EXCEPTION_METHODDEF + _TESTCAPI_TRACEBACK_PRINT_METHODDEF + _TESTCAPI_WRITE_UNRAISABLE_EXC_METHODDEF {NULL}, }; diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c index 1be8de5e576254..ede43f60d06f95 100644 --- a/Modules/_testcapi/long.c +++ b/Modules/_testcapi/long.c @@ -1,4 +1,10 @@ #include "parts.h" +#include "clinic/long.c.h" + +/*[clinic input] +module _testcapi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/ static PyObject * @@ -40,8 +46,13 @@ raise_test_long_error(const char* msg) #include "testcapi_long.h" +/*[clinic input] +_testcapi.test_long_api +[clinic start generated code]*/ + static PyObject * -test_long_api(PyObject* self, PyObject *Py_UNUSED(ignored)) +_testcapi_test_long_api_impl(PyObject *module) +/*[clinic end generated code: output=4405798ca1e9f444 input=e9b8880d7331c688]*/ { return TESTNAME(raise_test_long_error); } @@ -68,8 +79,13 @@ raise_test_longlong_error(const char* msg) #include "testcapi_long.h" +/*[clinic input] +_testcapi.test_longlong_api +[clinic start generated code]*/ + static PyObject * -test_longlong_api(PyObject* self, PyObject *args) +_testcapi_test_longlong_api_impl(PyObject *module) +/*[clinic end generated code: output=2b3414ba8c31dfe6 input=ccbb2a48c2b3c4a5]*/ { return TESTNAME(raise_test_longlong_error); } @@ -81,13 +97,19 @@ test_longlong_api(PyObject* self, PyObject *args) #undef F_U_TO_PY #undef F_PY_TO_U -/* Test the PyLong_AsLongAndOverflow API. General conversion to PY_LONG - is tested by test_long_api_inner. This test will concentrate on proper - handling of overflow. -*/ + +/*[clinic input] +_testcapi.test_long_and_overflow + +Test the PyLong_AsLongAndOverflow API. + +General conversion to PY_LONG is tested by test_long_api_inner. +This test will concentrate on proper handling of overflow. +[clinic start generated code]*/ static PyObject * -test_long_and_overflow(PyObject *self, PyObject *Py_UNUSED(ignored)) +_testcapi_test_long_and_overflow_impl(PyObject *module) +/*[clinic end generated code: output=f8460ca115e31d8e input=762f6b62da0a3cdc]*/ { PyObject *num, *one, *temp; long value; @@ -243,13 +265,18 @@ test_long_and_overflow(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } -/* Test the PyLong_AsLongLongAndOverflow API. General conversion to - long long is tested by test_long_api_inner. This test will - concentrate on proper handling of overflow. -*/ +/*[clinic input] +_testcapi.test_long_long_and_overflow + +Test the PyLong_AsLongLongAndOverflow API. + +General conversion to long long is tested by test_long_api_inner. +This test will concentrate on proper handling of overflow. +[clinic start generated code]*/ static PyObject * -test_long_long_and_overflow(PyObject *self, PyObject *Py_UNUSED(ignored)) +_testcapi_test_long_long_and_overflow_impl(PyObject *module) +/*[clinic end generated code: output=0b92330786f45483 input=544bb0aefe5e8a9e]*/ { PyObject *num, *one, *temp; long long value; @@ -405,13 +432,18 @@ test_long_long_and_overflow(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } -/* Test the PyLong_As{Size,Ssize}_t API. At present this just tests that - non-integer arguments are handled correctly. It should be extended to - test overflow handling. - */ +/*[clinic input] +_testcapi.test_long_as_size_t + +Test the PyLong_As{Size,Ssize}_t API. + +At present this just tests that non-integer arguments are handled correctly. +It should be extended to test overflow handling. +[clinic start generated code]*/ static PyObject * -test_long_as_size_t(PyObject *self, PyObject *Py_UNUSED(ignored)) +_testcapi_test_long_as_size_t_impl(PyObject *module) +/*[clinic end generated code: output=f6490ea2b41e6173 input=922990c4a3edfb0d]*/ { size_t out_u; Py_ssize_t out_s; @@ -442,9 +474,13 @@ test_long_as_size_t(PyObject *self, PyObject *Py_UNUSED(ignored)) return Py_None; } +/*[clinic input] +_testcapi.test_long_as_unsigned_long_long_mask +[clinic start generated code]*/ + static PyObject * -test_long_as_unsigned_long_long_mask(PyObject *self, - PyObject *Py_UNUSED(ignored)) +_testcapi_test_long_as_unsigned_long_long_mask_impl(PyObject *module) +/*[clinic end generated code: output=e3e16cd0189440cc input=eb2438493ae7b9af]*/ { unsigned long long res = PyLong_AsUnsignedLongLongMask(NULL); @@ -462,12 +498,13 @@ test_long_as_unsigned_long_long_mask(PyObject *self, Py_RETURN_NONE; } -/* Test the PyLong_AsDouble API. At present this just tests that - non-integer arguments are handled correctly. - */ +/*[clinic input] +_testcapi.test_long_as_double +[clinic start generated code]*/ static PyObject * -test_long_as_double(PyObject *self, PyObject *Py_UNUSED(ignored)) +_testcapi_test_long_as_double_impl(PyObject *module) +/*[clinic end generated code: output=deca0898e15adde5 input=c77bc88ef5a1de76]*/ { double out; @@ -487,9 +524,13 @@ test_long_as_double(PyObject *self, PyObject *Py_UNUSED(ignored)) return Py_None; } -/* Simple test of _PyLong_NumBits and _PyLong_Sign. */ +/*[clinic input] +_testcapi.test_long_numbits +[clinic start generated code]*/ + static PyObject * -test_long_numbits(PyObject *self, PyObject *Py_UNUSED(ignored)) +_testcapi_test_long_numbits_impl(PyObject *module) +/*[clinic end generated code: output=9eaf8458cb15d7f7 input=265c02d48a13059e]*/ { struct triple { long input; @@ -534,15 +575,36 @@ test_long_numbits(PyObject *self, PyObject *Py_UNUSED(ignored)) Py_RETURN_NONE; } +/*[clinic input] +_testcapi.call_long_compact_api + arg: object + / +[clinic start generated code]*/ + +static PyObject * +_testcapi_call_long_compact_api(PyObject *module, PyObject *arg) +/*[clinic end generated code: output=7e3894f611b1b2b7 input=87b87396967af14c]*/ + +{ + assert(PyLong_Check(arg)); + int is_compact = PyUnstable_Long_IsCompact((PyLongObject*)arg); + Py_ssize_t value = -1; + if (is_compact) { + value = PyUnstable_Long_CompactValue((PyLongObject*)arg); + } + return Py_BuildValue("in", is_compact, value); +} + static PyMethodDef test_methods[] = { - {"test_long_and_overflow", test_long_and_overflow, METH_NOARGS}, - {"test_long_api", test_long_api, METH_NOARGS}, - {"test_long_as_double", test_long_as_double, METH_NOARGS}, - {"test_long_as_size_t", test_long_as_size_t, METH_NOARGS}, - {"test_long_as_unsigned_long_long_mask", test_long_as_unsigned_long_long_mask, METH_NOARGS}, - {"test_long_long_and_overflow",test_long_long_and_overflow, METH_NOARGS}, - {"test_long_numbits", test_long_numbits, METH_NOARGS}, - {"test_longlong_api", test_longlong_api, METH_NOARGS}, + _TESTCAPI_TEST_LONG_AND_OVERFLOW_METHODDEF + _TESTCAPI_TEST_LONG_API_METHODDEF + _TESTCAPI_TEST_LONG_AS_DOUBLE_METHODDEF + _TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF + _TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF + _TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF + _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF + _TESTCAPI_TEST_LONGLONG_API_METHODDEF + _TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF {NULL}, }; diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c index 7dd3b9c0c03e50..73929eaffc676d 100644 --- a/Modules/_testcapi/unicode.c +++ b/Modules/_testcapi/unicode.c @@ -1,3 +1,5 @@ +#include // ptrdiff_t + #define PY_SSIZE_T_CLEAN #include "parts.h" @@ -1130,25 +1132,48 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1( "%c", "c", 'c'); CHECK_FORMAT_1( "%0c", "c", 'c'); CHECK_FORMAT_1("%00c", "c", 'c'); - CHECK_FORMAT_1( "%2c", "c", 'c'); - CHECK_FORMAT_1("%02c", "c", 'c'); - CHECK_FORMAT_1("%.0c", "c", 'c'); - CHECK_FORMAT_1("%.2c", "c", 'c'); + CHECK_FORMAT_1( "%2c", NULL, 'c'); + CHECK_FORMAT_1("%02c", NULL, 'c'); + CHECK_FORMAT_1("%.0c", NULL, 'c'); + CHECK_FORMAT_1("%.2c", NULL, 'c'); // Integers CHECK_FORMAT_1("%d", "123", (int)123); CHECK_FORMAT_1("%i", "123", (int)123); CHECK_FORMAT_1("%u", "123", (unsigned int)123); + CHECK_FORMAT_1("%x", "7b", (unsigned int)123); + CHECK_FORMAT_1("%X", "7B", (unsigned int)123); + CHECK_FORMAT_1("%o", "173", (unsigned int)123); CHECK_FORMAT_1("%ld", "123", (long)123); CHECK_FORMAT_1("%li", "123", (long)123); CHECK_FORMAT_1("%lu", "123", (unsigned long)123); + CHECK_FORMAT_1("%lx", "7b", (unsigned long)123); + CHECK_FORMAT_1("%lX", "7B", (unsigned long)123); + CHECK_FORMAT_1("%lo", "173", (unsigned long)123); CHECK_FORMAT_1("%lld", "123", (long long)123); CHECK_FORMAT_1("%lli", "123", (long long)123); CHECK_FORMAT_1("%llu", "123", (unsigned long long)123); + CHECK_FORMAT_1("%llx", "7b", (unsigned long long)123); + CHECK_FORMAT_1("%llX", "7B", (unsigned long long)123); + CHECK_FORMAT_1("%llo", "173", (unsigned long long)123); CHECK_FORMAT_1("%zd", "123", (Py_ssize_t)123); CHECK_FORMAT_1("%zi", "123", (Py_ssize_t)123); CHECK_FORMAT_1("%zu", "123", (size_t)123); - CHECK_FORMAT_1("%x", "7b", (int)123); + CHECK_FORMAT_1("%zx", "7b", (size_t)123); + CHECK_FORMAT_1("%zX", "7B", (size_t)123); + CHECK_FORMAT_1("%zo", "173", (size_t)123); + CHECK_FORMAT_1("%td", "123", (ptrdiff_t)123); + CHECK_FORMAT_1("%ti", "123", (ptrdiff_t)123); + CHECK_FORMAT_1("%tu", "123", (ptrdiff_t)123); + CHECK_FORMAT_1("%tx", "7b", (ptrdiff_t)123); + CHECK_FORMAT_1("%tX", "7B", (ptrdiff_t)123); + CHECK_FORMAT_1("%to", "173", (ptrdiff_t)123); + CHECK_FORMAT_1("%jd", "123", (intmax_t)123); + CHECK_FORMAT_1("%ji", "123", (intmax_t)123); + CHECK_FORMAT_1("%ju", "123", (uintmax_t)123); + CHECK_FORMAT_1("%jx", "7b", (uintmax_t)123); + CHECK_FORMAT_1("%jX", "7B", (uintmax_t)123); + CHECK_FORMAT_1("%jo", "173", (uintmax_t)123); CHECK_FORMAT_1("%d", "-123", (int)-123); CHECK_FORMAT_1("%i", "-123", (int)-123); @@ -1158,7 +1183,10 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%lli", "-123", (long long)-123); CHECK_FORMAT_1("%zd", "-123", (Py_ssize_t)-123); CHECK_FORMAT_1("%zi", "-123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%x", "ffffff85", (int)-123); + CHECK_FORMAT_1("%td", "-123", (ptrdiff_t)-123); + CHECK_FORMAT_1("%ti", "-123", (ptrdiff_t)-123); + CHECK_FORMAT_1("%jd", "-123", (intmax_t)-123); + CHECK_FORMAT_1("%ji", "-123", (intmax_t)-123); // Integers: width < length CHECK_FORMAT_1("%1d", "123", (int)123); @@ -1183,7 +1211,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%1lli", "-123", (long long)-123); CHECK_FORMAT_1("%1zd", "-123", (Py_ssize_t)-123); CHECK_FORMAT_1("%1zi", "-123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%1x", "ffffff85", (int)-123); // Integers: width > length CHECK_FORMAT_1("%5d", " 123", (int)123); @@ -1208,7 +1235,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%5lli", " -123", (long long)-123); CHECK_FORMAT_1("%5zd", " -123", (Py_ssize_t)-123); CHECK_FORMAT_1("%5zi", " -123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%9x", " ffffff85", (int)-123); // Integers: width > length, 0-flag CHECK_FORMAT_1("%05d", "00123", (int)123); @@ -1233,7 +1259,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%05lli", "-0123", (long long)-123); CHECK_FORMAT_1("%05zd", "-0123", (Py_ssize_t)-123); CHECK_FORMAT_1("%05zi", "-0123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%09x", "0ffffff85", (int)-123); // Integers: precision < length CHECK_FORMAT_1("%.1d", "123", (int)123); @@ -1258,7 +1283,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%.1lli", "-123", (long long)-123); CHECK_FORMAT_1("%.1zd", "-123", (Py_ssize_t)-123); CHECK_FORMAT_1("%.1zi", "-123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%.1x", "ffffff85", (int)-123); // Integers: precision > length CHECK_FORMAT_1("%.5d", "00123", (int)123); @@ -1283,7 +1307,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%.5lli", "-00123", (long long)-123); CHECK_FORMAT_1("%.5zd", "-00123", (Py_ssize_t)-123); CHECK_FORMAT_1("%.5zi", "-00123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%.9x", "0ffffff85", (int)-123); // Integers: width > precision > length CHECK_FORMAT_1("%7.5d", " 00123", (int)123); @@ -1308,7 +1331,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%7.5lli", " -00123", (long long)-123); CHECK_FORMAT_1("%7.5zd", " -00123", (Py_ssize_t)-123); CHECK_FORMAT_1("%7.5zi", " -00123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%10.9x", " 0ffffff85", (int)-123); // Integers: width > precision > length, 0-flag CHECK_FORMAT_1("%07.5d", "0000123", (int)123); @@ -1333,7 +1355,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%07.5lli", "-000123", (long long)-123); CHECK_FORMAT_1("%07.5zd", "-000123", (Py_ssize_t)-123); CHECK_FORMAT_1("%07.5zi", "-000123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%010.9x", "00ffffff85", (int)-123); // Integers: precision > width > length CHECK_FORMAT_1("%5.7d", "0000123", (int)123); @@ -1358,7 +1379,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%5.7lli", "-0000123", (long long)-123); CHECK_FORMAT_1("%5.7zd", "-0000123", (Py_ssize_t)-123); CHECK_FORMAT_1("%5.7zi", "-0000123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%9.10x", "00ffffff85", (int)-123); // Integers: precision > width > length, 0-flag CHECK_FORMAT_1("%05.7d", "0000123", (int)123); @@ -1383,7 +1403,6 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) CHECK_FORMAT_1("%05.7lli", "-0000123", (long long)-123); CHECK_FORMAT_1("%05.7zd", "-0000123", (Py_ssize_t)-123); CHECK_FORMAT_1("%05.7zi", "-0000123", (Py_ssize_t)-123); - CHECK_FORMAT_1("%09.10x", "00ffffff85", (int)-123); // Integers: precision = 0, arg = 0 (empty string in C) CHECK_FORMAT_1("%.0d", "0", (int)0); @@ -1402,66 +1421,80 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) // Strings CHECK_FORMAT_1("%s", "None", "None"); + CHECK_FORMAT_1("%ls", "None", L"None"); CHECK_FORMAT_1("%U", "None", unicode); CHECK_FORMAT_1("%A", "None", Py_None); CHECK_FORMAT_1("%S", "None", Py_None); CHECK_FORMAT_1("%R", "None", Py_None); CHECK_FORMAT_2("%V", "None", unicode, "ignored"); CHECK_FORMAT_2("%V", "None", NULL, "None"); + CHECK_FORMAT_2("%lV", "None", NULL, L"None"); // Strings: width < length CHECK_FORMAT_1("%1s", "None", "None"); + CHECK_FORMAT_1("%1ls", "None", L"None"); CHECK_FORMAT_1("%1U", "None", unicode); CHECK_FORMAT_1("%1A", "None", Py_None); CHECK_FORMAT_1("%1S", "None", Py_None); CHECK_FORMAT_1("%1R", "None", Py_None); CHECK_FORMAT_2("%1V", "None", unicode, "ignored"); CHECK_FORMAT_2("%1V", "None", NULL, "None"); + CHECK_FORMAT_2("%1lV", "None", NULL, L"None"); // Strings: width > length CHECK_FORMAT_1("%5s", " None", "None"); + CHECK_FORMAT_1("%5ls", " None", L"None"); CHECK_FORMAT_1("%5U", " None", unicode); CHECK_FORMAT_1("%5A", " None", Py_None); CHECK_FORMAT_1("%5S", " None", Py_None); CHECK_FORMAT_1("%5R", " None", Py_None); CHECK_FORMAT_2("%5V", " None", unicode, "ignored"); CHECK_FORMAT_2("%5V", " None", NULL, "None"); + CHECK_FORMAT_2("%5lV", " None", NULL, L"None"); // Strings: precision < length CHECK_FORMAT_1("%.1s", "N", "None"); + CHECK_FORMAT_1("%.1ls", "N", L"None"); CHECK_FORMAT_1("%.1U", "N", unicode); CHECK_FORMAT_1("%.1A", "N", Py_None); CHECK_FORMAT_1("%.1S", "N", Py_None); CHECK_FORMAT_1("%.1R", "N", Py_None); CHECK_FORMAT_2("%.1V", "N", unicode, "ignored"); CHECK_FORMAT_2("%.1V", "N", NULL, "None"); + CHECK_FORMAT_2("%.1lV", "N", NULL, L"None"); // Strings: precision > length CHECK_FORMAT_1("%.5s", "None", "None"); + CHECK_FORMAT_1("%.5ls", "None", L"None"); CHECK_FORMAT_1("%.5U", "None", unicode); CHECK_FORMAT_1("%.5A", "None", Py_None); CHECK_FORMAT_1("%.5S", "None", Py_None); CHECK_FORMAT_1("%.5R", "None", Py_None); CHECK_FORMAT_2("%.5V", "None", unicode, "ignored"); CHECK_FORMAT_2("%.5V", "None", NULL, "None"); + CHECK_FORMAT_2("%.5lV", "None", NULL, L"None"); // Strings: precision < length, width > length CHECK_FORMAT_1("%5.1s", " N", "None"); + CHECK_FORMAT_1("%5.1ls"," N", L"None"); CHECK_FORMAT_1("%5.1U", " N", unicode); CHECK_FORMAT_1("%5.1A", " N", Py_None); CHECK_FORMAT_1("%5.1S", " N", Py_None); CHECK_FORMAT_1("%5.1R", " N", Py_None); CHECK_FORMAT_2("%5.1V", " N", unicode, "ignored"); CHECK_FORMAT_2("%5.1V", " N", NULL, "None"); + CHECK_FORMAT_2("%5.1lV"," N", NULL, L"None"); // Strings: width < length, precision > length CHECK_FORMAT_1("%1.5s", "None", "None"); + CHECK_FORMAT_1("%1.5ls", "None", L"None"); CHECK_FORMAT_1("%1.5U", "None", unicode); CHECK_FORMAT_1("%1.5A", "None", Py_None); CHECK_FORMAT_1("%1.5S", "None", Py_None); CHECK_FORMAT_1("%1.5R", "None", Py_None); CHECK_FORMAT_2("%1.5V", "None", unicode, "ignored"); CHECK_FORMAT_2("%1.5V", "None", NULL, "None"); + CHECK_FORMAT_2("%1.5lV", "None", NULL, L"None"); Py_XDECREF(unicode); Py_RETURN_NONE; diff --git a/Modules/_testcapi/watchers.c b/Modules/_testcapi/watchers.c index 1284fdc2767b6c..d2c71fb401d36a 100644 --- a/Modules/_testcapi/watchers.c +++ b/Modules/_testcapi/watchers.c @@ -1,9 +1,16 @@ #include "parts.h" +#include "clinic/watchers.c.h" + #define Py_BUILD_CORE #include "pycore_function.h" // FUNC_MAX_WATCHERS #include "pycore_code.h" // CODE_MAX_WATCHERS +/*[clinic input] +module _testcapi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/ + // Test dict watching static PyObject *g_dict_watch_events; static int g_dict_watchers_installed; @@ -119,28 +126,31 @@ clear_dict_watcher(PyObject *self, PyObject *watcher_id) Py_RETURN_NONE; } +/*[clinic input] +_testcapi.watch_dict + watcher_id: int + dict: object + / +[clinic start generated code]*/ + static PyObject * -watch_dict(PyObject *self, PyObject *args) +_testcapi_watch_dict_impl(PyObject *module, int watcher_id, PyObject *dict) +/*[clinic end generated code: output=1426e0273cebe2d8 input=269b006d60c358bd]*/ { - PyObject *dict; - int watcher_id; - if (!PyArg_ParseTuple(args, "iO", &watcher_id, &dict)) { - return NULL; - } if (PyDict_Watch(watcher_id, dict)) { return NULL; } Py_RETURN_NONE; } +/*[clinic input] +_testcapi.unwatch_dict = _testcapi.watch_dict +[clinic start generated code]*/ + static PyObject * -unwatch_dict(PyObject *self, PyObject *args) +_testcapi_unwatch_dict_impl(PyObject *module, int watcher_id, PyObject *dict) +/*[clinic end generated code: output=512b1a71ae33c351 input=cae7dc1b6f7713b8]*/ { - PyObject *dict; - int watcher_id; - if (!PyArg_ParseTuple(args, "iO", &watcher_id, &dict)) { - return NULL; - } if (PyDict_Unwatch(watcher_id, dict)) { return NULL; } @@ -250,28 +260,31 @@ get_type_modified_events(PyObject *self, PyObject *Py_UNUSED(args)) return Py_NewRef(g_type_modified_events); } +/*[clinic input] +_testcapi.watch_type + watcher_id: int + type: object + / +[clinic start generated code]*/ + static PyObject * -watch_type(PyObject *self, PyObject *args) +_testcapi_watch_type_impl(PyObject *module, int watcher_id, PyObject *type) +/*[clinic end generated code: output=fdf4777126724fc4 input=5a808bf12be7e3ed]*/ { - PyObject *type; - int watcher_id; - if (!PyArg_ParseTuple(args, "iO", &watcher_id, &type)) { - return NULL; - } if (PyType_Watch(watcher_id, type)) { return NULL; } Py_RETURN_NONE; } +/*[clinic input] +_testcapi.unwatch_type = _testcapi.watch_type +[clinic start generated code]*/ + static PyObject * -unwatch_type(PyObject *self, PyObject *args) +_testcapi_unwatch_type_impl(PyObject *module, int watcher_id, PyObject *type) +/*[clinic end generated code: output=0389672d4ad5f68b input=6701911fb45edc9e]*/ { - PyObject *type; - int watcher_id; - if (!PyArg_ParseTuple(args, "iO", &watcher_id, &type)) { - return NULL; - } if (PyType_Unwatch(watcher_id, type)) { return NULL; } @@ -605,29 +618,34 @@ allocate_too_many_func_watchers(PyObject *self, PyObject *args) Py_RETURN_NONE; } +/*[clinic input] +_testcapi.set_func_defaults_via_capi + func: object + defaults: object + / +[clinic start generated code]*/ + static PyObject * -set_func_defaults(PyObject *self, PyObject *args) +_testcapi_set_func_defaults_via_capi_impl(PyObject *module, PyObject *func, + PyObject *defaults) +/*[clinic end generated code: output=caf0cb39db31ac24 input=e04a8508ca9d42fc]*/ { - PyObject *func = NULL; - PyObject *defaults = NULL; - if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) { - return NULL; - } if (PyFunction_SetDefaults(func, defaults) < 0) { return NULL; } Py_RETURN_NONE; } +/*[clinic input] +_testcapi.set_func_kwdefaults_via_capi = _testcapi.set_func_defaults_via_capi +[clinic start generated code]*/ + static PyObject * -set_func_kwdefaults(PyObject *self, PyObject *args) +_testcapi_set_func_kwdefaults_via_capi_impl(PyObject *module, PyObject *func, + PyObject *defaults) +/*[clinic end generated code: output=9ed3b08177025070 input=f3cd1ca3c18de8ce]*/ { - PyObject *func = NULL; - PyObject *kwdefaults = NULL; - if (!PyArg_ParseTuple(args, "OO", &func, &kwdefaults)) { - return NULL; - } - if (PyFunction_SetKwDefaults(func, kwdefaults) < 0) { + if (PyFunction_SetKwDefaults(func, defaults) < 0) { return NULL; } Py_RETURN_NONE; @@ -637,16 +655,16 @@ static PyMethodDef test_methods[] = { // Dict watchers. {"add_dict_watcher", add_dict_watcher, METH_O, NULL}, {"clear_dict_watcher", clear_dict_watcher, METH_O, NULL}, - {"watch_dict", watch_dict, METH_VARARGS, NULL}, - {"unwatch_dict", unwatch_dict, METH_VARARGS, NULL}, + _TESTCAPI_WATCH_DICT_METHODDEF + _TESTCAPI_UNWATCH_DICT_METHODDEF {"get_dict_watcher_events", (PyCFunction) get_dict_watcher_events, METH_NOARGS, NULL}, // Type watchers. {"add_type_watcher", add_type_watcher, METH_O, NULL}, {"clear_type_watcher", clear_type_watcher, METH_O, NULL}, - {"watch_type", watch_type, METH_VARARGS, NULL}, - {"unwatch_type", unwatch_type, METH_VARARGS, NULL}, + _TESTCAPI_WATCH_TYPE_METHODDEF + _TESTCAPI_UNWATCH_TYPE_METHODDEF {"get_type_modified_events", (PyCFunction) get_type_modified_events, METH_NOARGS, NULL}, @@ -663,8 +681,8 @@ static PyMethodDef test_methods[] = { // Function watchers. {"add_func_watcher", add_func_watcher, METH_O, NULL}, {"clear_func_watcher", clear_func_watcher, METH_O, NULL}, - {"set_func_defaults_via_capi", set_func_defaults, METH_VARARGS, NULL}, - {"set_func_kwdefaults_via_capi", set_func_kwdefaults, METH_VARARGS, NULL}, + _TESTCAPI_SET_FUNC_DEFAULTS_VIA_CAPI_METHODDEF + _TESTCAPI_SET_FUNC_KWDEFAULTS_VIA_CAPI_METHODDEF {"allocate_too_many_func_watchers", allocate_too_many_func_watchers, METH_NOARGS, NULL}, {NULL}, diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index c29d29c4791134..aff09aac80c610 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1808,10 +1808,9 @@ pymarshal_write_long_to_file(PyObject* self, PyObject *args) } PyMarshal_WriteLongToFile(value, fp, version); + assert(!PyErr_Occurred()); fclose(fp); - if (PyErr_Occurred()) - return NULL; Py_RETURN_NONE; } @@ -1834,10 +1833,9 @@ pymarshal_write_object_to_file(PyObject* self, PyObject *args) } PyMarshal_WriteObjectToFile(obj, fp, version); + assert(!PyErr_Occurred()); fclose(fp); - if (PyErr_Occurred()) - return NULL; Py_RETURN_NONE; } @@ -1895,48 +1893,46 @@ pymarshal_read_long_from_file(PyObject* self, PyObject *args) static PyObject* pymarshal_read_last_object_from_file(PyObject* self, PyObject *args) { - PyObject *obj; - long pos; PyObject *filename; - FILE *fp; - if (!PyArg_ParseTuple(args, "O:pymarshal_read_last_object_from_file", &filename)) return NULL; - fp = _Py_fopen_obj(filename, "rb"); + FILE *fp = _Py_fopen_obj(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - obj = PyMarshal_ReadLastObjectFromFile(fp); - pos = ftell(fp); + PyObject *obj = PyMarshal_ReadLastObjectFromFile(fp); + long pos = ftell(fp); fclose(fp); + if (obj == NULL) { + return NULL; + } return Py_BuildValue("Nl", obj, pos); } static PyObject* pymarshal_read_object_from_file(PyObject* self, PyObject *args) { - PyObject *obj; - long pos; PyObject *filename; - FILE *fp; - if (!PyArg_ParseTuple(args, "O:pymarshal_read_object_from_file", &filename)) return NULL; - fp = _Py_fopen_obj(filename, "rb"); + FILE *fp = _Py_fopen_obj(filename, "rb"); if (fp == NULL) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } - obj = PyMarshal_ReadObjectFromFile(fp); - pos = ftell(fp); + PyObject *obj = PyMarshal_ReadObjectFromFile(fp); + long pos = ftell(fp); fclose(fp); + if (obj == NULL) { + return NULL; + } return Py_BuildValue("Nl", obj, pos); } @@ -3062,6 +3058,33 @@ settrace_to_record(PyObject *self, PyObject *list) Py_RETURN_NONE; } +static int +error_func(PyObject *obj, PyFrameObject *f, int what, PyObject *arg) +{ + assert(PyList_Check(obj)); + /* Only raise if list is empty, otherwise append None + * This ensures that we only raise once */ + if (PyList_GET_SIZE(obj)) { + return 0; + } + if (PyList_Append(obj, Py_None)) { + return -1; + } + PyErr_SetString(PyExc_Exception, "an exception"); + return -1; +} + +static PyObject * +settrace_to_error(PyObject *self, PyObject *list) +{ + if (!PyList_Check(list)) { + PyErr_SetString(PyExc_TypeError, "argument must be a list"); + return NULL; + } + PyEval_SetTrace(error_func, list); + Py_RETURN_NONE; +} + static PyObject * clear_managed_dict(PyObject *self, PyObject *obj) { @@ -3352,6 +3375,7 @@ static PyMethodDef TestMethods[] = { {"gen_get_code", gen_get_code, METH_O, NULL}, {"get_feature_macros", get_feature_macros, METH_NOARGS, NULL}, {"test_code_api", test_code_api, METH_NOARGS, NULL}, + {"settrace_to_error", settrace_to_error, METH_O, NULL}, {"settrace_to_record", settrace_to_record, METH_O, NULL}, {"test_macros", test_macros, METH_NOARGS, NULL}, {"clear_managed_dict", clear_managed_dict, METH_O, NULL}, diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c index ea9b6e72b3c924..b91f7b620fdb4e 100644 --- a/Modules/_testinternalcapi.c +++ b/Modules/_testinternalcapi.c @@ -12,6 +12,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "frameobject.h" #include "pycore_atomic_funcs.h" // _Py_atomic_int_get() #include "pycore_bitutils.h" // _Py_bswap32() #include "pycore_compile.h" // _PyCompile_CodeGen, _PyCompile_OptimizeCfg, _PyCompile_Assemble @@ -615,16 +616,17 @@ _testinternalcapi.optimize_cfg -> object instructions: object consts: object + nlocals: int Apply compiler optimizations to an instruction list. [clinic start generated code]*/ static PyObject * _testinternalcapi_optimize_cfg_impl(PyObject *module, PyObject *instructions, - PyObject *consts) -/*[clinic end generated code: output=5412aeafca683c8b input=7e8a3de86ebdd0f9]*/ + PyObject *consts, int nlocals) +/*[clinic end generated code: output=57c53c3a3dfd1df0 input=6a96d1926d58d7e5]*/ { - return _PyCompile_OptimizeCfg(instructions, consts); + return _PyCompile_OptimizeCfg(instructions, consts, nlocals); } static int @@ -757,6 +759,63 @@ clear_extension(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +write_perf_map_entry(PyObject *self, PyObject *args) +{ + const void *code_addr; + unsigned int code_size; + const char *entry_name; + + if (!PyArg_ParseTuple(args, "KIs", &code_addr, &code_size, &entry_name)) + return NULL; + + int ret = PyUnstable_WritePerfMapEntry(code_addr, code_size, entry_name); + if (ret == -1) { + PyErr_SetString(PyExc_OSError, "Failed to write performance map entry"); + return NULL; + } + return Py_BuildValue("i", ret); +} + +static PyObject * +perf_map_state_teardown(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored)) +{ + PyUnstable_PerfMapState_Fini(); + Py_RETURN_NONE; +} + +static PyObject * +iframe_getcode(PyObject *self, PyObject *frame) +{ + if (!PyFrame_Check(frame)) { + PyErr_SetString(PyExc_TypeError, "argument must be a frame"); + return NULL; + } + struct _PyInterpreterFrame *f = ((PyFrameObject *)frame)->f_frame; + return PyUnstable_InterpreterFrame_GetCode(f); +} + +static PyObject * +iframe_getline(PyObject *self, PyObject *frame) +{ + if (!PyFrame_Check(frame)) { + PyErr_SetString(PyExc_TypeError, "argument must be a frame"); + return NULL; + } + struct _PyInterpreterFrame *f = ((PyFrameObject *)frame)->f_frame; + return PyLong_FromLong(PyUnstable_InterpreterFrame_GetLine(f)); +} + +static PyObject * +iframe_getlasti(PyObject *self, PyObject *frame) +{ + if (!PyFrame_Check(frame)) { + PyErr_SetString(PyExc_TypeError, "argument must be a frame"); + return NULL; + } + struct _PyInterpreterFrame *f = ((PyFrameObject *)frame)->f_frame; + return PyLong_FromLong(PyUnstable_InterpreterFrame_GetLasti(f)); +} static PyMethodDef module_functions[] = { {"get_configs", get_configs, METH_NOARGS}, @@ -781,6 +840,11 @@ static PyMethodDef module_functions[] = { _TESTINTERNALCAPI_ASSEMBLE_CODE_OBJECT_METHODDEF {"get_interp_settings", get_interp_settings, METH_VARARGS, NULL}, {"clear_extension", clear_extension, METH_VARARGS, NULL}, + {"write_perf_map_entry", write_perf_map_entry, METH_VARARGS}, + {"perf_map_state_teardown", perf_map_state_teardown, METH_NOARGS}, + {"iframe_getcode", iframe_getcode, METH_O, NULL}, + {"iframe_getline", iframe_getline, METH_O, NULL}, + {"iframe_getlasti", iframe_getlasti, METH_O, NULL}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 4dada0b28f0559..49c94447c7237c 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -60,6 +60,9 @@ Copyright (C) 1994 Steen Lumholt. #error "Tk older than 8.5.12 not supported" #endif +#ifndef TCL_WITH_EXTERNAL_TOMMATH +#define TCL_NO_TOMMATH_H +#endif #include #if !(defined(MS_WINDOWS) || defined(__CYGWIN__)) diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index c5714d5e7d5a0f..f3f4af9aba08c1 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -1,987 +1,12 @@ #include "Python.h" -#include "pycore_fileutils.h" // _Py_write_noraise() -#include "pycore_gc.h" // PyGC_Head -#include "pycore_hashtable.h" // _Py_hashtable_t -#include "pycore_object.h" // _PyType_PreHeaderSize -#include "pycore_pymem.h" // _Py_tracemalloc_config -#include "pycore_runtime.h" // _Py_ID() -#include "pycore_traceback.h" -#include -#include "frameobject.h" // _PyInterpreterFrame_GetLine -#include // malloc() - -#include "clinic/_tracemalloc.c.h" - -/*[clinic input] -module _tracemalloc -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/ - -#define tracemalloc_config _PyRuntime.tracemalloc.config - -_Py_DECLARE_STR(anon_unknown, ""); - -/* Forward declaration */ -static void tracemalloc_stop(void); -static void* raw_malloc(size_t size); -static void raw_free(void *ptr); - -#ifdef Py_DEBUG -# define TRACE_DEBUG -#endif - -#define TO_PTR(key) ((const void *)(uintptr_t)(key)) -#define FROM_PTR(key) ((uintptr_t)(key)) - -#define allocators _PyRuntime.tracemalloc.allocators - - -#if defined(TRACE_RAW_MALLOC) -/* This lock is needed because tracemalloc_free() is called without - the GIL held from PyMem_RawFree(). It cannot acquire the lock because it - would introduce a deadlock in _PyThreadState_DeleteCurrent(). */ -# define tables_lock _PyRuntime.tracemalloc.tables_lock -# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1) -# define TABLES_UNLOCK() PyThread_release_lock(tables_lock) -#else - /* variables are protected by the GIL */ -# define TABLES_LOCK() -# define TABLES_UNLOCK() -#endif - - -#define DEFAULT_DOMAIN 0 - -typedef struct tracemalloc_frame frame_t; -typedef struct tracemalloc_traceback traceback_t; - -#define TRACEBACK_SIZE(NFRAME) \ - (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1)) - -/* The maximum number of frames is either: - - The maximum number of frames we can store in `traceback_t.nframe` - - The maximum memory size_t we can allocate */ -static const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1)); - - -#define tracemalloc_empty_traceback _PyRuntime.tracemalloc.empty_traceback - - -/* Trace of a memory block */ -typedef struct { - /* Size of the memory block in bytes */ - size_t size; - - /* Traceback where the memory block was allocated */ - traceback_t *traceback; -} trace_t; - - -#define tracemalloc_traced_memory _PyRuntime.tracemalloc.traced_memory -#define tracemalloc_peak_traced_memory _PyRuntime.tracemalloc.peak_traced_memory -#define tracemalloc_filenames _PyRuntime.tracemalloc.filenames -#define tracemalloc_traceback _PyRuntime.tracemalloc.traceback -#define tracemalloc_tracebacks _PyRuntime.tracemalloc.tracebacks -#define tracemalloc_traces _PyRuntime.tracemalloc.traces -#define tracemalloc_domains _PyRuntime.tracemalloc.domains - - -#ifdef TRACE_DEBUG -static void -tracemalloc_error(const char *format, ...) -{ - va_list ap; - fprintf(stderr, "tracemalloc: "); - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - fprintf(stderr, "\n"); - fflush(stderr); -} -#endif - - -#if defined(TRACE_RAW_MALLOC) -#define REENTRANT_THREADLOCAL - -#define tracemalloc_reentrant_key _PyRuntime.tracemalloc.reentrant_key - -/* Any non-NULL pointer can be used */ -#define REENTRANT Py_True - -static int -get_reentrant(void) -{ - void *ptr; - - assert(PyThread_tss_is_created(&tracemalloc_reentrant_key)); - ptr = PyThread_tss_get(&tracemalloc_reentrant_key); - if (ptr != NULL) { - assert(ptr == REENTRANT); - return 1; - } - else - return 0; -} - -static void -set_reentrant(int reentrant) -{ - assert(reentrant == 0 || reentrant == 1); - assert(PyThread_tss_is_created(&tracemalloc_reentrant_key)); - - if (reentrant) { - assert(!get_reentrant()); - PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT); - } - else { - assert(get_reentrant()); - PyThread_tss_set(&tracemalloc_reentrant_key, NULL); - } -} - -#else - -/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */ -static int tracemalloc_reentrant = 0; - -static int -get_reentrant(void) -{ - return tracemalloc_reentrant; -} - -static void -set_reentrant(int reentrant) -{ - assert(reentrant != tracemalloc_reentrant); - tracemalloc_reentrant = reentrant; -} -#endif - - -static Py_uhash_t -hashtable_hash_pyobject(const void *key) -{ - PyObject *obj = (PyObject *)key; - return PyObject_Hash(obj); -} - - -static int -hashtable_compare_unicode(const void *key1, const void *key2) -{ - PyObject *obj1 = (PyObject *)key1; - PyObject *obj2 = (PyObject *)key2; - if (obj1 != NULL && obj2 != NULL) { - return (PyUnicode_Compare(obj1, obj2) == 0); - } - else { - return obj1 == obj2; - } -} - - -static Py_uhash_t -hashtable_hash_uint(const void *key_raw) -{ - unsigned int key = (unsigned int)FROM_PTR(key_raw); - return (Py_uhash_t)key; -} - - -static _Py_hashtable_t * -hashtable_new(_Py_hashtable_hash_func hash_func, - _Py_hashtable_compare_func compare_func, - _Py_hashtable_destroy_func key_destroy_func, - _Py_hashtable_destroy_func value_destroy_func) -{ - _Py_hashtable_allocator_t hashtable_alloc = {malloc, free}; - return _Py_hashtable_new_full(hash_func, compare_func, - key_destroy_func, value_destroy_func, - &hashtable_alloc); -} - - -static void* -raw_malloc(size_t size) -{ - return allocators.raw.malloc(allocators.raw.ctx, size); -} - -static void -raw_free(void *ptr) -{ - allocators.raw.free(allocators.raw.ctx, ptr); -} - - -static Py_uhash_t -hashtable_hash_traceback(const void *key) -{ - const traceback_t *traceback = (const traceback_t *)key; - return traceback->hash; -} - - -static int -hashtable_compare_traceback(const void *key1, const void *key2) -{ - const traceback_t *traceback1 = (const traceback_t *)key1; - const traceback_t *traceback2 = (const traceback_t *)key2; - - if (traceback1->nframe != traceback2->nframe) { - return 0; - } - if (traceback1->total_nframe != traceback2->total_nframe) { - return 0; - } - - for (int i=0; i < traceback1->nframe; i++) { - const frame_t *frame1 = &traceback1->frames[i]; - const frame_t *frame2 = &traceback2->frames[i]; - - if (frame1->lineno != frame2->lineno) { - return 0; - } - if (frame1->filename != frame2->filename) { - assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0); - return 0; - } - } - return 1; -} - - -static void -tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame) -{ - frame->filename = &_Py_STR(anon_unknown); - int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe); - if (lineno < 0) { - lineno = 0; - } - frame->lineno = (unsigned int)lineno; - - PyObject *filename = pyframe->f_code->co_filename; - - if (filename == NULL) { -#ifdef TRACE_DEBUG - tracemalloc_error("failed to get the filename of the code object"); -#endif - return; - } - - if (!PyUnicode_Check(filename)) { -#ifdef TRACE_DEBUG - tracemalloc_error("filename is not a unicode string"); -#endif - return; - } - if (!PyUnicode_IS_READY(filename)) { - /* Don't make a Unicode string ready to avoid reentrant calls - to tracemalloc_malloc() or tracemalloc_realloc() */ -#ifdef TRACE_DEBUG - tracemalloc_error("filename is not a ready unicode string"); -#endif - return; - } - - /* intern the filename */ - _Py_hashtable_entry_t *entry; - entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename); - if (entry != NULL) { - filename = (PyObject *)entry->key; - } - else { - /* tracemalloc_filenames is responsible to keep a reference - to the filename */ - if (_Py_hashtable_set(tracemalloc_filenames, Py_NewRef(filename), - NULL) < 0) { - Py_DECREF(filename); -#ifdef TRACE_DEBUG - tracemalloc_error("failed to intern the filename"); -#endif - return; - } - } - - /* the tracemalloc_filenames table keeps a reference to the filename */ - frame->filename = filename; -} - - -static Py_uhash_t -traceback_hash(traceback_t *traceback) -{ - /* code based on tuplehash() of Objects/tupleobject.c */ - Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */ - int len = traceback->nframe; - Py_uhash_t mult = _PyHASH_MULTIPLIER; - frame_t *frame; - - x = 0x345678UL; - frame = traceback->frames; - while (--len >= 0) { - y = (Py_uhash_t)PyObject_Hash(frame->filename); - y ^= (Py_uhash_t)frame->lineno; - frame++; - - x = (x ^ y) * mult; - /* the cast might truncate len; that doesn't change hash stability */ - mult += (Py_uhash_t)(82520UL + len + len); - } - x ^= traceback->total_nframe; - x += 97531UL; - return x; -} - - -static void -traceback_get_frames(traceback_t *traceback) -{ - PyThreadState *tstate = PyGILState_GetThisThreadState(); - if (tstate == NULL) { -#ifdef TRACE_DEBUG - tracemalloc_error("failed to get the current thread state"); -#endif - return; - } - - _PyInterpreterFrame *pyframe = _PyThreadState_GetFrame(tstate); - while (pyframe) { - if (traceback->nframe < tracemalloc_config.max_nframe) { - tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]); - assert(traceback->frames[traceback->nframe].filename != NULL); - traceback->nframe++; - } - if (traceback->total_nframe < UINT16_MAX) { - traceback->total_nframe++; - } - pyframe = _PyFrame_GetFirstComplete(pyframe->previous); - } -} - - -static traceback_t * -traceback_new(void) -{ - traceback_t *traceback; - _Py_hashtable_entry_t *entry; - - assert(PyGILState_Check()); - - /* get frames */ - traceback = tracemalloc_traceback; - traceback->nframe = 0; - traceback->total_nframe = 0; - traceback_get_frames(traceback); - if (traceback->nframe == 0) - return &tracemalloc_empty_traceback; - traceback->hash = traceback_hash(traceback); - - /* intern the traceback */ - entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback); - if (entry != NULL) { - traceback = (traceback_t *)entry->key; - } - else { - traceback_t *copy; - size_t traceback_size; - - traceback_size = TRACEBACK_SIZE(traceback->nframe); - - copy = raw_malloc(traceback_size); - if (copy == NULL) { -#ifdef TRACE_DEBUG - tracemalloc_error("failed to intern the traceback: malloc failed"); -#endif - return NULL; - } - memcpy(copy, traceback, traceback_size); - - if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL) < 0) { - raw_free(copy); -#ifdef TRACE_DEBUG - tracemalloc_error("failed to intern the traceback: putdata failed"); -#endif - return NULL; - } - traceback = copy; - } - return traceback; -} - - -static _Py_hashtable_t* -tracemalloc_create_traces_table(void) -{ - return hashtable_new(_Py_hashtable_hash_ptr, - _Py_hashtable_compare_direct, - NULL, raw_free); -} - - -static _Py_hashtable_t* -tracemalloc_create_domains_table(void) -{ - return hashtable_new(hashtable_hash_uint, - _Py_hashtable_compare_direct, - NULL, - (_Py_hashtable_destroy_func)_Py_hashtable_destroy); -} - - -static _Py_hashtable_t* -tracemalloc_get_traces_table(unsigned int domain) -{ - if (domain == DEFAULT_DOMAIN) { - return tracemalloc_traces; - } - else { - return _Py_hashtable_get(tracemalloc_domains, TO_PTR(domain)); - } -} - - -static void -tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr) -{ - assert(tracemalloc_config.tracing); - - _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); - if (!traces) { - return; - } - - trace_t *trace = _Py_hashtable_steal(traces, TO_PTR(ptr)); - if (!trace) { - return; - } - assert(tracemalloc_traced_memory >= trace->size); - tracemalloc_traced_memory -= trace->size; - raw_free(trace); -} - -#define REMOVE_TRACE(ptr) \ - tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr)) - - -static int -tracemalloc_add_trace(unsigned int domain, uintptr_t ptr, - size_t size) -{ - assert(tracemalloc_config.tracing); - - traceback_t *traceback = traceback_new(); - if (traceback == NULL) { - return -1; - } - - _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); - if (traces == NULL) { - traces = tracemalloc_create_traces_table(); - if (traces == NULL) { - return -1; - } - - if (_Py_hashtable_set(tracemalloc_domains, TO_PTR(domain), traces) < 0) { - _Py_hashtable_destroy(traces); - return -1; - } - } - - trace_t *trace = _Py_hashtable_get(traces, TO_PTR(ptr)); - if (trace != NULL) { - /* the memory block is already tracked */ - assert(tracemalloc_traced_memory >= trace->size); - tracemalloc_traced_memory -= trace->size; - - trace->size = size; - trace->traceback = traceback; - } - else { - trace = raw_malloc(sizeof(trace_t)); - if (trace == NULL) { - return -1; - } - trace->size = size; - trace->traceback = traceback; - - int res = _Py_hashtable_set(traces, TO_PTR(ptr), trace); - if (res != 0) { - raw_free(trace); - return res; - } - } - - assert(tracemalloc_traced_memory <= SIZE_MAX - size); - tracemalloc_traced_memory += size; - if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory) { - tracemalloc_peak_traced_memory = tracemalloc_traced_memory; - } - return 0; -} - -#define ADD_TRACE(ptr, size) \ - tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size) - - -static void* -tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize) -{ - PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; - void *ptr; - - assert(elsize == 0 || nelem <= SIZE_MAX / elsize); - - if (use_calloc) - ptr = alloc->calloc(alloc->ctx, nelem, elsize); - else - ptr = alloc->malloc(alloc->ctx, nelem * elsize); - if (ptr == NULL) - return NULL; - - TABLES_LOCK(); - if (ADD_TRACE(ptr, nelem * elsize) < 0) { - /* Failed to allocate a trace for the new memory block */ - TABLES_UNLOCK(); - alloc->free(alloc->ctx, ptr); - return NULL; - } - TABLES_UNLOCK(); - return ptr; -} - - -static void* -tracemalloc_realloc(void *ctx, void *ptr, size_t new_size) -{ - PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; - void *ptr2; - - ptr2 = alloc->realloc(alloc->ctx, ptr, new_size); - if (ptr2 == NULL) - return NULL; - - if (ptr != NULL) { - /* an existing memory block has been resized */ - - TABLES_LOCK(); - - /* tracemalloc_add_trace() updates the trace if there is already - a trace at address ptr2 */ - if (ptr2 != ptr) { - REMOVE_TRACE(ptr); - } - - if (ADD_TRACE(ptr2, new_size) < 0) { - /* Memory allocation failed. The error cannot be reported to - the caller, because realloc() may already have shrunk the - memory block and so removed bytes. - - This case is very unlikely: a hash entry has just been - released, so the hash table should have at least one free entry. - - The GIL and the table lock ensures that only one thread is - allocating memory. */ - Py_FatalError("tracemalloc_realloc() failed to allocate a trace"); - } - TABLES_UNLOCK(); - } - else { - /* new allocation */ - - TABLES_LOCK(); - if (ADD_TRACE(ptr2, new_size) < 0) { - /* Failed to allocate a trace for the new memory block */ - TABLES_UNLOCK(); - alloc->free(alloc->ctx, ptr2); - return NULL; - } - TABLES_UNLOCK(); - } - return ptr2; -} - - -static void -tracemalloc_free(void *ctx, void *ptr) -{ - PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; - - if (ptr == NULL) - return; - - /* GIL cannot be locked in PyMem_RawFree() because it would introduce - a deadlock in _PyThreadState_DeleteCurrent(). */ - - alloc->free(alloc->ctx, ptr); - - TABLES_LOCK(); - REMOVE_TRACE(ptr); - TABLES_UNLOCK(); -} - - -static void* -tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize) -{ - void *ptr; - - if (get_reentrant()) { - PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; - if (use_calloc) - return alloc->calloc(alloc->ctx, nelem, elsize); - else - return alloc->malloc(alloc->ctx, nelem * elsize); - } - - /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for - allocations larger than 512 bytes, don't trace the same memory - allocation twice. */ - set_reentrant(1); - - ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize); - - set_reentrant(0); - return ptr; -} - - -static void* -tracemalloc_malloc_gil(void *ctx, size_t size) -{ - return tracemalloc_alloc_gil(0, ctx, 1, size); -} - - -static void* -tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize) -{ - return tracemalloc_alloc_gil(1, ctx, nelem, elsize); -} - - -static void* -tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size) -{ - void *ptr2; - - if (get_reentrant()) { - /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc(). - Example: PyMem_RawRealloc() is called internally by pymalloc - (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new - arena (new_arena()). */ - PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; - - ptr2 = alloc->realloc(alloc->ctx, ptr, new_size); - if (ptr2 != NULL && ptr != NULL) { - TABLES_LOCK(); - REMOVE_TRACE(ptr); - TABLES_UNLOCK(); - } - return ptr2; - } - - /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for - allocations larger than 512 bytes. Don't trace the same memory - allocation twice. */ - set_reentrant(1); - - ptr2 = tracemalloc_realloc(ctx, ptr, new_size); - - set_reentrant(0); - return ptr2; -} - - -#ifdef TRACE_RAW_MALLOC -static void* -tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize) -{ - PyGILState_STATE gil_state; - void *ptr; - - if (get_reentrant()) { - PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; - if (use_calloc) - return alloc->calloc(alloc->ctx, nelem, elsize); - else - return alloc->malloc(alloc->ctx, nelem * elsize); - } - - /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc() - indirectly which would call PyGILState_Ensure() if reentrant are not - disabled. */ - set_reentrant(1); - - gil_state = PyGILState_Ensure(); - ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize); - PyGILState_Release(gil_state); - - set_reentrant(0); - return ptr; -} - - -static void* -tracemalloc_raw_malloc(void *ctx, size_t size) -{ - return tracemalloc_raw_alloc(0, ctx, 1, size); -} - - -static void* -tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize) -{ - return tracemalloc_raw_alloc(1, ctx, nelem, elsize); -} - - -static void* -tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size) -{ - PyGILState_STATE gil_state; - void *ptr2; - - if (get_reentrant()) { - /* Reentrant call to PyMem_RawRealloc(). */ - PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; - - ptr2 = alloc->realloc(alloc->ctx, ptr, new_size); - - if (ptr2 != NULL && ptr != NULL) { - TABLES_LOCK(); - REMOVE_TRACE(ptr); - TABLES_UNLOCK(); - } - return ptr2; - } - - /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc() - indirectly which would call PyGILState_Ensure() if reentrant calls are - not disabled. */ - set_reentrant(1); - - gil_state = PyGILState_Ensure(); - ptr2 = tracemalloc_realloc(ctx, ptr, new_size); - PyGILState_Release(gil_state); - - set_reentrant(0); - return ptr2; -} -#endif /* TRACE_RAW_MALLOC */ - - -static void -tracemalloc_clear_filename(void *value) -{ - PyObject *filename = (PyObject *)value; - Py_DECREF(filename); -} - - -/* reentrant flag must be set to call this function and GIL must be held */ -static void -tracemalloc_clear_traces(void) -{ - /* The GIL protects variables against concurrent access */ - assert(PyGILState_Check()); - - TABLES_LOCK(); - _Py_hashtable_clear(tracemalloc_traces); - _Py_hashtable_clear(tracemalloc_domains); - tracemalloc_traced_memory = 0; - tracemalloc_peak_traced_memory = 0; - TABLES_UNLOCK(); - - _Py_hashtable_clear(tracemalloc_tracebacks); - - _Py_hashtable_clear(tracemalloc_filenames); -} - - -static int -tracemalloc_init(void) -{ - if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) { - PyErr_SetString(PyExc_RuntimeError, - "the tracemalloc module has been unloaded"); - return -1; - } - - if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED) - return 0; - - PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); - -#ifdef REENTRANT_THREADLOCAL - if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) { -#ifdef MS_WINDOWS - PyErr_SetFromWindowsErr(0); -#else - PyErr_SetFromErrno(PyExc_OSError); -#endif - return -1; - } -#endif - -#if defined(TRACE_RAW_MALLOC) - if (tables_lock == NULL) { - tables_lock = PyThread_allocate_lock(); - if (tables_lock == NULL) { - PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock"); - return -1; - } - } -#endif - - tracemalloc_filenames = hashtable_new(hashtable_hash_pyobject, - hashtable_compare_unicode, - tracemalloc_clear_filename, NULL); - - tracemalloc_tracebacks = hashtable_new(hashtable_hash_traceback, - hashtable_compare_traceback, - NULL, raw_free); - - tracemalloc_traces = tracemalloc_create_traces_table(); - tracemalloc_domains = tracemalloc_create_domains_table(); - - if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL - || tracemalloc_traces == NULL || tracemalloc_domains == NULL) { - PyErr_NoMemory(); - return -1; - } - - tracemalloc_empty_traceback.nframe = 1; - tracemalloc_empty_traceback.total_nframe = 1; - /* borrowed reference */ - tracemalloc_empty_traceback.frames[0].filename = &_Py_STR(anon_unknown); - tracemalloc_empty_traceback.frames[0].lineno = 0; - tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback); - - tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED; - return 0; -} - - -static void -tracemalloc_deinit(void) -{ - if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED) - return; - tracemalloc_config.initialized = TRACEMALLOC_FINALIZED; - - tracemalloc_stop(); - - /* destroy hash tables */ - _Py_hashtable_destroy(tracemalloc_domains); - _Py_hashtable_destroy(tracemalloc_traces); - _Py_hashtable_destroy(tracemalloc_tracebacks); - _Py_hashtable_destroy(tracemalloc_filenames); - -#if defined(TRACE_RAW_MALLOC) - if (tables_lock != NULL) { - PyThread_free_lock(tables_lock); - tables_lock = NULL; - } -#endif - -#ifdef REENTRANT_THREADLOCAL - PyThread_tss_delete(&tracemalloc_reentrant_key); -#endif -} - - -static int -tracemalloc_start(int max_nframe) -{ - PyMemAllocatorEx alloc; - size_t size; - - if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) { - PyErr_Format(PyExc_ValueError, - "the number of frames must be in range [1; %lu]", - MAX_NFRAME); - return -1; - } - - if (tracemalloc_init() < 0) { - return -1; - } - - if (tracemalloc_config.tracing) { - /* hook already installed: do nothing */ - return 0; - } - - tracemalloc_config.max_nframe = max_nframe; - - /* allocate a buffer to store a new traceback */ - size = TRACEBACK_SIZE(max_nframe); - assert(tracemalloc_traceback == NULL); - tracemalloc_traceback = raw_malloc(size); - if (tracemalloc_traceback == NULL) { - PyErr_NoMemory(); - return -1; - } - -#ifdef TRACE_RAW_MALLOC - alloc.malloc = tracemalloc_raw_malloc; - alloc.calloc = tracemalloc_raw_calloc; - alloc.realloc = tracemalloc_raw_realloc; - alloc.free = tracemalloc_free; - - alloc.ctx = &allocators.raw; - PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc); -#endif - - alloc.malloc = tracemalloc_malloc_gil; - alloc.calloc = tracemalloc_calloc_gil; - alloc.realloc = tracemalloc_realloc_gil; - alloc.free = tracemalloc_free; - - alloc.ctx = &allocators.mem; - PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem); - PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc); - - alloc.ctx = &allocators.obj; - PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj); - PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc); - - /* everything is ready: start tracing Python memory allocations */ - tracemalloc_config.tracing = 1; - - return 0; -} - - -static void -tracemalloc_stop(void) -{ - if (!tracemalloc_config.tracing) - return; - - /* stop tracing Python memory allocations */ - tracemalloc_config.tracing = 0; - - /* unregister the hook on memory allocators */ -#ifdef TRACE_RAW_MALLOC - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); -#endif - PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem); - PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj); - - tracemalloc_clear_traces(); +#include "clinic/_tracemalloc.c.h" - /* release memory */ - raw_free(tracemalloc_traceback); - tracemalloc_traceback = NULL; -} +/*[clinic input] +module _tracemalloc +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/ /*[clinic input] @@ -994,7 +19,7 @@ static PyObject * _tracemalloc_is_tracing_impl(PyObject *module) /*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/ { - return PyBool_FromLong(tracemalloc_config.tracing); + return PyBool_FromLong(_PyTraceMalloc_IsTracing()); } @@ -1008,262 +33,11 @@ static PyObject * _tracemalloc_clear_traces_impl(PyObject *module) /*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/ { - if (!tracemalloc_config.tracing) - Py_RETURN_NONE; - - set_reentrant(1); - tracemalloc_clear_traces(); - set_reentrant(0); - + _PyTraceMalloc_ClearTraces(); Py_RETURN_NONE; } -static PyObject* -frame_to_pyobject(frame_t *frame) -{ - PyObject *frame_obj, *lineno_obj; - - frame_obj = PyTuple_New(2); - if (frame_obj == NULL) - return NULL; - - PyTuple_SET_ITEM(frame_obj, 0, Py_NewRef(frame->filename)); - - lineno_obj = PyLong_FromUnsignedLong(frame->lineno); - if (lineno_obj == NULL) { - Py_DECREF(frame_obj); - return NULL; - } - PyTuple_SET_ITEM(frame_obj, 1, lineno_obj); - - return frame_obj; -} - - -static PyObject* -traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) -{ - PyObject *frames; - - if (intern_table != NULL) { - frames = _Py_hashtable_get(intern_table, (const void *)traceback); - if (frames) { - return Py_NewRef(frames); - } - } - - frames = PyTuple_New(traceback->nframe); - if (frames == NULL) - return NULL; - - for (int i=0; i < traceback->nframe; i++) { - PyObject *frame = frame_to_pyobject(&traceback->frames[i]); - if (frame == NULL) { - Py_DECREF(frames); - return NULL; - } - PyTuple_SET_ITEM(frames, i, frame); - } - - if (intern_table != NULL) { - if (_Py_hashtable_set(intern_table, traceback, frames) < 0) { - Py_DECREF(frames); - PyErr_NoMemory(); - return NULL; - } - /* intern_table keeps a new reference to frames */ - Py_INCREF(frames); - } - return frames; -} - - -static PyObject* -trace_to_pyobject(unsigned int domain, const trace_t *trace, - _Py_hashtable_t *intern_tracebacks) -{ - PyObject *trace_obj = NULL; - PyObject *obj; - - trace_obj = PyTuple_New(4); - if (trace_obj == NULL) - return NULL; - - obj = PyLong_FromSize_t(domain); - if (obj == NULL) { - Py_DECREF(trace_obj); - return NULL; - } - PyTuple_SET_ITEM(trace_obj, 0, obj); - - obj = PyLong_FromSize_t(trace->size); - if (obj == NULL) { - Py_DECREF(trace_obj); - return NULL; - } - PyTuple_SET_ITEM(trace_obj, 1, obj); - - obj = traceback_to_pyobject(trace->traceback, intern_tracebacks); - if (obj == NULL) { - Py_DECREF(trace_obj); - return NULL; - } - PyTuple_SET_ITEM(trace_obj, 2, obj); - - obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe); - if (obj == NULL) { - Py_DECREF(trace_obj); - return NULL; - } - PyTuple_SET_ITEM(trace_obj, 3, obj); - - return trace_obj; -} - - -typedef struct { - _Py_hashtable_t *traces; - _Py_hashtable_t *domains; - _Py_hashtable_t *tracebacks; - PyObject *list; - unsigned int domain; -} get_traces_t; - - -static int -tracemalloc_copy_trace(_Py_hashtable_t *traces, - const void *key, const void *value, - void *user_data) -{ - _Py_hashtable_t *traces2 = (_Py_hashtable_t *)user_data; - - trace_t *trace = (trace_t *)value; - - trace_t *trace2 = raw_malloc(sizeof(trace_t)); - if (trace2 == NULL) { - return -1; - } - *trace2 = *trace; - if (_Py_hashtable_set(traces2, key, trace2) < 0) { - raw_free(trace2); - return -1; - } - return 0; -} - - -static _Py_hashtable_t* -tracemalloc_copy_traces(_Py_hashtable_t *traces) -{ - _Py_hashtable_t *traces2 = tracemalloc_create_traces_table(); - if (traces2 == NULL) { - return NULL; - } - - int err = _Py_hashtable_foreach(traces, - tracemalloc_copy_trace, - traces2); - if (err) { - _Py_hashtable_destroy(traces2); - return NULL; - } - return traces2; -} - - -static int -tracemalloc_copy_domain(_Py_hashtable_t *domains, - const void *key, const void *value, - void *user_data) -{ - _Py_hashtable_t *domains2 = (_Py_hashtable_t *)user_data; - - unsigned int domain = (unsigned int)FROM_PTR(key); - _Py_hashtable_t *traces = (_Py_hashtable_t *)value; - - _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces); - if (traces2 == NULL) { - return -1; - } - if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) { - _Py_hashtable_destroy(traces2); - return -1; - } - return 0; -} - - -static _Py_hashtable_t* -tracemalloc_copy_domains(_Py_hashtable_t *domains) -{ - _Py_hashtable_t *domains2 = tracemalloc_create_domains_table(); - if (domains2 == NULL) { - return NULL; - } - - int err = _Py_hashtable_foreach(domains, - tracemalloc_copy_domain, - domains2); - if (err) { - _Py_hashtable_destroy(domains2); - return NULL; - } - return domains2; -} - - -static int -tracemalloc_get_traces_fill(_Py_hashtable_t *traces, - const void *key, const void *value, - void *user_data) -{ - get_traces_t *get_traces = user_data; - - const trace_t *trace = (const trace_t *)value; - - PyObject *tuple = trace_to_pyobject(get_traces->domain, trace, - get_traces->tracebacks); - if (tuple == NULL) { - return 1; - } - - int res = PyList_Append(get_traces->list, tuple); - Py_DECREF(tuple); - if (res < 0) { - return 1; - } - - return 0; -} - - -static int -tracemalloc_get_traces_domain(_Py_hashtable_t *domains, - const void *key, const void *value, - void *user_data) -{ - get_traces_t *get_traces = user_data; - - unsigned int domain = (unsigned int)FROM_PTR(key); - _Py_hashtable_t *traces = (_Py_hashtable_t *)value; - - get_traces->domain = domain; - return _Py_hashtable_foreach(traces, - tracemalloc_get_traces_fill, - get_traces); -} - - -static void -tracemalloc_pyobject_decref(void *value) -{ - PyObject *obj = (PyObject *)value; - Py_DECREF(obj); -} - - - /*[clinic input] _tracemalloc._get_traces @@ -1279,107 +53,7 @@ static PyObject * _tracemalloc__get_traces_impl(PyObject *module) /*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/ { - get_traces_t get_traces; - get_traces.domain = DEFAULT_DOMAIN; - get_traces.traces = NULL; - get_traces.domains = NULL; - get_traces.tracebacks = NULL; - get_traces.list = PyList_New(0); - if (get_traces.list == NULL) - goto error; - - if (!tracemalloc_config.tracing) - return get_traces.list; - - /* the traceback hash table is used temporarily to intern traceback tuple - of (filename, lineno) tuples */ - get_traces.tracebacks = hashtable_new(_Py_hashtable_hash_ptr, - _Py_hashtable_compare_direct, - NULL, tracemalloc_pyobject_decref); - if (get_traces.tracebacks == NULL) { - goto no_memory; - } - - // Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable - // temporarily tracemalloc which would impact other threads and so would - // miss allocations while get_traces() is called. - TABLES_LOCK(); - get_traces.traces = tracemalloc_copy_traces(tracemalloc_traces); - TABLES_UNLOCK(); - - if (get_traces.traces == NULL) { - goto no_memory; - } - - TABLES_LOCK(); - get_traces.domains = tracemalloc_copy_domains(tracemalloc_domains); - TABLES_UNLOCK(); - - if (get_traces.domains == NULL) { - goto no_memory; - } - - // Convert traces to a list of tuples - set_reentrant(1); - int err = _Py_hashtable_foreach(get_traces.traces, - tracemalloc_get_traces_fill, - &get_traces); - if (!err) { - err = _Py_hashtable_foreach(get_traces.domains, - tracemalloc_get_traces_domain, - &get_traces); - } - set_reentrant(0); - if (err) { - goto error; - } - - goto finally; - -no_memory: - PyErr_NoMemory(); - -error: - Py_CLEAR(get_traces.list); - -finally: - if (get_traces.tracebacks != NULL) { - _Py_hashtable_destroy(get_traces.tracebacks); - } - if (get_traces.traces != NULL) { - _Py_hashtable_destroy(get_traces.traces); - } - if (get_traces.domains != NULL) { - _Py_hashtable_destroy(get_traces.domains); - } - - return get_traces.list; -} - - -static traceback_t* -tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr) -{ - - if (!tracemalloc_config.tracing) - return NULL; - - trace_t *trace; - TABLES_LOCK(); - _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); - if (traces) { - trace = _Py_hashtable_get(traces, TO_PTR(ptr)); - } - else { - trace = NULL; - } - TABLES_UNLOCK(); - - if (!trace) { - return NULL; - } - - return trace->traceback; + return _PyTraceMalloc_GetTraces(); } @@ -1401,62 +75,9 @@ static PyObject * _tracemalloc__get_object_traceback(PyObject *module, PyObject *obj) /*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/ { - PyTypeObject *type; - traceback_t *traceback; - - type = Py_TYPE(obj); - const size_t presize = _PyType_PreHeaderSize(type); - uintptr_t ptr = (uintptr_t)((char *)obj - presize); - - traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, ptr); - if (traceback == NULL) { - Py_RETURN_NONE; - } - - return traceback_to_pyobject(traceback, NULL); -} - - -#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) - -static void -_PyMem_DumpFrame(int fd, frame_t * frame) -{ - PUTS(fd, " File \""); - _Py_DumpASCII(fd, frame->filename); - PUTS(fd, "\", line "); - _Py_DumpDecimal(fd, frame->lineno); - PUTS(fd, "\n"); -} - -/* Dump the traceback where a memory block was allocated into file descriptor - fd. The function may block on TABLES_LOCK() but it is unlikely. */ -void -_PyMem_DumpTraceback(int fd, const void *ptr) -{ - traceback_t *traceback; - int i; - - if (!tracemalloc_config.tracing) { - PUTS(fd, "Enable tracemalloc to get the memory block " - "allocation traceback\n\n"); - return; - } - - traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr); - if (traceback == NULL) - return; - - PUTS(fd, "Memory block allocated at (most recent call first):\n"); - for (i=0; i < traceback->nframe; i++) { - _PyMem_DumpFrame(fd, &traceback->frames[i]); - } - PUTS(fd, "\n"); + return _PyTraceMalloc_GetObjectTraceback(obj); } -#undef PUTS - - /*[clinic input] _tracemalloc.start @@ -1474,7 +95,7 @@ static PyObject * _tracemalloc_start_impl(PyObject *module, int nframe) /*[clinic end generated code: output=caae05c23c159d3c input=40d849b5b29d1933]*/ { - if (tracemalloc_start(nframe) < 0) { + if (_PyTraceMalloc_Start(nframe) < 0) { return NULL; } Py_RETURN_NONE; @@ -1493,7 +114,7 @@ static PyObject * _tracemalloc_stop_impl(PyObject *module) /*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/ { - tracemalloc_stop(); + _PyTraceMalloc_Stop(); Py_RETURN_NONE; } @@ -1511,22 +132,9 @@ static PyObject * _tracemalloc_get_traceback_limit_impl(PyObject *module) /*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/ { - return PyLong_FromLong(tracemalloc_config.max_nframe); -} - - -static int -tracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains, - const void *key, const void *value, - void *user_data) -{ - const _Py_hashtable_t *traces = value; - size_t *size = (size_t*)user_data; - *size += _Py_hashtable_size(traces); - return 0; + return PyLong_FromLong(_PyTraceMalloc_GetTracebackLimit()); } - /*[clinic input] _tracemalloc.get_tracemalloc_memory @@ -1539,22 +147,10 @@ static PyObject * _tracemalloc_get_tracemalloc_memory_impl(PyObject *module) /*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/ { - size_t size; - - size = _Py_hashtable_size(tracemalloc_tracebacks); - size += _Py_hashtable_size(tracemalloc_filenames); - - TABLES_LOCK(); - size += _Py_hashtable_size(tracemalloc_traces); - _Py_hashtable_foreach(tracemalloc_domains, - tracemalloc_get_tracemalloc_memory_cb, &size); - TABLES_UNLOCK(); - - return PyLong_FromSize_t(size); + return PyLong_FromSize_t(_PyTraceMalloc_GetMemory()); } - /*[clinic input] _tracemalloc.get_traced_memory @@ -1567,17 +163,7 @@ static PyObject * _tracemalloc_get_traced_memory_impl(PyObject *module) /*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/ { - Py_ssize_t size, peak_size; - - if (!tracemalloc_config.tracing) - return Py_BuildValue("ii", 0, 0); - - TABLES_LOCK(); - size = tracemalloc_traced_memory; - peak_size = tracemalloc_peak_traced_memory; - TABLES_UNLOCK(); - - return Py_BuildValue("nn", size, peak_size); + return _PyTraceMalloc_GetTracedMemory(); } /*[clinic input] @@ -1593,14 +179,7 @@ static PyObject * _tracemalloc_reset_peak_impl(PyObject *module) /*[clinic end generated code: output=140c2870f691dbb2 input=18afd0635066e9ce]*/ { - if (!tracemalloc_config.tracing) { - Py_RETURN_NONE; - } - - TABLES_LOCK(); - tracemalloc_peak_traced_memory = tracemalloc_traced_memory; - TABLES_UNLOCK(); - + _PyTraceMalloc_ResetPeak(); Py_RETURN_NONE; } @@ -1640,118 +219,10 @@ PyInit__tracemalloc(void) if (m == NULL) return NULL; - if (tracemalloc_init() < 0) { + if (_PyTraceMalloc_Init() < 0) { Py_DECREF(m); return NULL; } return m; } - - -int -_PyTraceMalloc_Init(int nframe) -{ - assert(PyGILState_Check()); - if (nframe == 0) { - return 0; - } - return tracemalloc_start(nframe); -} - - -void -_PyTraceMalloc_Fini(void) -{ - assert(PyGILState_Check()); - tracemalloc_deinit(); -} - -int -PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, - size_t size) -{ - int res; - PyGILState_STATE gil_state; - - if (!tracemalloc_config.tracing) { - /* tracemalloc is not tracing: do nothing */ - return -2; - } - - gil_state = PyGILState_Ensure(); - - TABLES_LOCK(); - res = tracemalloc_add_trace(domain, ptr, size); - TABLES_UNLOCK(); - - PyGILState_Release(gil_state); - return res; -} - - -int -PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr) -{ - if (!tracemalloc_config.tracing) { - /* tracemalloc is not tracing: do nothing */ - return -2; - } - - TABLES_LOCK(); - tracemalloc_remove_trace(domain, ptr); - TABLES_UNLOCK(); - - return 0; -} - - -/* If the object memory block is already traced, update its trace - with the current Python traceback. - - Do nothing if tracemalloc is not tracing memory allocations - or if the object memory block is not already traced. */ -int -_PyTraceMalloc_NewReference(PyObject *op) -{ - assert(PyGILState_Check()); - - if (!tracemalloc_config.tracing) { - /* tracemalloc is not tracing: do nothing */ - return -1; - } - - PyTypeObject *type = Py_TYPE(op); - const size_t presize = _PyType_PreHeaderSize(type); - uintptr_t ptr = (uintptr_t)((char *)op - presize); - - int res = -1; - - TABLES_LOCK(); - trace_t *trace = _Py_hashtable_get(tracemalloc_traces, TO_PTR(ptr)); - if (trace != NULL) { - /* update the traceback of the memory block */ - traceback_t *traceback = traceback_new(); - if (traceback != NULL) { - trace->traceback = traceback; - res = 0; - } - } - /* else: cannot track the object, its memory block size is unknown */ - TABLES_UNLOCK(); - - return res; -} - - -PyObject* -_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr) -{ - traceback_t *traceback; - - traceback = tracemalloc_get_traceback(domain, ptr); - if (traceback == NULL) - Py_RETURN_NONE; - - return traceback_to_pyobject(traceback, NULL); -} diff --git a/Modules/_typingmodule.c b/Modules/_typingmodule.c index 64286375636aff..39a124a26adf31 100644 --- a/Modules/_typingmodule.c +++ b/Modules/_typingmodule.c @@ -1,6 +1,12 @@ /* typing accelerator C extension: _typing module. */ +#ifndef Py_BUILD_CORE +#define Py_BUILD_CORE +#endif + #include "Python.h" +#include "internal/pycore_interp.h" +#include "internal/pycore_typevarobject.h" #include "clinic/_typingmodule.c.h" /*[clinic input] @@ -35,7 +41,32 @@ static PyMethodDef typing_methods[] = { PyDoc_STRVAR(typing_doc, "Accelerators for the typing module.\n"); +static int +_typing_exec(PyObject *m) +{ + PyInterpreterState *interp = PyInterpreterState_Get(); + +#define EXPORT_TYPE(name, typename) \ + if (PyModule_AddObjectRef(m, name, \ + (PyObject *)interp->cached_objects.typename) < 0) { \ + return -1; \ + } + + EXPORT_TYPE("TypeVar", typevar_type); + EXPORT_TYPE("TypeVarTuple", typevartuple_type); + EXPORT_TYPE("ParamSpec", paramspec_type); + EXPORT_TYPE("ParamSpecArgs", paramspecargs_type); + EXPORT_TYPE("ParamSpecKwargs", paramspeckwargs_type); + EXPORT_TYPE("Generic", generic_type); +#undef EXPORT_TYPE + if (PyModule_AddObjectRef(m, "TypeAliasType", (PyObject *)&_PyTypeAlias_Type) < 0) { + return -1; + } + return 0; +} + static struct PyModuleDef_Slot _typingmodule_slots[] = { + {Py_mod_exec, _typing_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {0, NULL} }; diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 473bcb4736e925..1e02dbc1a4bfd1 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -133,7 +133,7 @@ overlapped_dealloc(OverlappedObject *self) { /* The operation is no longer pending -- nothing to do. */ } - else if (_Py_IsFinalizing()) + else if (_Py_IsInterpreterFinalizing(PyInterpreterState_Get())) { /* The operation is still pending -- give a warning. This will probably only happen on Windows XP. */ diff --git a/Modules/clinic/_testinternalcapi.c.h b/Modules/clinic/_testinternalcapi.c.h index 41dd50437956c4..f5124125874503 100644 --- a/Modules/clinic/_testinternalcapi.c.h +++ b/Modules/clinic/_testinternalcapi.c.h @@ -83,7 +83,7 @@ _testinternalcapi_compiler_codegen(PyObject *module, PyObject *const *args, Py_s } PyDoc_STRVAR(_testinternalcapi_optimize_cfg__doc__, -"optimize_cfg($module, /, instructions, consts)\n" +"optimize_cfg($module, /, instructions, consts, nlocals)\n" "--\n" "\n" "Apply compiler optimizations to an instruction list."); @@ -93,7 +93,7 @@ PyDoc_STRVAR(_testinternalcapi_optimize_cfg__doc__, static PyObject * _testinternalcapi_optimize_cfg_impl(PyObject *module, PyObject *instructions, - PyObject *consts); + PyObject *consts, int nlocals); static PyObject * _testinternalcapi_optimize_cfg(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) @@ -101,14 +101,14 @@ _testinternalcapi_optimize_cfg(PyObject *module, PyObject *const *args, Py_ssize PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 2 + #define NUM_KEYWORDS 3 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD PyObject *ob_item[NUM_KEYWORDS]; } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(instructions), &_Py_ID(consts), }, + .ob_item = { &_Py_ID(instructions), &_Py_ID(consts), &_Py_ID(nlocals), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -117,24 +117,29 @@ _testinternalcapi_optimize_cfg(PyObject *module, PyObject *const *args, Py_ssize # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"instructions", "consts", NULL}; + static const char * const _keywords[] = {"instructions", "consts", "nlocals", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "optimize_cfg", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[2]; + PyObject *argsbuf[3]; PyObject *instructions; PyObject *consts; + int nlocals; - args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf); if (!args) { goto exit; } instructions = args[0]; consts = args[1]; - return_value = _testinternalcapi_optimize_cfg_impl(module, instructions, consts); + nlocals = _PyLong_AsInt(args[2]); + if (nlocals == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _testinternalcapi_optimize_cfg_impl(module, instructions, consts, nlocals); exit: return return_value; @@ -201,4 +206,4 @@ _testinternalcapi_assemble_code_object(PyObject *module, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=ab661d56a14b1a1c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2965f1578b986218 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h index bc5bbceb4c92b6..c16c1b083985f2 100644 --- a/Modules/clinic/mathmodule.c.h +++ b/Modules/clinic/mathmodule.c.h @@ -826,25 +826,59 @@ math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs) } PyDoc_STRVAR(math_nextafter__doc__, -"nextafter($module, x, y, /)\n" +"nextafter($module, x, y, /, *, steps=None)\n" "--\n" "\n" -"Return the next floating-point value after x towards y."); +"Return the floating-point value the given number of steps after x towards y.\n" +"\n" +"If steps is not specified or is None, it defaults to 1.\n" +"\n" +"Raises a TypeError, if x or y is not a double, or if steps is not an integer.\n" +"Raises ValueError if steps is negative."); #define MATH_NEXTAFTER_METHODDEF \ - {"nextafter", _PyCFunction_CAST(math_nextafter), METH_FASTCALL, math_nextafter__doc__}, + {"nextafter", _PyCFunction_CAST(math_nextafter), METH_FASTCALL|METH_KEYWORDS, math_nextafter__doc__}, static PyObject * -math_nextafter_impl(PyObject *module, double x, double y); +math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps); static PyObject * -math_nextafter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +math_nextafter(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(steps), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"", "", "steps", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "nextafter", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2; double x; double y; + PyObject *steps = Py_None; - if (!_PyArg_CheckPositional("nextafter", nargs, 2, 2)) { + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { goto exit; } if (PyFloat_CheckExact(args[0])) { @@ -867,7 +901,12 @@ math_nextafter(PyObject *module, PyObject *const *args, Py_ssize_t nargs) goto exit; } } - return_value = math_nextafter_impl(module, x, y); + if (!noptargs) { + goto skip_optional_kwonly; + } + steps = args[2]; +skip_optional_kwonly: + return_value = math_nextafter_impl(module, x, y, steps); exit: return return_value; @@ -911,4 +950,4 @@ math_ulp(PyObject *module, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=a6437a3ba18c486a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=91a0357265a2a553 input=a9049054013a1b77]*/ diff --git a/Modules/hashlib.h b/Modules/hashlib.h index 56ae7a5e50bf58..a8bad9dd87a939 100644 --- a/Modules/hashlib.h +++ b/Modules/hashlib.h @@ -37,6 +37,13 @@ * LEAVE_HASHLIB block or explicitly acquire and release the lock inside * a PY_BEGIN / END_ALLOW_THREADS block if they wish to release the GIL for * an operation. + * + * These only drop the GIL if the lock acquisition itself is likely to + * block. Thus the non-blocking acquire gating the GIL release for a + * blocking lock acquisition. The intent of these macros is to surround + * the assumed always "fast" operations that you aren't releasing the + * GIL around. Otherwise use code similar to what you see in hash + * function update() methods. */ #include "pythread.h" @@ -53,7 +60,7 @@ PyThread_release_lock((obj)->lock); \ } -/* TODO(gps): We should probably make this a module or EVPobject attribute +/* TODO(gpshead): We should make this a module or class attribute * to allow the user to optimize based on the platform they're using. */ #define HASHLIB_GIL_MINSIZE 2048 diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index f369b2c45ce3ba..f26602d5871acc 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -3864,13 +3864,20 @@ math.nextafter x: double y: double / + * + steps: object = None + +Return the floating-point value the given number of steps after x towards y. + +If steps is not specified or is None, it defaults to 1. -Return the next floating-point value after x towards y. +Raises a TypeError, if x or y is not a double, or if steps is not an integer. +Raises ValueError if steps is negative. [clinic start generated code]*/ static PyObject * -math_nextafter_impl(PyObject *module, double x, double y) -/*[clinic end generated code: output=750c8266c1c540ce input=02b2d50cd1d9f9b6]*/ +math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps) +/*[clinic end generated code: output=cc6511f02afc099e input=7f2a5842112af2b4]*/ { #if defined(_AIX) if (x == y) { @@ -3885,7 +3892,101 @@ math_nextafter_impl(PyObject *module, double x, double y) return PyFloat_FromDouble(y); } #endif - return PyFloat_FromDouble(nextafter(x, y)); + if (steps == Py_None) { + // fast path: we default to one step. + return PyFloat_FromDouble(nextafter(x, y)); + } + steps = PyNumber_Index(steps); + if (steps == NULL) { + return NULL; + } + assert(PyLong_CheckExact(steps)); + if (_PyLong_IsNegative((PyLongObject *)steps)) { + PyErr_SetString(PyExc_ValueError, + "steps must be a non-negative integer"); + Py_DECREF(steps); + return NULL; + } + + unsigned long long usteps_ull = PyLong_AsUnsignedLongLong(steps); + // Conveniently, uint64_t and double have the same number of bits + // on all the platforms we care about. + // So if an overflow occurs, we can just use UINT64_MAX. + Py_DECREF(steps); + if (usteps_ull >= UINT64_MAX) { + // This branch includes the case where an error occurred, since + // (unsigned long long)(-1) = ULLONG_MAX >= UINT64_MAX. Note that + // usteps_ull can be strictly larger than UINT64_MAX on a machine + // where unsigned long long has width > 64 bits. + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_Clear(); + } + else { + return NULL; + } + } + usteps_ull = UINT64_MAX; + } + assert(usteps_ull <= UINT64_MAX); + uint64_t usteps = (uint64_t)usteps_ull; + + if (usteps == 0) { + return PyFloat_FromDouble(x); + } + if (Py_IS_NAN(x)) { + return PyFloat_FromDouble(x); + } + if (Py_IS_NAN(y)) { + return PyFloat_FromDouble(y); + } + + // We assume that double and uint64_t have the same endianness. + // This is not guaranteed by the C-standard, but it is true for + // all platforms we care about. (The most likely form of violation + // would be a "mixed-endian" double.) + union pun {double f; uint64_t i;}; + union pun ux = {x}, uy = {y}; + if (ux.i == uy.i) { + return PyFloat_FromDouble(x); + } + + const uint64_t sign_bit = 1ULL<<63; + + uint64_t ax = ux.i & ~sign_bit; + uint64_t ay = uy.i & ~sign_bit; + + // opposite signs + if (((ux.i ^ uy.i) & sign_bit)) { + // NOTE: ax + ay can never overflow, because their most significant bit + // ain't set. + if (ax + ay <= usteps) { + return PyFloat_FromDouble(uy.f); + // This comparison has to use <, because <= would get +0.0 vs -0.0 + // wrong. + } else if (ax < usteps) { + union pun result = {.i = (uy.i & sign_bit) | (usteps - ax)}; + return PyFloat_FromDouble(result.f); + } else { + ux.i -= usteps; + return PyFloat_FromDouble(ux.f); + } + // same sign + } else if (ax > ay) { + if (ax - ay >= usteps) { + ux.i -= usteps; + return PyFloat_FromDouble(ux.f); + } else { + return PyFloat_FromDouble(uy.f); + } + } else { + if (ay - ax >= usteps) { + ux.i += usteps; + return PyFloat_FromDouble(ux.f); + } else { + return PyFloat_FromDouble(uy.f); + } + } } diff --git a/Modules/md5module.c b/Modules/md5module.c index 86605771d9643f..2122f8b18baf6e 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -49,7 +49,9 @@ typedef long long MD5_INT64; /* 64-bit integer */ typedef struct { PyObject_HEAD - + // Prevents undefined behavior via multiple threads entering the C API. + // The lock will be NULL before threaded access has been enabled. + PyThread_type_lock lock; Hacl_Streaming_MD5_state *hash_state; } MD5object; @@ -72,6 +74,7 @@ static MD5object * newMD5object(MD5State * st) { MD5object *md5 = (MD5object *)PyObject_GC_New(MD5object, st->md5_type); + md5->lock = NULL; PyObject_GC_Track(md5); return md5; } @@ -88,6 +91,9 @@ static void MD5_dealloc(MD5object *ptr) { Hacl_Streaming_MD5_legacy_free(ptr->hash_state); + if (ptr->lock != NULL) { + PyThread_free_lock(ptr->lock); + } PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -115,7 +121,9 @@ MD5Type_copy_impl(MD5object *self, PyTypeObject *cls) if ((newobj = newMD5object(st))==NULL) return NULL; + ENTER_HASHLIB(self); newobj->hash_state = Hacl_Streaming_MD5_legacy_copy(self->hash_state); + LEAVE_HASHLIB(self); return (PyObject *)newobj; } @@ -130,7 +138,9 @@ MD5Type_digest_impl(MD5object *self) /*[clinic end generated code: output=eb691dc4190a07ec input=bc0c4397c2994be6]*/ { unsigned char digest[MD5_DIGESTSIZE]; + ENTER_HASHLIB(self); Hacl_Streaming_MD5_legacy_finish(self->hash_state, digest); + LEAVE_HASHLIB(self); return PyBytes_FromStringAndSize((const char *)digest, MD5_DIGESTSIZE); } @@ -145,7 +155,9 @@ MD5Type_hexdigest_impl(MD5object *self) /*[clinic end generated code: output=17badced1f3ac932 input=b60b19de644798dd]*/ { unsigned char digest[MD5_DIGESTSIZE]; + ENTER_HASHLIB(self); Hacl_Streaming_MD5_legacy_finish(self->hash_state, digest); + LEAVE_HASHLIB(self); return _Py_strhex((const char*)digest, MD5_DIGESTSIZE); } @@ -177,7 +189,18 @@ MD5Type_update(MD5object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - update(self->hash_state, buf.buf, buf.len); + if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { + self->lock = PyThread_allocate_lock(); + } + if (self->lock != NULL) { + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(self->lock, 1); + update(self->hash_state, buf.buf, buf.len); + PyThread_release_lock(self->lock); + Py_END_ALLOW_THREADS + } else { + update(self->hash_state, buf.buf, buf.len); + } PyBuffer_Release(&buf); Py_RETURN_NONE; @@ -279,7 +302,15 @@ _md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - update(new->hash_state, buf.buf, buf.len); + if (buf.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ + Py_BEGIN_ALLOW_THREADS + update(new->hash_state, buf.buf, buf.len); + Py_END_ALLOW_THREADS + } else { + update(new->hash_state, buf.buf, buf.len); + } PyBuffer_Release(&buf); } diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index a470dd3c2f3bba..6bde9939eaa2ca 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -227,6 +227,14 @@ do { \ return err; \ } \ } while (0) +#define CHECK_VALID_OR_RELEASE(err, buffer) \ +do { \ + if (self->map_handle == NULL) { \ + PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ + PyBuffer_Release(&(buffer)); \ + return (err); \ + } \ +} while (0) #endif /* MS_WINDOWS */ #ifdef UNIX @@ -237,6 +245,14 @@ do { \ return err; \ } \ } while (0) +#define CHECK_VALID_OR_RELEASE(err, buffer) \ +do { \ + if (self->data == NULL) { \ + PyErr_SetString(PyExc_ValueError, "mmap closed or invalid"); \ + PyBuffer_Release(&(buffer)); \ + return (err); \ + } \ +} while (0) #endif /* UNIX */ static PyObject * @@ -284,7 +300,8 @@ mmap_read_method(mmap_object *self, CHECK_VALID(NULL); if (!PyArg_ParseTuple(args, "|O&:read", _Py_convert_optional_to_ssize_t, &num_bytes)) - return(NULL); + return NULL; + CHECK_VALID(NULL); /* silently 'adjust' out-of-range requests */ remaining = (self->pos < self->size) ? self->size - self->pos : 0; @@ -325,6 +342,7 @@ mmap_gfind(mmap_object *self, end = self->size; Py_ssize_t res; + CHECK_VALID_OR_RELEASE(NULL, view); if (reverse) { res = _PyBytes_ReverseFind( self->data + start, end - start, @@ -388,7 +406,7 @@ mmap_write_method(mmap_object *self, CHECK_VALID(NULL); if (!PyArg_ParseTuple(args, "y*:write", &data)) - return(NULL); + return NULL; if (!is_writable(self)) { PyBuffer_Release(&data); @@ -401,6 +419,7 @@ mmap_write_method(mmap_object *self, return NULL; } + CHECK_VALID_OR_RELEASE(NULL, data); memcpy(&self->data[self->pos], data.buf, data.len); self->pos += data.len; PyBuffer_Release(&data); @@ -420,6 +439,7 @@ mmap_write_byte_method(mmap_object *self, if (!is_writable(self)) return NULL; + CHECK_VALID(NULL); if (self->pos < self->size) { self->data[self->pos++] = value; Py_RETURN_NONE; @@ -724,6 +744,7 @@ mmap_move_method(mmap_object *self, PyObject *args) if (self->size - dest < cnt || self->size - src < cnt) goto bounds; + CHECK_VALID(NULL); memmove(&self->data[dest], &self->data[src], cnt); Py_RETURN_NONE; @@ -847,6 +868,7 @@ mmap_madvise_method(mmap_object *self, PyObject *args) length = self->size - start; } + CHECK_VALID(NULL); if (madvise(self->data + start, length, option) != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; @@ -945,6 +967,7 @@ mmap_subscript(mmap_object *self, PyObject *item) "mmap index out of range"); return NULL; } + CHECK_VALID(NULL); return PyLong_FromLong(Py_CHARMASK(self->data[i])); } else if (PySlice_Check(item)) { @@ -955,6 +978,7 @@ mmap_subscript(mmap_object *self, PyObject *item) } slicelen = PySlice_AdjustIndices(self->size, &start, &stop, step); + CHECK_VALID(NULL); if (slicelen <= 0) return PyBytes_FromStringAndSize("", 0); else if (step == 1) @@ -968,6 +992,7 @@ mmap_subscript(mmap_object *self, PyObject *item) if (result_buf == NULL) return PyErr_NoMemory(); + for (cur = start, i = 0; i < slicelen; cur += step, i++) { result_buf[i] = self->data[cur]; @@ -1052,6 +1077,7 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) "in range(0, 256)"); return -1; } + CHECK_VALID(-1); self->data[i] = (char) v; return 0; } @@ -1077,6 +1103,7 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value) return -1; } + CHECK_VALID_OR_RELEASE(-1, vbuf); if (slicelen == 0) { } else if (step == 1) { diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 5022fdeb03703a..531f26ba8bc86f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -15917,6 +15917,18 @@ all_ins(PyObject *m) #ifdef PRIO_USER if (PyModule_AddIntMacro(m, PRIO_USER)) return -1; #endif +#ifdef PRIO_DARWIN_THREAD + if (PyModule_AddIntMacro(m, PRIO_DARWIN_THREAD)) return -1; +#endif +#ifdef PRIO_DARWIN_PROCESS + if (PyModule_AddIntMacro(m, PRIO_DARWIN_PROCESS)) return -1; +#endif +#ifdef PRIO_DARWIN_BG + if (PyModule_AddIntMacro(m, PRIO_DARWIN_BG)) return -1; +#endif +#ifdef PRIO_DARWIN_NONUI + if (PyModule_AddIntMacro(m, PRIO_DARWIN_NONUI)) return -1; +#endif #ifdef O_CLOEXEC if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1; #endif diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c index c0fbd4d39f0096..92f594ab63ea2a 100644 --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -1076,13 +1076,31 @@ static struct PyMethodDef xmlparse_methods[] = { Make it as simple as possible. */ +static const unsigned char template_buffer[256] = + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}; + + static int PyUnknownEncodingHandler(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info) { - static unsigned char template_buffer[256] = {0}; - PyObject* u; + PyObject *u; int i; const void *data; int kind; @@ -1090,12 +1108,7 @@ PyUnknownEncodingHandler(void *encodingHandlerData, if (PyErr_Occurred()) return XML_STATUS_ERROR; - if (template_buffer[1] == 0) { - for (i = 0; i < 256; i++) - template_buffer[i] = i; - } - - u = PyUnicode_Decode((char*) template_buffer, 256, name, "replace"); + u = PyUnicode_Decode((const char*) template_buffer, 256, name, "replace"); if (u == NULL || PyUnicode_READY(u)) { Py_XDECREF(u); return XML_STATUS_ERROR; diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 79bd5b59ab68f9..9a4943c9eb2f75 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -1849,14 +1849,11 @@ static PyObject * kqueue_event_repr(kqueue_event_Object *s) { - char buf[1024]; - PyOS_snprintf( - buf, sizeof(buf), + return PyUnicode_FromFormat( "", (size_t)(s->e.ident), (int)s->e.filter, (unsigned int)s->e.flags, (unsigned int)s->e.fflags, (long long)(s->e.data), (void *)s->e.udata); - return PyUnicode_FromString(buf); } static int diff --git a/Modules/sha1module.c b/Modules/sha1module.c index bdb76c56f1a6e8..c66269b5f5cdf3 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -48,7 +48,9 @@ typedef long long SHA1_INT64; /* 64-bit integer */ typedef struct { PyObject_HEAD - + // Prevents undefined behavior via multiple threads entering the C API. + // The lock will be NULL before threaded access has been enabled. + PyThread_type_lock lock; Hacl_Streaming_SHA1_state *hash_state; } SHA1object; @@ -71,6 +73,7 @@ static SHA1object * newSHA1object(SHA1State *st) { SHA1object *sha = (SHA1object *)PyObject_GC_New(SHA1object, st->sha1_type); + sha->lock = NULL; PyObject_GC_Track(sha); return sha; } @@ -88,6 +91,9 @@ static void SHA1_dealloc(SHA1object *ptr) { Hacl_Streaming_SHA1_legacy_free(ptr->hash_state); + if (ptr->lock != NULL) { + PyThread_free_lock(ptr->lock); + } PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -115,7 +121,9 @@ SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls) if ((newobj = newSHA1object(st)) == NULL) return NULL; + ENTER_HASHLIB(self); newobj->hash_state = Hacl_Streaming_SHA1_legacy_copy(self->hash_state); + LEAVE_HASHLIB(self); return (PyObject *)newobj; } @@ -130,7 +138,9 @@ SHA1Type_digest_impl(SHA1object *self) /*[clinic end generated code: output=2f05302a7aa2b5cb input=13824b35407444bd]*/ { unsigned char digest[SHA1_DIGESTSIZE]; + ENTER_HASHLIB(self); Hacl_Streaming_SHA1_legacy_finish(self->hash_state, digest); + LEAVE_HASHLIB(self); return PyBytes_FromStringAndSize((const char *)digest, SHA1_DIGESTSIZE); } @@ -145,7 +155,9 @@ SHA1Type_hexdigest_impl(SHA1object *self) /*[clinic end generated code: output=4161fd71e68c6659 input=97691055c0c74ab0]*/ { unsigned char digest[SHA1_DIGESTSIZE]; + ENTER_HASHLIB(self); Hacl_Streaming_SHA1_legacy_finish(self->hash_state, digest); + LEAVE_HASHLIB(self); return _Py_strhex((const char *)digest, SHA1_DIGESTSIZE); } @@ -177,7 +189,18 @@ SHA1Type_update(SHA1object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - update(self->hash_state, buf.buf, buf.len); + if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { + self->lock = PyThread_allocate_lock(); + } + if (self->lock != NULL) { + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(self->lock, 1); + update(self->hash_state, buf.buf, buf.len); + PyThread_release_lock(self->lock); + Py_END_ALLOW_THREADS + } else { + update(self->hash_state, buf.buf, buf.len); + } PyBuffer_Release(&buf); Py_RETURN_NONE; @@ -279,7 +302,15 @@ _sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - update(new->hash_state, buf.buf, buf.len); + if (buf.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ + Py_BEGIN_ALLOW_THREADS + update(new->hash_state, buf.buf, buf.len); + Py_END_ALLOW_THREADS + } else { + update(new->hash_state, buf.buf, buf.len); + } PyBuffer_Release(&buf); } diff --git a/Modules/sha2module.c b/Modules/sha2module.c index 37d9b5c538fd0b..6c7c3917198d18 100644 --- a/Modules/sha2module.c +++ b/Modules/sha2module.c @@ -52,12 +52,18 @@ class SHA512Type "SHA512object *" "&PyType_Type" typedef struct { PyObject_HEAD int digestsize; + // Prevents undefined behavior via multiple threads entering the C API. + // The lock will be NULL before threaded access has been enabled. + PyThread_type_lock lock; Hacl_Streaming_SHA2_state_sha2_256 *state; } SHA256object; typedef struct { PyObject_HEAD int digestsize; + // Prevents undefined behavior via multiple threads entering the C API. + // The lock will be NULL before threaded access has been enabled. + PyThread_type_lock lock; Hacl_Streaming_SHA2_state_sha2_512 *state; } SHA512object; @@ -100,6 +106,7 @@ newSHA224object(sha2_state *state) if (!sha) { return NULL; } + sha->lock = NULL; PyObject_GC_Track(sha); return sha; } @@ -112,6 +119,7 @@ newSHA256object(sha2_state *state) if (!sha) { return NULL; } + sha->lock = NULL; PyObject_GC_Track(sha); return sha; } @@ -124,6 +132,7 @@ newSHA384object(sha2_state *state) if (!sha) { return NULL; } + sha->lock = NULL; PyObject_GC_Track(sha); return sha; } @@ -136,6 +145,7 @@ newSHA512object(sha2_state *state) if (!sha) { return NULL; } + sha->lock = NULL; PyObject_GC_Track(sha); return sha; } @@ -153,6 +163,9 @@ static void SHA256_dealloc(SHA256object *ptr) { Hacl_Streaming_SHA2_free_256(ptr->state); + if (ptr->lock != NULL) { + PyThread_free_lock(ptr->lock); + } PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -163,6 +176,9 @@ static void SHA512_dealloc(SHA512object *ptr) { Hacl_Streaming_SHA2_free_512(ptr->state); + if (ptr->lock != NULL) { + PyThread_free_lock(ptr->lock); + } PyTypeObject *tp = Py_TYPE(ptr); PyObject_GC_UnTrack(ptr); PyObject_GC_Del(ptr); @@ -229,7 +245,9 @@ SHA256Type_copy_impl(SHA256object *self, PyTypeObject *cls) } } + ENTER_HASHLIB(self); SHA256copy(self, newobj); + LEAVE_HASHLIB(self); return (PyObject *)newobj; } @@ -259,7 +277,9 @@ SHA512Type_copy_impl(SHA512object *self, PyTypeObject *cls) } } + ENTER_HASHLIB(self); SHA512copy(self, newobj); + LEAVE_HASHLIB(self); return (PyObject *)newobj; } @@ -275,9 +295,11 @@ SHA256Type_digest_impl(SHA256object *self) { uint8_t digest[SHA256_DIGESTSIZE]; assert(self->digestsize <= SHA256_DIGESTSIZE); + ENTER_HASHLIB(self); // HACL* performs copies under the hood so that self->state remains valid // after this call. Hacl_Streaming_SHA2_finish_256(self->state, digest); + LEAVE_HASHLIB(self); return PyBytes_FromStringAndSize((const char *)digest, self->digestsize); } @@ -293,9 +315,11 @@ SHA512Type_digest_impl(SHA512object *self) { uint8_t digest[SHA512_DIGESTSIZE]; assert(self->digestsize <= SHA512_DIGESTSIZE); + ENTER_HASHLIB(self); // HACL* performs copies under the hood so that self->state remains valid // after this call. Hacl_Streaming_SHA2_finish_512(self->state, digest); + LEAVE_HASHLIB(self); return PyBytes_FromStringAndSize((const char *)digest, self->digestsize); } @@ -311,7 +335,9 @@ SHA256Type_hexdigest_impl(SHA256object *self) { uint8_t digest[SHA256_DIGESTSIZE]; assert(self->digestsize <= SHA256_DIGESTSIZE); + ENTER_HASHLIB(self); Hacl_Streaming_SHA2_finish_256(self->state, digest); + LEAVE_HASHLIB(self); return _Py_strhex((const char *)digest, self->digestsize); } @@ -327,7 +353,9 @@ SHA512Type_hexdigest_impl(SHA512object *self) { uint8_t digest[SHA512_DIGESTSIZE]; assert(self->digestsize <= SHA512_DIGESTSIZE); + ENTER_HASHLIB(self); Hacl_Streaming_SHA2_finish_512(self->state, digest); + LEAVE_HASHLIB(self); return _Py_strhex((const char *)digest, self->digestsize); } @@ -348,7 +376,18 @@ SHA256Type_update(SHA256object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - update_256(self->state, buf.buf, buf.len); + if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { + self->lock = PyThread_allocate_lock(); + } + if (self->lock != NULL) { + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(self->lock, 1); + update_256(self->state, buf.buf, buf.len); + PyThread_release_lock(self->lock); + Py_END_ALLOW_THREADS + } else { + update_256(self->state, buf.buf, buf.len); + } PyBuffer_Release(&buf); Py_RETURN_NONE; @@ -371,7 +410,18 @@ SHA512Type_update(SHA512object *self, PyObject *obj) GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - update_512(self->state, buf.buf, buf.len); + if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { + self->lock = PyThread_allocate_lock(); + } + if (self->lock != NULL) { + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(self->lock, 1); + update_512(self->state, buf.buf, buf.len); + PyThread_release_lock(self->lock); + Py_END_ALLOW_THREADS + } else { + update_512(self->state, buf.buf, buf.len); + } PyBuffer_Release(&buf); Py_RETURN_NONE; @@ -560,7 +610,15 @@ _sha2_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - update_256(new->state, buf.buf, buf.len); + if (buf.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ + Py_BEGIN_ALLOW_THREADS + update_256(new->state, buf.buf, buf.len); + Py_END_ALLOW_THREADS + } else { + update_256(new->state, buf.buf, buf.len); + } PyBuffer_Release(&buf); } @@ -606,7 +664,15 @@ _sha2_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - update_256(new->state, buf.buf, buf.len); + if (buf.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ + Py_BEGIN_ALLOW_THREADS + update_256(new->state, buf.buf, buf.len); + Py_END_ALLOW_THREADS + } else { + update_256(new->state, buf.buf, buf.len); + } PyBuffer_Release(&buf); } @@ -651,7 +717,15 @@ _sha2_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - update_512(new->state, buf.buf, buf.len); + if (buf.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ + Py_BEGIN_ALLOW_THREADS + update_512(new->state, buf.buf, buf.len); + Py_END_ALLOW_THREADS + } else { + update_512(new->state, buf.buf, buf.len); + } PyBuffer_Release(&buf); } @@ -696,7 +770,15 @@ _sha2_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity) return NULL; } if (string) { - update_512(new->state, buf.buf, buf.len); + if (buf.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ + Py_BEGIN_ALLOW_THREADS + update_512(new->state, buf.buf, buf.len); + Py_END_ALLOW_THREADS + } else { + update_512(new->state, buf.buf, buf.len); + } PyBuffer_Release(&buf); } diff --git a/Modules/sha3module.c b/Modules/sha3module.c index f05187498a19b3..558d2005cff617 100644 --- a/Modules/sha3module.c +++ b/Modules/sha3module.c @@ -60,6 +60,9 @@ class _sha3.shake_256 "SHA3object *" "&SHAKE256type" typedef struct { PyObject_HEAD + // Prevents undefined behavior via multiple threads entering the C API. + // The lock will be NULL before threaded access has been enabled. + PyThread_type_lock lock; Hacl_Streaming_Keccak_state *hash_state; } SHA3object; @@ -73,6 +76,7 @@ newSHA3object(PyTypeObject *type) if (newobj == NULL) { return NULL; } + newobj->lock = NULL; return newobj; } @@ -133,7 +137,15 @@ py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity) if (data) { GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error); - sha3_update(self->hash_state, buf.buf, buf.len); + if (buf.len >= HASHLIB_GIL_MINSIZE) { + /* We do not initialize self->lock here as this is the constructor + * where it is not yet possible to have concurrent access. */ + Py_BEGIN_ALLOW_THREADS + sha3_update(self->hash_state, buf.buf, buf.len); + Py_END_ALLOW_THREADS + } else { + sha3_update(self->hash_state, buf.buf, buf.len); + } } PyBuffer_Release(&buf); @@ -157,6 +169,9 @@ static void SHA3_dealloc(SHA3object *self) { Hacl_Streaming_Keccak_free(self->hash_state); + if (self->lock != NULL) { + PyThread_free_lock(self->lock); + } PyTypeObject *tp = Py_TYPE(self); PyObject_Free(self); Py_DECREF(tp); @@ -181,7 +196,9 @@ _sha3_sha3_224_copy_impl(SHA3object *self) if ((newobj = newSHA3object(Py_TYPE(self))) == NULL) { return NULL; } + ENTER_HASHLIB(self); newobj->hash_state = Hacl_Streaming_Keccak_copy(self->hash_state); + LEAVE_HASHLIB(self); return (PyObject *)newobj; } @@ -199,7 +216,9 @@ _sha3_sha3_224_digest_impl(SHA3object *self) unsigned char digest[SHA3_MAX_DIGESTSIZE]; // This function errors out if the algorithm is Shake. Here, we know this // not to be the case, and therefore do not perform error checking. + ENTER_HASHLIB(self); Hacl_Streaming_Keccak_finish(self->hash_state, digest); + LEAVE_HASHLIB(self); return PyBytes_FromStringAndSize((const char *)digest, Hacl_Streaming_Keccak_hash_len(self->hash_state)); } @@ -216,7 +235,9 @@ _sha3_sha3_224_hexdigest_impl(SHA3object *self) /*[clinic end generated code: output=75ad03257906918d input=2d91bb6e0d114ee3]*/ { unsigned char digest[SHA3_MAX_DIGESTSIZE]; + ENTER_HASHLIB(self); Hacl_Streaming_Keccak_finish(self->hash_state, digest); + LEAVE_HASHLIB(self); return _Py_strhex((const char *)digest, Hacl_Streaming_Keccak_hash_len(self->hash_state)); } @@ -237,7 +258,18 @@ _sha3_sha3_224_update(SHA3object *self, PyObject *data) { Py_buffer buf; GET_BUFFER_VIEW_OR_ERROUT(data, &buf); - sha3_update(self->hash_state, buf.buf, buf.len); + if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) { + self->lock = PyThread_allocate_lock(); + } + if (self->lock != NULL) { + Py_BEGIN_ALLOW_THREADS + PyThread_acquire_lock(self->lock, 1); + sha3_update(self->hash_state, buf.buf, buf.len); + PyThread_release_lock(self->lock); + Py_END_ALLOW_THREADS + } else { + sha3_update(self->hash_state, buf.buf, buf.len); + } PyBuffer_Release(&buf); Py_RETURN_NONE; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index c11fb4400eab2f..a86aaed501fa33 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1339,8 +1339,6 @@ setbdaddr(const char *name, bdaddr_t *bdaddr) static PyObject * makebdaddr(bdaddr_t *bdaddr) { - char buf[(6 * 2) + 5 + 1]; - #ifdef MS_WINDOWS int i; unsigned int octets[6]; @@ -1349,16 +1347,14 @@ makebdaddr(bdaddr_t *bdaddr) octets[i] = ((*bdaddr) >> (8 * i)) & 0xFF; } - sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", + return PyUnicode_FromFormat("%02X:%02X:%02X:%02X:%02X:%02X", octets[5], octets[4], octets[3], octets[2], octets[1], octets[0]); #else - sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", + return PyUnicode_FromFormat("%02X:%02X:%02X:%02X:%02X:%02X", bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); #endif - - return PyUnicode_FromString(buf); } #endif diff --git a/Objects/boolobject.c b/Objects/boolobject.c index 0300f7bb4e3dc0..f43e26f3f24e77 100644 --- a/Objects/boolobject.c +++ b/Objects/boolobject.c @@ -20,13 +20,7 @@ bool_repr(PyObject *self) PyObject *PyBool_FromLong(long ok) { - PyObject *result; - - if (ok) - result = Py_True; - else - result = Py_False; - return Py_NewRef(result); + return ok ? Py_True : Py_False; } /* We define bool_new to always return either Py_True or Py_False */ diff --git a/Objects/clinic/typevarobject.c.h b/Objects/clinic/typevarobject.c.h new file mode 100644 index 00000000000000..54189b98446814 --- /dev/null +++ b/Objects/clinic/typevarobject.c.h @@ -0,0 +1,786 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) +# include "pycore_gc.h" // PyGC_Head +# include "pycore_runtime.h" // _Py_ID() +#endif + + +PyDoc_STRVAR(typevar_new__doc__, +"typevar(name, *constraints, *, bound=None, covariant=False,\n" +" contravariant=False, infer_variance=False)\n" +"--\n" +"\n" +"Create a TypeVar."); + +static PyObject * +typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints, + PyObject *bound, int covariant, int contravariant, + int infer_variance); + +static PyObject * +typevar_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "typevar", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[6]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = Py_MIN(nargs, 1) + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1; + PyObject *name; + PyObject *constraints = NULL; + PyObject *bound = Py_None; + int covariant = 0; + int contravariant = 0; + int infer_variance = 0; + + fastargs = _PyArg_UnpackKeywordsWithVararg(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, 1, argsbuf); + if (!fastargs) { + goto exit; + } + if (!PyUnicode_Check(fastargs[0])) { + _PyArg_BadArgument("typevar", "argument 'name'", "str", fastargs[0]); + goto exit; + } + name = fastargs[0]; + constraints = fastargs[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (fastargs[2]) { + bound = fastargs[2]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[3]) { + covariant = PyObject_IsTrue(fastargs[3]); + if (covariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[4]) { + contravariant = PyObject_IsTrue(fastargs[4]); + if (contravariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + infer_variance = PyObject_IsTrue(fastargs[5]); + if (infer_variance < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = typevar_new_impl(type, name, constraints, bound, covariant, contravariant, infer_variance); + +exit: + Py_XDECREF(constraints); + return return_value; +} + +PyDoc_STRVAR(typevar_typing_subst__doc__, +"__typing_subst__($self, /, arg)\n" +"--\n" +"\n"); + +#define TYPEVAR_TYPING_SUBST_METHODDEF \ + {"__typing_subst__", _PyCFunction_CAST(typevar_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevar_typing_subst__doc__}, + +static PyObject * +typevar_typing_subst_impl(typevarobject *self, PyObject *arg); + +static PyObject * +typevar_typing_subst(typevarobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(arg), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"arg", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "__typing_subst__", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *arg; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + arg = args[0]; + return_value = typevar_typing_subst_impl(self, arg); + +exit: + return return_value; +} + +PyDoc_STRVAR(typevar_reduce__doc__, +"__reduce__($self, /)\n" +"--\n" +"\n"); + +#define TYPEVAR_REDUCE_METHODDEF \ + {"__reduce__", (PyCFunction)typevar_reduce, METH_NOARGS, typevar_reduce__doc__}, + +static PyObject * +typevar_reduce_impl(typevarobject *self); + +static PyObject * +typevar_reduce(typevarobject *self, PyObject *Py_UNUSED(ignored)) +{ + return typevar_reduce_impl(self); +} + +PyDoc_STRVAR(paramspecargs_new__doc__, +"paramspecargs(origin)\n" +"--\n" +"\n" +"Create a ParamSpecArgs object."); + +static PyObject * +paramspecargs_new_impl(PyTypeObject *type, PyObject *origin); + +static PyObject * +paramspecargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(origin), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"origin", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "paramspecargs", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *origin; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + origin = fastargs[0]; + return_value = paramspecargs_new_impl(type, origin); + +exit: + return return_value; +} + +PyDoc_STRVAR(paramspeckwargs_new__doc__, +"paramspeckwargs(origin)\n" +"--\n" +"\n" +"Create a ParamSpecKwargs object."); + +static PyObject * +paramspeckwargs_new_impl(PyTypeObject *type, PyObject *origin); + +static PyObject * +paramspeckwargs_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(origin), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"origin", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "paramspeckwargs", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *origin; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + origin = fastargs[0]; + return_value = paramspeckwargs_new_impl(type, origin); + +exit: + return return_value; +} + +PyDoc_STRVAR(paramspec_new__doc__, +"paramspec(name, *, bound=None, covariant=False, contravariant=False,\n" +" infer_variance=False)\n" +"--\n" +"\n" +"Create a ParamSpec object."); + +static PyObject * +paramspec_new_impl(PyTypeObject *type, PyObject *name, PyObject *bound, + int covariant, int contravariant, int infer_variance); + +static PyObject * +paramspec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 5 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(name), &_Py_ID(bound), &_Py_ID(covariant), &_Py_ID(contravariant), &_Py_ID(infer_variance), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", "bound", "covariant", "contravariant", "infer_variance", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "paramspec", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[5]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1; + PyObject *name; + PyObject *bound = Py_None; + int covariant = 0; + int contravariant = 0; + int infer_variance = 0; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!PyUnicode_Check(fastargs[0])) { + _PyArg_BadArgument("paramspec", "argument 'name'", "str", fastargs[0]); + goto exit; + } + name = fastargs[0]; + if (!noptargs) { + goto skip_optional_kwonly; + } + if (fastargs[1]) { + bound = fastargs[1]; + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[2]) { + covariant = PyObject_IsTrue(fastargs[2]); + if (covariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + if (fastargs[3]) { + contravariant = PyObject_IsTrue(fastargs[3]); + if (contravariant < 0) { + goto exit; + } + if (!--noptargs) { + goto skip_optional_kwonly; + } + } + infer_variance = PyObject_IsTrue(fastargs[4]); + if (infer_variance < 0) { + goto exit; + } +skip_optional_kwonly: + return_value = paramspec_new_impl(type, name, bound, covariant, contravariant, infer_variance); + +exit: + return return_value; +} + +PyDoc_STRVAR(paramspec_typing_subst__doc__, +"__typing_subst__($self, /, arg)\n" +"--\n" +"\n"); + +#define PARAMSPEC_TYPING_SUBST_METHODDEF \ + {"__typing_subst__", _PyCFunction_CAST(paramspec_typing_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_subst__doc__}, + +static PyObject * +paramspec_typing_subst_impl(paramspecobject *self, PyObject *arg); + +static PyObject * +paramspec_typing_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(arg), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"arg", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "__typing_subst__", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *arg; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + arg = args[0]; + return_value = paramspec_typing_subst_impl(self, arg); + +exit: + return return_value; +} + +PyDoc_STRVAR(paramspec_typing_prepare_subst__doc__, +"__typing_prepare_subst__($self, /, alias, args)\n" +"--\n" +"\n"); + +#define PARAMSPEC_TYPING_PREPARE_SUBST_METHODDEF \ + {"__typing_prepare_subst__", _PyCFunction_CAST(paramspec_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, paramspec_typing_prepare_subst__doc__}, + +static PyObject * +paramspec_typing_prepare_subst_impl(paramspecobject *self, PyObject *alias, + PyObject *args); + +static PyObject * +paramspec_typing_prepare_subst(paramspecobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(alias), &_Py_ID(args), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"alias", "args", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "__typing_prepare_subst__", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *alias; + PyObject *__clinic_args; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + alias = args[0]; + __clinic_args = args[1]; + return_value = paramspec_typing_prepare_subst_impl(self, alias, __clinic_args); + +exit: + return return_value; +} + +PyDoc_STRVAR(paramspec_reduce__doc__, +"__reduce__($self, /)\n" +"--\n" +"\n"); + +#define PARAMSPEC_REDUCE_METHODDEF \ + {"__reduce__", (PyCFunction)paramspec_reduce, METH_NOARGS, paramspec_reduce__doc__}, + +static PyObject * +paramspec_reduce_impl(paramspecobject *self); + +static PyObject * +paramspec_reduce(paramspecobject *self, PyObject *Py_UNUSED(ignored)) +{ + return paramspec_reduce_impl(self); +} + +PyDoc_STRVAR(typevartuple__doc__, +"typevartuple(name)\n" +"--\n" +"\n" +"Create a new TypeVarTuple with the given name."); + +static PyObject * +typevartuple_impl(PyTypeObject *type, PyObject *name); + +static PyObject * +typevartuple(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(name), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "typevartuple", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + PyObject *name; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!PyUnicode_Check(fastargs[0])) { + _PyArg_BadArgument("typevartuple", "argument 'name'", "str", fastargs[0]); + goto exit; + } + name = fastargs[0]; + return_value = typevartuple_impl(type, name); + +exit: + return return_value; +} + +PyDoc_STRVAR(typevartuple_typing_subst__doc__, +"__typing_subst__($self, /, arg)\n" +"--\n" +"\n"); + +#define TYPEVARTUPLE_TYPING_SUBST_METHODDEF \ + {"__typing_subst__", _PyCFunction_CAST(typevartuple_typing_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_subst__doc__}, + +static PyObject * +typevartuple_typing_subst_impl(typevartupleobject *self, PyObject *arg); + +static PyObject * +typevartuple_typing_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 1 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(arg), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"arg", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "__typing_subst__", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[1]; + PyObject *arg; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf); + if (!args) { + goto exit; + } + arg = args[0]; + return_value = typevartuple_typing_subst_impl(self, arg); + +exit: + return return_value; +} + +PyDoc_STRVAR(typevartuple_typing_prepare_subst__doc__, +"__typing_prepare_subst__($self, /, alias, args)\n" +"--\n" +"\n"); + +#define TYPEVARTUPLE_TYPING_PREPARE_SUBST_METHODDEF \ + {"__typing_prepare_subst__", _PyCFunction_CAST(typevartuple_typing_prepare_subst), METH_FASTCALL|METH_KEYWORDS, typevartuple_typing_prepare_subst__doc__}, + +static PyObject * +typevartuple_typing_prepare_subst_impl(typevartupleobject *self, + PyObject *alias, PyObject *args); + +static PyObject * +typevartuple_typing_prepare_subst(typevartupleobject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 2 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(alias), &_Py_ID(args), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"alias", "args", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "__typing_prepare_subst__", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[2]; + PyObject *alias; + PyObject *__clinic_args; + + args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf); + if (!args) { + goto exit; + } + alias = args[0]; + __clinic_args = args[1]; + return_value = typevartuple_typing_prepare_subst_impl(self, alias, __clinic_args); + +exit: + return return_value; +} + +PyDoc_STRVAR(typevartuple_reduce__doc__, +"__reduce__($self, /)\n" +"--\n" +"\n"); + +#define TYPEVARTUPLE_REDUCE_METHODDEF \ + {"__reduce__", (PyCFunction)typevartuple_reduce, METH_NOARGS, typevartuple_reduce__doc__}, + +static PyObject * +typevartuple_reduce_impl(typevartupleobject *self); + +static PyObject * +typevartuple_reduce(typevartupleobject *self, PyObject *Py_UNUSED(ignored)) +{ + return typevartuple_reduce_impl(self); +} + +PyDoc_STRVAR(typealias_reduce__doc__, +"__reduce__($self, /)\n" +"--\n" +"\n"); + +#define TYPEALIAS_REDUCE_METHODDEF \ + {"__reduce__", (PyCFunction)typealias_reduce, METH_NOARGS, typealias_reduce__doc__}, + +static PyObject * +typealias_reduce_impl(typealiasobject *self); + +static PyObject * +typealias_reduce(typealiasobject *self, PyObject *Py_UNUSED(ignored)) +{ + return typealias_reduce_impl(self); +} + +PyDoc_STRVAR(typealias_new__doc__, +"typealias(name, value, *, type_params=)\n" +"--\n" +"\n" +"Create a TypeAliasType."); + +static PyObject * +typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value, + PyObject *type_params); + +static PyObject * +typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) + + #define NUM_KEYWORDS 3 + static struct { + PyGC_Head _this_is_not_used; + PyObject_VAR_HEAD + PyObject *ob_item[NUM_KEYWORDS]; + } _kwtuple = { + .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) + .ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), }, + }; + #undef NUM_KEYWORDS + #define KWTUPLE (&_kwtuple.ob_base.ob_base) + + #else // !Py_BUILD_CORE + # define KWTUPLE NULL + #endif // !Py_BUILD_CORE + + static const char * const _keywords[] = {"name", "value", "type_params", NULL}; + static _PyArg_Parser _parser = { + .keywords = _keywords, + .fname = "typealias", + .kwtuple = KWTUPLE, + }; + #undef KWTUPLE + PyObject *argsbuf[3]; + PyObject * const *fastargs; + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 2; + PyObject *name; + PyObject *value; + PyObject *type_params = NULL; + + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 2, 2, 0, argsbuf); + if (!fastargs) { + goto exit; + } + if (!PyUnicode_Check(fastargs[0])) { + _PyArg_BadArgument("typealias", "argument 'name'", "str", fastargs[0]); + goto exit; + } + name = fastargs[0]; + value = fastargs[1]; + if (!noptargs) { + goto skip_optional_kwonly; + } + type_params = fastargs[2]; +skip_optional_kwonly: + return_value = typealias_new_impl(type, name, value, type_params); + +exit: + return return_value; +} +/*[clinic end generated code: output=807bcd30ebd10ac3 input=a9049054013a1b77]*/ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 7436c113f37c4a..254cd9ad2f9bda 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -944,6 +944,7 @@ unicodekeys_lookup_unicode(PyDictKeysObject* dk, PyObject *key, Py_hash_t hash) } perturb >>= PERTURB_SHIFT; i = mask & (i*5 + perturb + 1); + // Manual loop unrolling ix = dictkeys_get_index(dk, i); if (ix >= 0) { PyDictUnicodeEntry *ep = &ep0[ix]; diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 78c1144afca2eb..753038600aa858 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -127,6 +127,7 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr) PyErr_Clear(); } op->func_annotations = NULL; + op->func_typeparams = NULL; op->vectorcall = _PyFunction_Vectorcall; op->func_version = 0; _PyObject_GC_TRACK(op); @@ -202,6 +203,7 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname op->func_weakreflist = NULL; op->func_module = module; op->func_annotations = NULL; + op->func_typeparams = NULL; op->vectorcall = _PyFunction_Vectorcall; op->func_version = 0; _PyObject_GC_TRACK(op); @@ -652,6 +654,42 @@ func_set_annotations(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(igno return 0; } +static PyObject * +func_get_type_params(PyFunctionObject *op, void *Py_UNUSED(ignored)) +{ + if (op->func_typeparams == NULL) { + return PyTuple_New(0); + } + + assert(PyTuple_Check(op->func_typeparams)); + return Py_NewRef(op->func_typeparams); +} + +static int +func_set_type_params(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +{ + /* Not legal to del f.__type_params__ or to set it to anything + * other than a tuple object. */ + if (value == NULL || !PyTuple_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "__type_params__ must be set to a tuple"); + return -1; + } + Py_XSETREF(op->func_typeparams, Py_NewRef(value)); + return 0; +} + +PyObject * +_Py_set_function_type_params(PyThreadState *Py_UNUSED(ignored), PyObject *func, + PyObject *type_params) +{ + assert(PyFunction_Check(func)); + assert(PyTuple_Check(type_params)); + PyFunctionObject *f = (PyFunctionObject *)func; + Py_XSETREF(f->func_typeparams, Py_NewRef(type_params)); + return Py_NewRef(func); +} + static PyGetSetDef func_getsetlist[] = { {"__code__", (getter)func_get_code, (setter)func_set_code}, {"__defaults__", (getter)func_get_defaults, @@ -663,6 +701,8 @@ static PyGetSetDef func_getsetlist[] = { {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, {"__name__", (getter)func_get_name, (setter)func_set_name}, {"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname}, + {"__type_params__", (getter)func_get_type_params, + (setter)func_set_type_params}, {NULL} /* Sentinel */ }; @@ -783,6 +823,7 @@ func_clear(PyFunctionObject *op) Py_CLEAR(op->func_dict); Py_CLEAR(op->func_closure); Py_CLEAR(op->func_annotations); + Py_CLEAR(op->func_typeparams); // Don't Py_CLEAR(op->func_code), since code is always required // to be non-NULL. Similarly, name and qualname shouldn't be NULL. // However, name and qualname could be str subclasses, so they @@ -837,6 +878,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg) Py_VISIT(f->func_dict); Py_VISIT(f->func_closure); Py_VISIT(f->func_annotations); + Py_VISIT(f->func_typeparams); Py_VISIT(f->func_qualname); return 0; } diff --git a/Objects/longobject.c b/Objects/longobject.c index 853e934e2107ea..5fca55e5c3a2be 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -6366,3 +6366,17 @@ _PyLong_FiniTypes(PyInterpreterState *interp) { _PyStructSequence_FiniBuiltin(interp, &Int_InfoType); } + +#undef PyUnstable_Long_IsCompact + +int +PyUnstable_Long_IsCompact(const PyLongObject* op) { + return _PyLong_IsCompact(op); +} + +#undef PyUnstable_Long_CompactValue + +Py_ssize_t +PyUnstable_Long_CompactValue(const PyLongObject* op) { + return _PyLong_CompactValue(op); +} diff --git a/Objects/object.c b/Objects/object.c index a7c79c673d5fd3..ece0c5e21e77fa 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -14,6 +14,7 @@ #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // PySTEntry_Type +#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic #include "pycore_typeobject.h" // _PyBufferWrapper_Type #include "pycore_unionobject.h" // _PyUnion_Type #include "pycore_interpreteridobject.h" // _PyInterpreterID_Type @@ -2111,6 +2112,7 @@ static PyTypeObject* static_types[] = { &_PyWeakref_CallableProxyType, &_PyWeakref_ProxyType, &_PyWeakref_RefType, + &_PyTypeAlias_Type, // subclasses: _PyTypes_FiniTypes() deallocates them before their base // class @@ -2139,6 +2141,11 @@ _PyTypes_InitTypes(PyInterpreterState *interp) } } + // Must be after static types are initialized + if (_Py_initialize_generic(interp) < 0) { + return _PyStatus_ERR("Can't initialize generic types"); + } + return _PyStatus_OK(); } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c1525320a7cbd5..2fbcafe91aadc6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1490,6 +1490,34 @@ type_set_annotations(PyTypeObject *type, PyObject *value, void *context) return result; } +static PyObject * +type_get_type_params(PyTypeObject *type, void *context) +{ + PyObject *params = PyDict_GetItem(lookup_tp_dict(type), &_Py_ID(__type_params__)); + + if (params) { + return Py_NewRef(params); + } + + return PyTuple_New(0); +} + +static int +type_set_type_params(PyTypeObject *type, PyObject *value, void *context) +{ + if (!check_set_special_type_attr(type, value, "__type_params__")) { + return -1; + } + + PyObject *dict = lookup_tp_dict(type); + int result = PyDict_SetItem(dict, &_Py_ID(__type_params__), value); + + if (result == 0) { + PyType_Modified(type); + } + return result; +} + /*[clinic input] type.__instancecheck__ -> bool @@ -1536,6 +1564,7 @@ static PyGetSetDef type_getsets[] = { {"__doc__", (getter)type_get_doc, (setter)type_set_doc, NULL}, {"__text_signature__", (getter)type_get_text_signature, NULL, NULL}, {"__annotations__", (getter)type_get_annotations, (setter)type_set_annotations, NULL}, + {"__type_params__", (getter)type_get_type_params, (setter)type_set_type_params, NULL}, {0} }; @@ -3130,11 +3159,12 @@ type_new_copy_slots(type_new_ctx *ctx, PyObject *dict) goto error; } if (r > 0) { - /* CPython inserts __qualname__ and __classcell__ (when needed) + /* CPython inserts these names (when needed) into the namespace when creating a class. They will be deleted below so won't act as class variables. */ if (!_PyUnicode_Equal(slot, &_Py_ID(__qualname__)) && - !_PyUnicode_Equal(slot, &_Py_ID(__classcell__))) + !_PyUnicode_Equal(slot, &_Py_ID(__classcell__)) && + !_PyUnicode_Equal(slot, &_Py_ID(__classdictcell__))) { PyErr_Format(PyExc_ValueError, "%R in __slots__ conflicts with class variable", @@ -3585,6 +3615,32 @@ type_new_set_classcell(PyTypeObject *type) return 0; } +static int +type_new_set_classdictcell(PyTypeObject *type) +{ + PyObject *dict = lookup_tp_dict(type); + PyObject *cell = PyDict_GetItemWithError(dict, &_Py_ID(__classdictcell__)); + if (cell == NULL) { + if (PyErr_Occurred()) { + return -1; + } + return 0; + } + + /* At least one method requires a reference to the dict of its defining class */ + if (!PyCell_Check(cell)) { + PyErr_Format(PyExc_TypeError, + "__classdictcell__ must be a nonlocal cell, not %.200R", + Py_TYPE(cell)); + return -1; + } + + (void)PyCell_Set(cell, (PyObject *)dict); + if (PyDict_DelItem(dict, &_Py_ID(__classdictcell__)) < 0) { + return -1; + } + return 0; +} static int type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type) @@ -3629,6 +3685,9 @@ type_new_set_attrs(const type_new_ctx *ctx, PyTypeObject *type) if (type_new_set_classcell(type) < 0) { return -1; } + if (type_new_set_classdictcell(type) < 0) { + return -1; + } return 0; } diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c new file mode 100644 index 00000000000000..6730ebfc064e35 --- /dev/null +++ b/Objects/typevarobject.c @@ -0,0 +1,1649 @@ +// TypeVar, TypeVarTuple, and ParamSpec +#include "Python.h" +#include "pycore_object.h" // _PyObject_GC_TRACK/UNTRACK +#include "pycore_typevarobject.h" +#include "pycore_unionobject.h" // _Py_union_type_or +#include "structmember.h" + +/*[clinic input] +class typevar "typevarobject *" "&_PyTypeVar_Type" +class paramspec "paramspecobject *" "&_PyParamSpec_Type" +class paramspecargs "paramspecattrobject *" "&_PyParamSpecArgs_Type" +class paramspeckwargs "paramspecattrobject *" "&_PyParamSpecKwargs_Type" +class typevartuple "typevartupleobject *" "&_PyTypeVarTuple_Type" +class typealias "typealiasobject *" "&_PyTypeAlias_Type" +class Generic "PyObject *" "&PyGeneric_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=aa86741931a0f55c]*/ + +typedef struct { + PyObject_HEAD + PyObject *name; + PyObject *bound; + PyObject *evaluate_bound; + PyObject *constraints; + PyObject *evaluate_constraints; + bool covariant; + bool contravariant; + bool infer_variance; +} typevarobject; + +typedef struct { + PyObject_HEAD + PyObject *name; +} typevartupleobject; + +typedef struct { + PyObject_HEAD + PyObject *name; + PyObject *bound; + bool covariant; + bool contravariant; + bool infer_variance; +} paramspecobject; + +typedef struct { + PyObject_HEAD + PyObject *name; + PyObject *type_params; + PyObject *compute_value; + PyObject *value; + PyObject *module; +} typealiasobject; + +#include "clinic/typevarobject.c.h" + +static PyObject * +call_typing_func_object(const char *name, PyObject **args, size_t nargs) +{ + PyObject *typing = PyImport_ImportModule("typing"); + if (typing == NULL) { + return NULL; + } + PyObject *func = PyObject_GetAttrString(typing, name); + if (func == NULL) { + Py_DECREF(typing); + return NULL; + } + PyObject *result = PyObject_Vectorcall(func, args, nargs, NULL); + Py_DECREF(func); + Py_DECREF(typing); + return result; +} + +static PyObject * +type_check(PyObject *arg, const char *msg) +{ + // Calling typing.py here leads to bootstrapping problems + if (Py_IsNone(arg)) { + return Py_NewRef(Py_TYPE(arg)); + } + PyObject *message_str = PyUnicode_FromString(msg); + if (message_str == NULL) { + return NULL; + } + PyObject *args[2] = {arg, message_str}; + PyObject *result = call_typing_func_object("_type_check", args, 2); + Py_DECREF(message_str); + return result; +} + +/* + * Return a typing.Union. This is used as the nb_or (|) operator for + * TypeVar and ParamSpec. We use this rather than _Py_union_type_or + * (which would produce a types.Union) because historically TypeVar + * supported unions with string forward references, and we want to + * preserve that behavior. _Py_union_type_or only allows a small set + * of types. + */ +static PyObject * +make_union(PyObject *self, PyObject *other) +{ + PyObject *args[2] = {self, other}; + PyObject *result = call_typing_func_object("_make_union", args, 2); + return result; +} + +static PyObject * +caller(void) +{ + _PyInterpreterFrame *f = _PyThreadState_GET()->cframe->current_frame; + if (f == NULL) { + Py_RETURN_NONE; + } + if (f == NULL || f->f_funcobj == NULL) { + Py_RETURN_NONE; + } + PyObject *r = PyFunction_GetModule(f->f_funcobj); + if (!r) { + PyErr_Clear(); + Py_RETURN_NONE; + } + return Py_NewRef(r); +} + +static PyObject * +typevartuple_unpack(PyObject *tvt) +{ + PyObject *typing = PyImport_ImportModule("typing"); + if (typing == NULL) { + return NULL; + } + PyObject *unpack = PyObject_GetAttrString(typing, "Unpack"); + if (unpack == NULL) { + Py_DECREF(typing); + return NULL; + } + PyObject *unpacked = PyObject_GetItem(unpack, tvt); + Py_DECREF(typing); + Py_DECREF(unpack); + return unpacked; +} + +static int +contains_typevartuple(PyTupleObject *params) +{ + Py_ssize_t n = PyTuple_GET_SIZE(params); + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevartuple_type; + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *param = PyTuple_GET_ITEM(params, i); + if (Py_IS_TYPE(param, tp)) { + return 1; + } + } + return 0; +} + +static PyObject * +unpack_typevartuples(PyObject *params) +{ + assert(PyTuple_Check(params)); + // TypeVarTuple must be unpacked when passed to Generic, so we do that here. + if (contains_typevartuple((PyTupleObject *)params)) { + Py_ssize_t n = PyTuple_GET_SIZE(params); + PyObject *new_params = PyTuple_New(n); + if (new_params == NULL) { + return NULL; + } + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevartuple_type; + for (Py_ssize_t i = 0; i < n; i++) { + PyObject *param = PyTuple_GET_ITEM(params, i); + if (Py_IS_TYPE(param, tp)) { + PyObject *unpacked = typevartuple_unpack(param); + if (unpacked == NULL) { + Py_DECREF(new_params); + return NULL; + } + PyTuple_SET_ITEM(new_params, i, unpacked); + } + else { + PyTuple_SET_ITEM(new_params, i, Py_NewRef(param)); + } + } + return new_params; + } + else { + return Py_NewRef(params); + } +} + +static void +typevar_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + typevarobject *tv = (typevarobject *)self; + + _PyObject_GC_UNTRACK(self); + + Py_DECREF(tv->name); + Py_XDECREF(tv->bound); + Py_XDECREF(tv->evaluate_bound); + Py_XDECREF(tv->constraints); + Py_XDECREF(tv->evaluate_constraints); + _PyObject_ClearManagedDict(self); + + Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); +} + +static int +typevar_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + typevarobject *tv = (typevarobject *)self; + Py_VISIT(tv->bound); + Py_VISIT(tv->evaluate_bound); + Py_VISIT(tv->constraints); + Py_VISIT(tv->evaluate_constraints); + _PyObject_VisitManagedDict(self, visit, arg); + return 0; +} + +static int +typevar_clear(typevarobject *self) +{ + Py_CLEAR(self->bound); + Py_CLEAR(self->evaluate_bound); + Py_CLEAR(self->constraints); + Py_CLEAR(self->evaluate_constraints); + _PyObject_ClearManagedDict((PyObject *)self); + return 0; +} + +static PyObject * +typevar_repr(PyObject *self) +{ + typevarobject *tv = (typevarobject *)self; + + if (tv->infer_variance) { + return Py_NewRef(tv->name); + } + + char variance = tv->covariant ? '+' : tv->contravariant ? '-' : '~'; + return PyUnicode_FromFormat("%c%U", variance, tv->name); +} + +static PyMemberDef typevar_members[] = { + {"__name__", T_OBJECT, offsetof(typevarobject, name), READONLY}, + {"__covariant__", T_BOOL, offsetof(typevarobject, covariant), READONLY}, + {"__contravariant__", T_BOOL, offsetof(typevarobject, contravariant), READONLY}, + {"__infer_variance__", T_BOOL, offsetof(typevarobject, infer_variance), READONLY}, + {0} +}; + +static PyObject * +typevar_bound(typevarobject *self, void *Py_UNUSED(ignored)) +{ + if (self->bound != NULL) { + return Py_NewRef(self->bound); + } + if (self->evaluate_bound == NULL) { + Py_RETURN_NONE; + } + PyObject *bound = PyObject_CallNoArgs(self->evaluate_bound); + self->bound = Py_XNewRef(bound); + return bound; +} + +static PyObject * +typevar_constraints(typevarobject *self, void *Py_UNUSED(ignored)) +{ + if (self->constraints != NULL) { + return Py_NewRef(self->constraints); + } + if (self->evaluate_constraints == NULL) { + return PyTuple_New(0); + } + PyObject *constraints = PyObject_CallNoArgs(self->evaluate_constraints); + self->constraints = Py_XNewRef(constraints); + return constraints; +} + +static PyGetSetDef typevar_getset[] = { + {"__bound__", (getter)typevar_bound, NULL, NULL, NULL}, + {"__constraints__", (getter)typevar_constraints, NULL, NULL, NULL}, + {0} +}; + +static typevarobject * +typevar_alloc(PyObject *name, PyObject *bound, PyObject *evaluate_bound, + PyObject *constraints, PyObject *evaluate_constraints, + bool covariant, bool contravariant, bool infer_variance, + PyObject *module) +{ + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevar_type; + assert(tp != NULL); + typevarobject *tv = PyObject_GC_New(typevarobject, tp); + if (tv == NULL) { + return NULL; + } + + tv->name = Py_NewRef(name); + + tv->bound = Py_XNewRef(bound); + tv->evaluate_bound = Py_XNewRef(evaluate_bound); + tv->constraints = Py_XNewRef(constraints); + tv->evaluate_constraints = Py_XNewRef(evaluate_constraints); + + tv->covariant = covariant; + tv->contravariant = contravariant; + tv->infer_variance = infer_variance; + _PyObject_GC_TRACK(tv); + + if (module != NULL) { + if (PyObject_SetAttrString((PyObject *)tv, "__module__", module) < 0) { + Py_DECREF(tv); + return NULL; + } + } + + return tv; +} + +/*[clinic input] +@classmethod +typevar.__new__ as typevar_new + + name: object(subclass_of="&PyUnicode_Type") + *constraints: object + * + bound: object = None + covariant: bool = False + contravariant: bool = False + infer_variance: bool = False + +Create a TypeVar. +[clinic start generated code]*/ + +static PyObject * +typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints, + PyObject *bound, int covariant, int contravariant, + int infer_variance) +/*[clinic end generated code: output=1d200450ee99226d input=2c07ab87c94f462b]*/ +{ + if (covariant && contravariant) { + PyErr_SetString(PyExc_ValueError, + "Bivariant types are not supported."); + return NULL; + } + + if (infer_variance && (covariant || contravariant)) { + PyErr_SetString(PyExc_ValueError, + "Variance cannot be specified with infer_variance."); + return NULL; + } + + if (Py_IsNone(bound)) { + bound = NULL; + } + if (bound != NULL) { + bound = type_check(bound, "Bound must be a type."); + if (bound == NULL) { + return NULL; + } + } + + if (!PyTuple_CheckExact(constraints)) { + PyErr_SetString(PyExc_TypeError, + "constraints must be a tuple"); + return NULL; + } + Py_ssize_t n_constraints = PyTuple_GET_SIZE(constraints); + if (n_constraints == 1) { + PyErr_SetString(PyExc_TypeError, + "A single constraint is not allowed"); + Py_XDECREF(bound); + return NULL; + } else if (n_constraints == 0) { + constraints = NULL; + } else if (bound != NULL) { + PyErr_SetString(PyExc_TypeError, + "Constraints cannot be combined with bound=..."); + Py_XDECREF(bound); + return NULL; + } + PyObject *module = caller(); + if (module == NULL) { + Py_XDECREF(bound); + return NULL; + } + + PyObject *tv = (PyObject *)typevar_alloc(name, bound, NULL, + constraints, NULL, + covariant, contravariant, + infer_variance, module); + Py_XDECREF(bound); + Py_XDECREF(module); + return tv; +} + +/*[clinic input] +typevar.__typing_subst__ as typevar_typing_subst + + arg: object + +[clinic start generated code]*/ + +static PyObject * +typevar_typing_subst_impl(typevarobject *self, PyObject *arg) +/*[clinic end generated code: output=c76ced134ed8f4e1 input=6b70a4bb2da838de]*/ +{ + PyObject *args[2] = {(PyObject *)self, arg}; + PyObject *result = call_typing_func_object("_typevar_subst", args, 2); + return result; +} + +/*[clinic input] +typevar.__reduce__ as typevar_reduce + +[clinic start generated code]*/ + +static PyObject * +typevar_reduce_impl(typevarobject *self) +/*[clinic end generated code: output=02e5c55d7cf8a08f input=de76bc95f04fb9ff]*/ +{ + return Py_NewRef(self->name); +} + +static PyObject * +typevar_mro_entries(PyObject *self, PyObject *args) +{ + PyErr_SetString(PyExc_TypeError, + "Cannot subclass an instance of TypeVar"); + return NULL; +} + +static PyMethodDef typevar_methods[] = { + TYPEVAR_TYPING_SUBST_METHODDEF + TYPEVAR_REDUCE_METHODDEF + {"__mro_entries__", typevar_mro_entries, METH_O}, + {0} +}; + +PyDoc_STRVAR(typevar_doc, +"Type variable.\n\ +\n\ +Usage::\n\ +\n\ + T = TypeVar('T') # Can be anything\n\ + A = TypeVar('A', str, bytes) # Must be str or bytes\n\ +\n\ +Type variables exist primarily for the benefit of static type\n\ +checkers. They serve as the parameters for generic types as well\n\ +as for generic function definitions. See class Generic for more\n\ +information on generic types. Generic functions work as follows:\n\ +\n\ + def repeat(x: T, n: int) -> List[T]:\n\ + '''Return a list containing n references to x.'''\n\ + return [x]*n\n\ +\n\ + def longest(x: A, y: A) -> A:\n\ + '''Return the longest of two strings.'''\n\ + return x if len(x) >= len(y) else y\n\ +\n\ +The latter example's signature is essentially the overloading\n\ +of (str, str) -> str and (bytes, bytes) -> bytes. Also note\n\ +that if the arguments are instances of some subclass of str,\n\ +the return type is still plain str.\n\ +\n\ +At runtime, isinstance(x, T) and issubclass(C, T) will raise TypeError.\n\ +\n\ +Type variables defined with covariant=True or contravariant=True\n\ +can be used to declare covariant or contravariant generic types.\n\ +See PEP 484 for more details. By default generic types are invariant\n\ +in all type variables.\n\ +\n\ +Type variables can be introspected. e.g.:\n\ +\n\ + T.__name__ == 'T'\n\ + T.__constraints__ == ()\n\ + T.__covariant__ == False\n\ + T.__contravariant__ = False\n\ + A.__constraints__ == (str, bytes)\n\ +\n\ +Note that only type variables defined in global scope can be pickled.\n\ +"); + +static PyType_Slot typevar_slots[] = { + {Py_tp_doc, (void *)typevar_doc}, + {Py_tp_methods, typevar_methods}, + {Py_nb_or, make_union}, + {Py_tp_new, typevar_new}, + {Py_tp_dealloc, typevar_dealloc}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_free, PyObject_GC_Del}, + {Py_tp_traverse, typevar_traverse}, + {Py_tp_clear, typevar_clear}, + {Py_tp_repr, typevar_repr}, + {Py_tp_members, typevar_members}, + {Py_tp_getset, typevar_getset}, + {0, NULL}, +}; + +PyType_Spec typevar_spec = { + .name = "typing.TypeVar", + .basicsize = sizeof(typevarobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE + | Py_TPFLAGS_MANAGED_DICT, + .slots = typevar_slots, +}; + +typedef struct { + PyObject_HEAD + PyObject *__origin__; +} paramspecattrobject; + +static void +paramspecattr_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + paramspecattrobject *psa = (paramspecattrobject *)self; + + _PyObject_GC_UNTRACK(self); + + Py_XDECREF(psa->__origin__); + + Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); +} + +static int +paramspecattr_traverse(PyObject *self, visitproc visit, void *arg) +{ + paramspecattrobject *psa = (paramspecattrobject *)self; + Py_VISIT(psa->__origin__); + return 0; +} + +static int +paramspecattr_clear(paramspecattrobject *self) +{ + Py_CLEAR(self->__origin__); + return 0; +} + +static PyObject * +paramspecattr_richcompare(PyObject *a, PyObject *b, int op) +{ + if (!Py_IS_TYPE(a, Py_TYPE(b))) { + Py_RETURN_NOTIMPLEMENTED; + } + if (op != Py_EQ && op != Py_NE) { + Py_RETURN_NOTIMPLEMENTED; + } + return PyObject_RichCompare( + ((paramspecattrobject *)a)->__origin__, + ((paramspecattrobject *)b)->__origin__, + op + ); +} + +static PyMemberDef paramspecattr_members[] = { + {"__origin__", T_OBJECT, offsetof(paramspecattrobject, __origin__), READONLY}, + {0} +}; + +static paramspecattrobject * +paramspecattr_new(PyTypeObject *tp, PyObject *origin) +{ + paramspecattrobject *psa = PyObject_GC_New(paramspecattrobject, tp); + if (psa == NULL) { + return NULL; + } + psa->__origin__ = Py_NewRef(origin); + _PyObject_GC_TRACK(psa); + return psa; +} + +static PyObject * +paramspecargs_repr(PyObject *self) +{ + paramspecattrobject *psa = (paramspecattrobject *)self; + + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspec_type; + if (Py_IS_TYPE(psa->__origin__, tp)) { + return PyUnicode_FromFormat("%U.args", + ((paramspecobject *)psa->__origin__)->name); + } + return PyUnicode_FromFormat("%R.args", psa->__origin__); +} + + +/*[clinic input] +@classmethod +paramspecargs.__new__ as paramspecargs_new + + origin: object + +Create a ParamSpecArgs object. +[clinic start generated code]*/ + +static PyObject * +paramspecargs_new_impl(PyTypeObject *type, PyObject *origin) +/*[clinic end generated code: output=9a1463dc8942fe4e input=3596a0bb6183c208]*/ +{ + return (PyObject *)paramspecattr_new(type, origin); +} + +static PyObject * +paramspecargs_mro_entries(PyObject *self, PyObject *args) +{ + PyErr_SetString(PyExc_TypeError, + "Cannot subclass an instance of ParamSpecArgs"); + return NULL; +} + +static PyMethodDef paramspecargs_methods[] = { + {"__mro_entries__", paramspecargs_mro_entries, METH_O}, + {0} +}; + +PyDoc_STRVAR(paramspecargs_doc, +"The args for a ParamSpec object.\n\ +\n\ +Given a ParamSpec object P, P.args is an instance of ParamSpecArgs.\n\ +\n\ +ParamSpecArgs objects have a reference back to their ParamSpec:\n\ +\n\ + P.args.__origin__ is P\n\ +\n\ +This type is meant for runtime introspection and has no special meaning to\n\ +static type checkers.\n\ +"); + +static PyType_Slot paramspecargs_slots[] = { + {Py_tp_doc, (void *)paramspecargs_doc}, + {Py_tp_methods, paramspecargs_methods}, + {Py_tp_new, paramspecargs_new}, + {Py_tp_dealloc, paramspecattr_dealloc}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_free, PyObject_GC_Del}, + {Py_tp_traverse, paramspecattr_traverse}, + {Py_tp_clear, (inquiry)paramspecattr_clear}, + {Py_tp_repr, paramspecargs_repr}, + {Py_tp_members, paramspecattr_members}, + {Py_tp_richcompare, paramspecattr_richcompare}, + {0, NULL}, +}; + +PyType_Spec paramspecargs_spec = { + .name = "typing.ParamSpecArgs", + .basicsize = sizeof(paramspecattrobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE, + .slots = paramspecargs_slots, +}; + +static PyObject * +paramspeckwargs_repr(PyObject *self) +{ + paramspecattrobject *psk = (paramspecattrobject *)self; + + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspec_type; + if (Py_IS_TYPE(psk->__origin__, tp)) { + return PyUnicode_FromFormat("%U.kwargs", + ((paramspecobject *)psk->__origin__)->name); + } + return PyUnicode_FromFormat("%R.kwargs", psk->__origin__); +} + +/*[clinic input] +@classmethod +paramspeckwargs.__new__ as paramspeckwargs_new + + origin: object + +Create a ParamSpecKwargs object. +[clinic start generated code]*/ + +static PyObject * +paramspeckwargs_new_impl(PyTypeObject *type, PyObject *origin) +/*[clinic end generated code: output=277b11967ebaf4ab input=981bca9b0cf9e40a]*/ +{ + return (PyObject *)paramspecattr_new(type, origin); +} + +static PyObject * +paramspeckwargs_mro_entries(PyObject *self, PyObject *args) +{ + PyErr_SetString(PyExc_TypeError, + "Cannot subclass an instance of ParamSpecKwargs"); + return NULL; +} + +static PyMethodDef paramspeckwargs_methods[] = { + {"__mro_entries__", paramspeckwargs_mro_entries, METH_O}, + {0} +}; + +PyDoc_STRVAR(paramspeckwargs_doc, +"The kwargs for a ParamSpec object.\n\ +\n\ +Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs.\n\ +\n\ +ParamSpecKwargs objects have a reference back to their ParamSpec:\n\ +\n\ + P.kwargs.__origin__ is P\n\ +\n\ +This type is meant for runtime introspection and has no special meaning to\n\ +static type checkers.\n\ +"); + +static PyType_Slot paramspeckwargs_slots[] = { + {Py_tp_doc, (void *)paramspeckwargs_doc}, + {Py_tp_methods, paramspeckwargs_methods}, + {Py_tp_new, paramspeckwargs_new}, + {Py_tp_dealloc, paramspecattr_dealloc}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_free, PyObject_GC_Del}, + {Py_tp_traverse, paramspecattr_traverse}, + {Py_tp_clear, (inquiry)paramspecattr_clear}, + {Py_tp_repr, paramspeckwargs_repr}, + {Py_tp_members, paramspecattr_members}, + {Py_tp_richcompare, paramspecattr_richcompare}, + {0, NULL}, +}; + +PyType_Spec paramspeckwargs_spec = { + .name = "typing.ParamSpecKwargs", + .basicsize = sizeof(paramspecattrobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE, + .slots = paramspeckwargs_slots, +}; + +static void +paramspec_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + paramspecobject *ps = (paramspecobject *)self; + + _PyObject_GC_UNTRACK(self); + + Py_DECREF(ps->name); + Py_XDECREF(ps->bound); + _PyObject_ClearManagedDict(self); + + Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); +} + +static int +paramspec_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + paramspecobject *ps = (paramspecobject *)self; + Py_VISIT(ps->bound); + _PyObject_VisitManagedDict(self, visit, arg); + return 0; +} + +static int +paramspec_clear(paramspecobject *self) +{ + Py_CLEAR(self->bound); + _PyObject_ClearManagedDict((PyObject *)self); + return 0; +} + +static PyObject * +paramspec_repr(PyObject *self) +{ + paramspecobject *ps = (paramspecobject *)self; + + if (ps->infer_variance) { + return Py_NewRef(ps->name); + } + + char variance = ps->covariant ? '+' : ps->contravariant ? '-' : '~'; + return PyUnicode_FromFormat("%c%U", variance, ps->name); +} + +static PyMemberDef paramspec_members[] = { + {"__name__", T_OBJECT, offsetof(paramspecobject, name), READONLY}, + {"__bound__", T_OBJECT, offsetof(paramspecobject, bound), READONLY}, + {"__covariant__", T_BOOL, offsetof(paramspecobject, covariant), READONLY}, + {"__contravariant__", T_BOOL, offsetof(paramspecobject, contravariant), READONLY}, + {"__infer_variance__", T_BOOL, offsetof(paramspecobject, infer_variance), READONLY}, + {0} +}; + +static PyObject * +paramspec_args(PyObject *self, void *unused) +{ + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspecargs_type; + return (PyObject *)paramspecattr_new(tp, self); +} + +static PyObject * +paramspec_kwargs(PyObject *self, void *unused) +{ + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspeckwargs_type; + return (PyObject *)paramspecattr_new(tp, self); +} + +static PyGetSetDef paramspec_getset[] = { + {"args", (getter)paramspec_args, NULL, "Represents positional arguments.", NULL}, + {"kwargs", (getter)paramspec_kwargs, NULL, "Represents keyword arguments.", NULL}, + {0}, +}; + +static paramspecobject * +paramspec_alloc(PyObject *name, PyObject *bound, bool covariant, + bool contravariant, bool infer_variance, PyObject *module) +{ + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.paramspec_type; + paramspecobject *ps = PyObject_GC_New(paramspecobject, tp); + if (ps == NULL) { + return NULL; + } + ps->name = Py_NewRef(name); + ps->bound = Py_XNewRef(bound); + ps->covariant = covariant; + ps->contravariant = contravariant; + ps->infer_variance = infer_variance; + _PyObject_GC_TRACK(ps); + if (module != NULL) { + if (PyObject_SetAttrString((PyObject *)ps, "__module__", module) < 0) { + Py_DECREF(ps); + return NULL; + } + } + return ps; +} + +/*[clinic input] +@classmethod +paramspec.__new__ as paramspec_new + + name: object(subclass_of="&PyUnicode_Type") + * + bound: object = None + covariant: bool = False + contravariant: bool = False + infer_variance: bool = False + +Create a ParamSpec object. +[clinic start generated code]*/ + +static PyObject * +paramspec_new_impl(PyTypeObject *type, PyObject *name, PyObject *bound, + int covariant, int contravariant, int infer_variance) +/*[clinic end generated code: output=fd2daab79cba62da input=57c49c581979b952]*/ +{ + if (covariant && contravariant) { + PyErr_SetString(PyExc_ValueError, "Bivariant types are not supported."); + return NULL; + } + if (infer_variance && (covariant || contravariant)) { + PyErr_SetString(PyExc_ValueError, "Variance cannot be specified with infer_variance."); + return NULL; + } + if (bound != NULL) { + bound = type_check(bound, "Bound must be a type."); + if (bound == NULL) { + return NULL; + } + } + PyObject *module = caller(); + if (module == NULL) { + Py_XDECREF(bound); + return NULL; + } + PyObject *ps = (PyObject *)paramspec_alloc( + name, bound, covariant, contravariant, infer_variance, module); + Py_XDECREF(bound); + Py_DECREF(module); + return ps; +} + + +/*[clinic input] +paramspec.__typing_subst__ as paramspec_typing_subst + + arg: object + +[clinic start generated code]*/ + +static PyObject * +paramspec_typing_subst_impl(paramspecobject *self, PyObject *arg) +/*[clinic end generated code: output=803e1ade3f13b57d input=4e0005d24023e896]*/ +{ + PyObject *args[2] = {(PyObject *)self, arg}; + PyObject *result = call_typing_func_object("_paramspec_subst", args, 2); + return result; +} + +/*[clinic input] +paramspec.__typing_prepare_subst__ as paramspec_typing_prepare_subst + + alias: object + args: object + +[clinic start generated code]*/ + +static PyObject * +paramspec_typing_prepare_subst_impl(paramspecobject *self, PyObject *alias, + PyObject *args) +/*[clinic end generated code: output=95449d630a2adb9a input=4375e2ffcb2ad635]*/ +{ + PyObject *args_array[3] = {(PyObject *)self, alias, args}; + PyObject *result = call_typing_func_object( + "_paramspec_prepare_subst", args_array, 3); + return result; +} + +/*[clinic input] +paramspec.__reduce__ as paramspec_reduce + +[clinic start generated code]*/ + +static PyObject * +paramspec_reduce_impl(paramspecobject *self) +/*[clinic end generated code: output=b83398674416db27 input=5bf349f0d5dd426c]*/ +{ + return Py_NewRef(self->name); +} + +static PyObject * +paramspec_mro_entries(PyObject *self, PyObject *args) +{ + PyErr_SetString(PyExc_TypeError, + "Cannot subclass an instance of ParamSpec"); + return NULL; +} + +static PyMethodDef paramspec_methods[] = { + PARAMSPEC_TYPING_SUBST_METHODDEF + PARAMSPEC_TYPING_PREPARE_SUBST_METHODDEF + PARAMSPEC_REDUCE_METHODDEF + {"__mro_entries__", paramspec_mro_entries, METH_O}, + {0} +}; + +PyDoc_STRVAR(paramspec_doc, +"Parameter specification variable.\n\ +\n\ +Usage::\n\ +\n\ + P = ParamSpec('P')\n\ +\n\ +Parameter specification variables exist primarily for the benefit of static\n\ +type checkers. They are used to forward the parameter types of one\n\ +callable to another callable, a pattern commonly found in higher order\n\ +functions and decorators. They are only valid when used in ``Concatenate``,\n\ +or as the first argument to ``Callable``, or as parameters for user-defined\n\ +Generics. See class Generic for more information on generic types. An\n\ +example for annotating a decorator::\n\ +\n\ + T = TypeVar('T')\n\ + P = ParamSpec('P')\n\ +\n\ + def add_logging(f: Callable[P, T]) -> Callable[P, T]:\n\ + '''A type-safe decorator to add logging to a function.'''\n\ + def inner(*args: P.args, **kwargs: P.kwargs) -> T:\n\ + logging.info(f'{f.__name__} was called')\n\ + return f(*args, **kwargs)\n\ + return inner\n\ +\n\ + @add_logging\n\ + def add_two(x: float, y: float) -> float:\n\ + '''Add two numbers together.'''\n\ + return x + y\n\ +\n\ +Parameter specification variables defined with covariant=True or\n\ +contravariant=True can be used to declare covariant or contravariant\n\ +generic types. These keyword arguments are valid, but their actual semantics\n\ +are yet to be decided. See PEP 612 for details.\n\ +\n\ +Parameter specification variables can be introspected. e.g.:\n\ +\n\ + P.__name__ == 'P'\n\ + P.__bound__ == None\n\ + P.__covariant__ == False\n\ + P.__contravariant__ == False\n\ +\n\ +Note that only parameter specification variables defined in global scope can\n\ +be pickled.\n\ +"); + +static PyType_Slot paramspec_slots[] = { + {Py_tp_doc, (void *)paramspec_doc}, + {Py_tp_members, paramspec_members}, + {Py_tp_methods, paramspec_methods}, + {Py_tp_getset, paramspec_getset}, + // Unions of ParamSpecs have no defined meaning, but they were allowed + // by the Python implementation, so we allow them here too. + {Py_nb_or, make_union}, + {Py_tp_new, paramspec_new}, + {Py_tp_dealloc, paramspec_dealloc}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_free, PyObject_GC_Del}, + {Py_tp_traverse, paramspec_traverse}, + {Py_tp_clear, paramspec_clear}, + {Py_tp_repr, paramspec_repr}, + {0, 0}, +}; + +PyType_Spec paramspec_spec = { + .name = "typing.ParamSpec", + .basicsize = sizeof(paramspecobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE + | Py_TPFLAGS_MANAGED_DICT, + .slots = paramspec_slots, +}; + +static void +typevartuple_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + _PyObject_GC_UNTRACK(self); + typevartupleobject *tvt = (typevartupleobject *)self; + + Py_DECREF(tvt->name); + _PyObject_ClearManagedDict(self); + + Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); +} + +static PyObject * +typevartuple_iter(PyObject *self) +{ + PyObject *unpacked = typevartuple_unpack(self); + if (unpacked == NULL) { + return NULL; + } + PyObject *tuple = PyTuple_Pack(1, unpacked); + if (tuple == NULL) { + Py_DECREF(unpacked); + return NULL; + } + PyObject *result = PyObject_GetIter(tuple); + Py_DECREF(unpacked); + Py_DECREF(tuple); + return result; +} + +static PyObject * +typevartuple_repr(PyObject *self) +{ + typevartupleobject *tvt = (typevartupleobject *)self; + + return Py_NewRef(tvt->name); +} + +static PyMemberDef typevartuple_members[] = { + {"__name__", T_OBJECT, offsetof(typevartupleobject, name), READONLY}, + {0} +}; + +static typevartupleobject * +typevartuple_alloc(PyObject *name, PyObject *module) +{ + PyTypeObject *tp = PyInterpreterState_Get()->cached_objects.typevartuple_type; + typevartupleobject *tvt = PyObject_GC_New(typevartupleobject, tp); + if (tvt == NULL) { + return NULL; + } + tvt->name = Py_NewRef(name); + _PyObject_GC_TRACK(tvt); + if (module != NULL) { + if (PyObject_SetAttrString((PyObject *)tvt, "__module__", module) < 0) { + Py_DECREF(tvt); + return NULL; + } + } + return tvt; +} + +/*[clinic input] +@classmethod +typevartuple.__new__ + + name: object(subclass_of="&PyUnicode_Type") + +Create a new TypeVarTuple with the given name. +[clinic start generated code]*/ + +static PyObject * +typevartuple_impl(PyTypeObject *type, PyObject *name) +/*[clinic end generated code: output=09d417a28f976202 input=00d28abcf1fc96bb]*/ +{ + PyObject *module = caller(); + if (module == NULL) { + return NULL; + } + PyObject *result = (PyObject *)typevartuple_alloc(name, module); + Py_DECREF(module); + return result; +} + +/*[clinic input] +typevartuple.__typing_subst__ as typevartuple_typing_subst + + arg: object + +[clinic start generated code]*/ + +static PyObject * +typevartuple_typing_subst_impl(typevartupleobject *self, PyObject *arg) +/*[clinic end generated code: output=814316519441cd76 input=670c4e0a36e5d8c0]*/ +{ + PyErr_SetString(PyExc_TypeError, "Substitution of bare TypeVarTuple is not supported"); + return NULL; +} + +/*[clinic input] +typevartuple.__typing_prepare_subst__ as typevartuple_typing_prepare_subst + + alias: object + args: object + +[clinic start generated code]*/ + +static PyObject * +typevartuple_typing_prepare_subst_impl(typevartupleobject *self, + PyObject *alias, PyObject *args) +/*[clinic end generated code: output=ff999bc5b02036c1 input=a211b05f2eeb4306]*/ +{ + PyObject *args_array[3] = {(PyObject *)self, alias, args}; + PyObject *result = call_typing_func_object( + "_typevartuple_prepare_subst", args_array, 3); + return result; +} + +/*[clinic input] +typevartuple.__reduce__ as typevartuple_reduce + +[clinic start generated code]*/ + +static PyObject * +typevartuple_reduce_impl(typevartupleobject *self) +/*[clinic end generated code: output=3215bc0477913d20 input=3018a4d66147e807]*/ +{ + return Py_NewRef(self->name); +} + +static PyObject * +typevartuple_mro_entries(PyObject *self, PyObject *args) +{ + PyErr_SetString(PyExc_TypeError, + "Cannot subclass an instance of TypeVarTuple"); + return NULL; +} + +static int +typevartuple_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + _PyObject_VisitManagedDict(self, visit, arg); + return 0; +} + +static int +typevartuple_clear(PyObject *self) +{ + _PyObject_ClearManagedDict(self); + return 0; +} + +static PyMethodDef typevartuple_methods[] = { + TYPEVARTUPLE_TYPING_SUBST_METHODDEF + TYPEVARTUPLE_TYPING_PREPARE_SUBST_METHODDEF + TYPEVARTUPLE_REDUCE_METHODDEF + {"__mro_entries__", typevartuple_mro_entries, METH_O}, + {0} +}; + +PyDoc_STRVAR(typevartuple_doc, +"Type variable tuple.\n\ +\n\ +Usage:\n\ +\n\ + Ts = TypeVarTuple('Ts') # Can be given any name\n\ +\n\ +Just as a TypeVar (type variable) is a placeholder for a single type,\n\ +a TypeVarTuple is a placeholder for an *arbitrary* number of types. For\n\ +example, if we define a generic class using a TypeVarTuple:\n\ +\n\ + class C(Generic[*Ts]): ...\n\ +\n\ +Then we can parameterize that class with an arbitrary number of type\n\ +arguments:\n\ +\n\ + C[int] # Fine\n\ + C[int, str] # Also fine\n\ + C[()] # Even this is fine\n\ +\n\ +For more details, see PEP 646.\n\ +\n\ +Note that only TypeVarTuples defined in global scope can be pickled.\n\ +"); + +PyType_Slot typevartuple_slots[] = { + {Py_tp_doc, (void *)typevartuple_doc}, + {Py_tp_members, typevartuple_members}, + {Py_tp_methods, typevartuple_methods}, + {Py_tp_new, typevartuple}, + {Py_tp_iter, typevartuple_iter}, + {Py_tp_repr, typevartuple_repr}, + {Py_tp_dealloc, typevartuple_dealloc}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_free, PyObject_GC_Del}, + {Py_tp_traverse, typevartuple_traverse}, + {Py_tp_clear, typevartuple_clear}, + {0, 0}, +}; + +PyType_Spec typevartuple_spec = { + .name = "typing.TypeVarTuple", + .basicsize = sizeof(typevartupleobject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_DICT + | Py_TPFLAGS_HAVE_GC, + .slots = typevartuple_slots, +}; + +PyObject * +_Py_make_typevar(PyObject *name, PyObject *evaluate_bound, PyObject *evaluate_constraints) +{ + return (PyObject *)typevar_alloc(name, NULL, evaluate_bound, NULL, evaluate_constraints, + false, false, true, NULL); +} + +PyObject * +_Py_make_paramspec(PyThreadState *Py_UNUSED(ignored), PyObject *v) +{ + assert(PyUnicode_Check(v)); + return (PyObject *)paramspec_alloc(v, NULL, false, false, true, NULL); +} + +PyObject * +_Py_make_typevartuple(PyThreadState *Py_UNUSED(ignored), PyObject *v) +{ + assert(PyUnicode_Check(v)); + return (PyObject *)typevartuple_alloc(v, NULL); +} + +static void +typealias_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + _PyObject_GC_UNTRACK(self); + typealiasobject *ta = (typealiasobject *)self; + Py_DECREF(ta->name); + Py_XDECREF(ta->type_params); + Py_XDECREF(ta->compute_value); + Py_XDECREF(ta->value); + Py_XDECREF(ta->module); + Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); +} + +static PyObject * +typealias_get_value(typealiasobject *ta) +{ + if (ta->value != NULL) { + return Py_NewRef(ta->value); + } + PyObject *result = PyObject_CallNoArgs(ta->compute_value); + if (result == NULL) { + return NULL; + } + ta->value = Py_NewRef(result); + return result; +} + +static PyObject * +typealias_repr(PyObject *self) +{ + typealiasobject *ta = (typealiasobject *)self; + return Py_NewRef(ta->name); +} + +static PyMemberDef typealias_members[] = { + {"__name__", T_OBJECT, offsetof(typealiasobject, name), READONLY}, + {0} +}; + +static PyObject * +typealias_value(PyObject *self, void *unused) +{ + typealiasobject *ta = (typealiasobject *)self; + return typealias_get_value(ta); +} + +static PyObject * +typealias_parameters(PyObject *self, void *unused) +{ + typealiasobject *ta = (typealiasobject *)self; + if (ta->type_params == NULL) { + return PyTuple_New(0); + } + return unpack_typevartuples(ta->type_params); +} + +static PyObject * +typealias_type_params(PyObject *self, void *unused) +{ + typealiasobject *ta = (typealiasobject *)self; + if (ta->type_params == NULL) { + return PyTuple_New(0); + } + return Py_NewRef(ta->type_params); +} + +static PyObject * +typealias_module(PyObject *self, void *unused) +{ + typealiasobject *ta = (typealiasobject *)self; + if (ta->module != NULL) { + return Py_NewRef(ta->module); + } + if (ta->compute_value != NULL) { + // PyFunction_GetModule() returns a borrowed reference + return Py_NewRef(PyFunction_GetModule(ta->compute_value)); + } + Py_RETURN_NONE; +} + +static PyGetSetDef typealias_getset[] = { + {"__parameters__", typealias_parameters, (setter)NULL, NULL, NULL}, + {"__type_params__", typealias_type_params, (setter)NULL, NULL, NULL}, + {"__value__", typealias_value, (setter)NULL, NULL, NULL}, + {"__module__", typealias_module, (setter)NULL, NULL, NULL}, + {0} +}; + +static typealiasobject * +typealias_alloc(PyObject *name, PyObject *type_params, PyObject *compute_value, + PyObject *value, PyObject *module) +{ + typealiasobject *ta = PyObject_GC_New(typealiasobject, &_PyTypeAlias_Type); + if (ta == NULL) { + return NULL; + } + ta->name = Py_NewRef(name); + ta->type_params = Py_IsNone(type_params) ? NULL : Py_XNewRef(type_params); + ta->compute_value = Py_XNewRef(compute_value); + ta->value = Py_XNewRef(value); + ta->module = Py_XNewRef(module); + _PyObject_GC_TRACK(ta); + return ta; +} + +static int +typealias_traverse(typealiasobject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->type_params); + Py_VISIT(self->compute_value); + Py_VISIT(self->value); + Py_VISIT(self->module); + return 0; +} + +static int +typealias_clear(typealiasobject *self) +{ + Py_CLEAR(self->type_params); + Py_CLEAR(self->compute_value); + Py_CLEAR(self->value); + Py_CLEAR(self->module); + return 0; +} + +/*[clinic input] +typealias.__reduce__ as typealias_reduce + +[clinic start generated code]*/ + +static PyObject * +typealias_reduce_impl(typealiasobject *self) +/*[clinic end generated code: output=913724f92ad3b39b input=4f06fbd9472ec0f1]*/ +{ + return Py_NewRef(self->name); +} + +static PyObject * +typealias_subscript(PyObject *self, PyObject *args) +{ + if (((typealiasobject *)self)->type_params == NULL) { + PyErr_SetString(PyExc_TypeError, + "Only generic type aliases are subscriptable"); + return NULL; + } + return Py_GenericAlias(self, args); +} + +static PyMethodDef typealias_methods[] = { + TYPEALIAS_REDUCE_METHODDEF + {0} +}; + + +/*[clinic input] +@classmethod +typealias.__new__ as typealias_new + + name: object(subclass_of="&PyUnicode_Type") + value: object + * + type_params: object = NULL + +Create a TypeAliasType. +[clinic start generated code]*/ + +static PyObject * +typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value, + PyObject *type_params) +/*[clinic end generated code: output=8920ce6bdff86f00 input=df163c34e17e1a35]*/ +{ + if (type_params != NULL && !PyTuple_Check(type_params)) { + PyErr_SetString(PyExc_TypeError, "type_params must be a tuple"); + return NULL; + } + PyObject *module = caller(); + if (module == NULL) { + return NULL; + } + PyObject *ta = (PyObject *)typealias_alloc(name, type_params, NULL, value, + module); + Py_DECREF(module); + return ta; +} + +PyDoc_STRVAR(typealias_doc, +"Type alias.\n\ +\n\ +Type aliases are created through the type statement:\n\ +\n\ + type Alias = int\n\ +"); + +static PyNumberMethods typealias_as_number = { + .nb_or = _Py_union_type_or, +}; + +static PyMappingMethods typealias_as_mapping = { + .mp_subscript = typealias_subscript, +}; + +PyTypeObject _PyTypeAlias_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "typing.TypeAliasType", + .tp_basicsize = sizeof(typealiasobject), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC, + .tp_doc = typealias_doc, + .tp_members = typealias_members, + .tp_methods = typealias_methods, + .tp_getset = typealias_getset, + .tp_alloc = PyType_GenericAlloc, + .tp_dealloc = typealias_dealloc, + .tp_new = typealias_new, + .tp_free = PyObject_GC_Del, + .tp_traverse = (traverseproc)typealias_traverse, + .tp_clear = (inquiry)typealias_clear, + .tp_repr = typealias_repr, + .tp_as_number = &typealias_as_number, + .tp_as_mapping = &typealias_as_mapping, +}; + +PyObject * +_Py_make_typealias(PyThreadState* unused, PyObject *args) +{ + assert(PyTuple_Check(args)); + assert(PyTuple_GET_SIZE(args) == 3); + PyObject *name = PyTuple_GET_ITEM(args, 0); + assert(PyUnicode_Check(name)); + PyObject *type_params = PyTuple_GET_ITEM(args, 1); + PyObject *compute_value = PyTuple_GET_ITEM(args, 2); + assert(PyFunction_Check(compute_value)); + return (PyObject *)typealias_alloc(name, type_params, compute_value, NULL, NULL); +} + +PyDoc_STRVAR(generic_doc, +"Abstract base class for generic types.\n\ +\n\ +A generic type is typically declared by inheriting from\n\ +this class parameterized with one or more type variables.\n\ +For example, a generic mapping type might be defined as::\n\ +\n\ + class Mapping(Generic[KT, VT]):\n\ + def __getitem__(self, key: KT) -> VT:\n\ + ...\n\ + # Etc.\n\ +\n\ +This class can then be used as follows::\n\ +\n\ + def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:\n\ + try:\n\ + return mapping[key]\n\ + except KeyError:\n\ + return default\n\ +"); + +PyDoc_STRVAR(generic_class_getitem_doc, +"Parameterizes a generic class.\n\ +\n\ +At least, parameterizing a generic class is the *main* thing this method\n\ +does. For example, for some generic class `Foo`, this is called when we\n\ +do `Foo[int]` - there, with `cls=Foo` and `params=int`.\n\ +\n\ +However, note that this method is also called when defining generic\n\ +classes in the first place with `class Foo(Generic[T]): ...`.\n\ +"); + +static PyObject * +call_typing_args_kwargs(const char *name, PyTypeObject *cls, PyObject *args, PyObject *kwargs) +{ + PyObject *typing = NULL, *func = NULL, *new_args = NULL; + typing = PyImport_ImportModule("typing"); + if (typing == NULL) { + goto error; + } + func = PyObject_GetAttrString(typing, name); + if (func == NULL) { + goto error; + } + assert(PyTuple_Check(args)); + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + new_args = PyTuple_New(nargs + 1); + if (new_args == NULL) { + goto error; + } + PyTuple_SET_ITEM(new_args, 0, Py_NewRef((PyObject *)cls)); + for (Py_ssize_t i = 0; i < nargs; i++) { + PyObject *arg = PyTuple_GET_ITEM(args, i); + PyTuple_SET_ITEM(new_args, i + 1, Py_NewRef(arg)); + } + PyObject *result = PyObject_Call(func, new_args, kwargs); + Py_DECREF(typing); + Py_DECREF(func); + Py_DECREF(new_args); + return result; +error: + Py_XDECREF(typing); + Py_XDECREF(func); + Py_XDECREF(new_args); + return NULL; +} + +static PyObject * +generic_init_subclass(PyTypeObject *cls, PyObject *args, PyObject *kwargs) +{ + return call_typing_args_kwargs("_generic_init_subclass", cls, args, kwargs); +} + +static PyObject * +generic_class_getitem(PyTypeObject *cls, PyObject *args, PyObject *kwargs) +{ + return call_typing_args_kwargs("_generic_class_getitem", cls, args, kwargs); +} + +PyObject * +_Py_subscript_generic(PyThreadState* unused, PyObject *params) +{ + params = unpack_typevartuples(params); + + PyInterpreterState *interp = PyInterpreterState_Get(); + if (interp->cached_objects.generic_type == NULL) { + PyErr_SetString(PyExc_SystemError, "Cannot find Generic type"); + return NULL; + } + PyObject *args[2] = {(PyObject *)interp->cached_objects.generic_type, params}; + PyObject *result = call_typing_func_object("_GenericAlias", args, 2); + Py_DECREF(params); + return result; +} + +static PyMethodDef generic_methods[] = { + {"__class_getitem__", (PyCFunction)(void (*)(void))generic_class_getitem, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, + generic_class_getitem_doc}, + {"__init_subclass__", (PyCFunction)(void (*)(void))generic_init_subclass, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, + PyDoc_STR("Function to initialize subclasses.")}, + {NULL} /* Sentinel */ +}; + +static void +generic_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + _PyObject_GC_UNTRACK(self); + Py_TYPE(self)->tp_free(self); + Py_DECREF(tp); +} + +static int +generic_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static PyType_Slot generic_slots[] = { + {Py_tp_doc, (void *)generic_doc}, + {Py_tp_methods, generic_methods}, + {Py_tp_dealloc, generic_dealloc}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_free, PyObject_GC_Del}, + {Py_tp_traverse, generic_traverse}, + {0, NULL}, +}; + +PyType_Spec generic_spec = { + .name = "typing.Generic", + .basicsize = sizeof(PyObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = generic_slots, +}; + +int _Py_initialize_generic(PyInterpreterState *interp) +{ +#define MAKE_TYPE(name) \ + do { \ + PyTypeObject *name ## _type = (PyTypeObject *)PyType_FromSpec(&name ## _spec); \ + if (name ## _type == NULL) { \ + return -1; \ + } \ + interp->cached_objects.name ## _type = name ## _type; \ + } while(0) + + MAKE_TYPE(generic); + MAKE_TYPE(typevar); + MAKE_TYPE(typevartuple); + MAKE_TYPE(paramspec); + MAKE_TYPE(paramspecargs); + MAKE_TYPE(paramspeckwargs); +#undef MAKE_TYPE + return 0; +} + +void _Py_clear_generic_types(PyInterpreterState *interp) +{ + Py_CLEAR(interp->cached_objects.generic_type); + Py_CLEAR(interp->cached_objects.typevar_type); + Py_CLEAR(interp->cached_objects.typevartuple_type); + Py_CLEAR(interp->cached_objects.paramspec_type); + Py_CLEAR(interp->cached_objects.paramspecargs_type); + Py_CLEAR(interp->cached_objects.paramspeckwargs_type); +} diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 7726f2fb17afde..ec5684b1d09502 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -56,6 +56,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "pycore_unicodeobject.h" // struct _Py_unicode_state #include "pycore_unicodeobject_generated.h" // _PyUnicode_InitStaticStrings() #include "stringlib/eq.h" // unicode_eq() +#include // ptrdiff_t #ifdef MS_WINDOWS #include @@ -2285,14 +2286,15 @@ PyUnicode_AsUCS4Copy(PyObject *string) return as_ucs4(string, NULL, 0, 1); } -/* maximum number of characters required for output of %lld or %p. - We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits, - plus 1 for the sign. 53/22 is an upper bound for log10(256). */ -#define MAX_LONG_LONG_CHARS (2 + (SIZEOF_LONG_LONG*53-1) / 22) +/* maximum number of characters required for output of %jo or %jd or %p. + We need at most ceil(log8(256)*sizeof(intmax_t)) digits, + plus 1 for the sign, plus 2 for the 0x prefix (for %p), + plus 1 for the terminal NUL. */ +#define MAX_INTMAX_CHARS (5 + (sizeof(intmax_t)*8-1) / 3) static int unicode_fromformat_write_str(_PyUnicodeWriter *writer, PyObject *str, - Py_ssize_t width, Py_ssize_t precision) + Py_ssize_t width, Py_ssize_t precision, int flags) { Py_ssize_t length, fill, arglen; Py_UCS4 maxchar; @@ -2314,8 +2316,8 @@ unicode_fromformat_write_str(_PyUnicodeWriter *writer, PyObject *str, if (_PyUnicodeWriter_Prepare(writer, arglen, maxchar) == -1) return -1; - if (width > length) { - fill = width - length; + fill = Py_MAX(width - length, 0); + if (fill && !(flags & F_LJUST)) { if (PyUnicode_Fill(writer->buffer, writer->pos, fill, ' ') == -1) return -1; writer->pos += fill; @@ -2324,12 +2326,19 @@ unicode_fromformat_write_str(_PyUnicodeWriter *writer, PyObject *str, _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, str, 0, length); writer->pos += length; + + if (fill && (flags & F_LJUST)) { + if (PyUnicode_Fill(writer->buffer, writer->pos, fill, ' ') == -1) + return -1; + writer->pos += fill; + } + return 0; } static int unicode_fromformat_write_cstr(_PyUnicodeWriter *writer, const char *str, - Py_ssize_t width, Py_ssize_t precision) + Py_ssize_t width, Py_ssize_t precision, int flags) { /* UTF-8 */ Py_ssize_t length; @@ -2349,24 +2358,58 @@ unicode_fromformat_write_cstr(_PyUnicodeWriter *writer, const char *str, if (unicode == NULL) return -1; - res = unicode_fromformat_write_str(writer, unicode, width, -1); + res = unicode_fromformat_write_str(writer, unicode, width, -1, flags); + Py_DECREF(unicode); + return res; +} + +static int +unicode_fromformat_write_wcstr(_PyUnicodeWriter *writer, const wchar_t *str, + Py_ssize_t width, Py_ssize_t precision, int flags) +{ + /* UTF-8 */ + Py_ssize_t length; + PyObject *unicode; + int res; + + if (precision == -1) { + length = wcslen(str); + } + else { + length = 0; + while (length < precision && str[length]) { + length++; + } + } + unicode = PyUnicode_FromWideChar(str, length); + if (unicode == NULL) + return -1; + + res = unicode_fromformat_write_str(writer, unicode, width, -1, flags); Py_DECREF(unicode); return res; } +#define F_LONG 1 +#define F_LONGLONG 2 +#define F_SIZE 3 +#define F_PTRDIFF 4 +#define F_INTMAX 5 +static const char * const formats[] = {"%d", "%ld", "%lld", "%zd", "%td", "%jd"}; +static const char * const formats_o[] = {"%o", "%lo", "%llo", "%zo", "%to", "%jo"}; +static const char * const formats_u[] = {"%u", "%lu", "%llu", "%zu", "%tu", "%ju"}; +static const char * const formats_x[] = {"%x", "%lx", "%llx", "%zx", "%tx", "%jx"}; +static const char * const formats_X[] = {"%X", "%lX", "%llX", "%zX", "%tX", "%jX"}; + static const char* unicode_fromformat_arg(_PyUnicodeWriter *writer, const char *f, va_list *vargs) { const char *p; Py_ssize_t len; - int zeropad; + int flags = 0; Py_ssize_t width; Py_ssize_t precision; - int longflag; - int longlongflag; - int size_tflag; - Py_ssize_t fill; p = f; f++; @@ -2377,15 +2420,31 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, return f; } - zeropad = 0; - if (*f == '0') { - zeropad = 1; - f++; + /* Parse flags. Example: "%-i" => flags=F_LJUST. */ + /* Flags '+', ' ' and '#' are not particularly useful. + * They are not worth the implementation and maintenance costs. + * In addition, '#' should add "0" for "o" conversions for compatibility + * with printf, but it would confuse Python users. */ + while (1) { + switch (*f++) { + case '-': flags |= F_LJUST; continue; + case '0': flags |= F_ZERO; continue; + } + f--; + break; } /* parse the width.precision part, e.g. "%2.5s" => width=2, precision=5 */ width = -1; - if (Py_ISDIGIT((unsigned)*f)) { + if (*f == '*') { + width = va_arg(*vargs, int); + if (width < 0) { + flags |= F_LJUST; + width = -width; + } + f++; + } + else if (Py_ISDIGIT((unsigned)*f)) { width = *f - '0'; f++; while (Py_ISDIGIT((unsigned)*f)) { @@ -2401,7 +2460,14 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, precision = -1; if (*f == '.') { f++; - if (Py_ISDIGIT((unsigned)*f)) { + if (*f == '*') { + precision = va_arg(*vargs, int); + if (precision < 0) { + precision = -2; + } + f++; + } + else if (Py_ISDIGIT((unsigned)*f)) { precision = (*f - '0'); f++; while (Py_ISDIGIT((unsigned)*f)) { @@ -2416,30 +2482,47 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, } } - /* Handle %ld, %lu, %lld and %llu. */ - longflag = 0; - longlongflag = 0; - size_tflag = 0; + int sizemod = 0; if (*f == 'l') { - if (f[1] == 'd' || f[1] == 'u' || f[1] == 'i') { - longflag = 1; - ++f; - } - else if (f[1] == 'l' && - (f[2] == 'd' || f[2] == 'u' || f[2] == 'i')) { - longlongflag = 1; + if (f[1] == 'l') { + sizemod = F_LONGLONG; f += 2; } + else { + sizemod = F_LONG; + ++f; + } } - /* handle the size_t flag. */ - else if (*f == 'z' && (f[1] == 'd' || f[1] == 'u' || f[1] == 'i')) { - size_tflag = 1; + else if (*f == 'z') { + sizemod = F_SIZE; + ++f; + } + else if (*f == 't') { + sizemod = F_PTRDIFF; + ++f; + } + else if (*f == 'j') { + sizemod = F_INTMAX; ++f; } - if (f[0] != '\0' && f[1] == '\0') writer->overallocate = 0; + switch (*f) { + case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': + break; + case 'c': case 'p': + if (sizemod || width >= 0 || precision >= 0) goto invalid_format; + break; + case 's': + case 'V': + if (sizemod && sizemod != F_LONG) goto invalid_format; + break; + default: + if (sizemod) goto invalid_format; + break; + } + switch (*f) { case 'c': { @@ -2454,91 +2537,98 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, break; } - case 'i': - case 'd': - case 'u': - case 'x': + case 'd': case 'i': + case 'o': case 'u': case 'x': case 'X': { /* used by sprintf */ - char buffer[MAX_LONG_LONG_CHARS]; - Py_ssize_t arglen; - - if (*f == 'u') { - if (longflag) { - len = sprintf(buffer, "%lu", va_arg(*vargs, unsigned long)); - } - else if (longlongflag) { - len = sprintf(buffer, "%llu", va_arg(*vargs, unsigned long long)); - } - else if (size_tflag) { - len = sprintf(buffer, "%zu", va_arg(*vargs, size_t)); - } - else { - len = sprintf(buffer, "%u", va_arg(*vargs, unsigned int)); - } - } - else if (*f == 'x') { - len = sprintf(buffer, "%x", va_arg(*vargs, int)); - } - else { - if (longflag) { - len = sprintf(buffer, "%li", va_arg(*vargs, long)); - } - else if (longlongflag) { - len = sprintf(buffer, "%lli", va_arg(*vargs, long long)); - } - else if (size_tflag) { - len = sprintf(buffer, "%zi", va_arg(*vargs, Py_ssize_t)); - } - else { - len = sprintf(buffer, "%i", va_arg(*vargs, int)); - } + char buffer[MAX_INTMAX_CHARS]; + const char *fmt = NULL; + switch (*f) { + case 'o': fmt = formats_o[sizemod]; break; + case 'u': fmt = formats_u[sizemod]; break; + case 'x': fmt = formats_x[sizemod]; break; + case 'X': fmt = formats_X[sizemod]; break; + default: fmt = formats[sizemod]; break; + } + int issigned = (*f == 'd' || *f == 'i'); + switch (sizemod) { + case F_LONG: + len = issigned ? + sprintf(buffer, fmt, va_arg(*vargs, long)) : + sprintf(buffer, fmt, va_arg(*vargs, unsigned long)); + break; + case F_LONGLONG: + len = issigned ? + sprintf(buffer, fmt, va_arg(*vargs, long long)) : + sprintf(buffer, fmt, va_arg(*vargs, unsigned long long)); + break; + case F_SIZE: + len = issigned ? + sprintf(buffer, fmt, va_arg(*vargs, Py_ssize_t)) : + sprintf(buffer, fmt, va_arg(*vargs, size_t)); + break; + case F_PTRDIFF: + len = sprintf(buffer, fmt, va_arg(*vargs, ptrdiff_t)); + break; + case F_INTMAX: + len = issigned ? + sprintf(buffer, fmt, va_arg(*vargs, intmax_t)) : + sprintf(buffer, fmt, va_arg(*vargs, uintmax_t)); + break; + default: + len = issigned ? + sprintf(buffer, fmt, va_arg(*vargs, int)) : + sprintf(buffer, fmt, va_arg(*vargs, unsigned int)); + break; } assert(len >= 0); - int negative = (buffer[0] == '-'); - len -= negative; + int sign = (buffer[0] == '-'); + len -= sign; precision = Py_MAX(precision, len); - width = Py_MAX(width, precision + negative); + width = Py_MAX(width, precision + sign); + if ((flags & F_ZERO) && !(flags & F_LJUST)) { + precision = width - sign; + } - arglen = Py_MAX(precision, width); - if (_PyUnicodeWriter_Prepare(writer, arglen, 127) == -1) - return NULL; + Py_ssize_t spacepad = Py_MAX(width - precision - sign, 0); + Py_ssize_t zeropad = Py_MAX(precision - len, 0); - if (width > precision) { - if (negative && zeropad) { - if (_PyUnicodeWriter_WriteChar(writer, '-') == -1) - return NULL; - } + if (_PyUnicodeWriter_Prepare(writer, width, 127) == -1) + return NULL; - Py_UCS4 fillchar = zeropad?'0':' '; - fill = width - precision - negative; - if (PyUnicode_Fill(writer->buffer, writer->pos, fill, fillchar) == -1) + if (spacepad && !(flags & F_LJUST)) { + if (PyUnicode_Fill(writer->buffer, writer->pos, spacepad, ' ') == -1) return NULL; - writer->pos += fill; + writer->pos += spacepad; + } - if (negative && !zeropad) { - if (_PyUnicodeWriter_WriteChar(writer, '-') == -1) - return NULL; - } + if (sign) { + if (_PyUnicodeWriter_WriteChar(writer, '-') == -1) + return NULL; } - if (precision > len) { - fill = precision - len; - if (PyUnicode_Fill(writer->buffer, writer->pos, fill, '0') == -1) + if (zeropad) { + if (PyUnicode_Fill(writer->buffer, writer->pos, zeropad, '0') == -1) return NULL; - writer->pos += fill; + writer->pos += zeropad; } - if (_PyUnicodeWriter_WriteASCIIString(writer, &buffer[negative], len) < 0) + if (_PyUnicodeWriter_WriteASCIIString(writer, &buffer[sign], len) < 0) return NULL; + + if (spacepad && (flags & F_LJUST)) { + if (PyUnicode_Fill(writer->buffer, writer->pos, spacepad, ' ') == -1) + return NULL; + writer->pos += spacepad; + } break; } case 'p': { - char number[MAX_LONG_LONG_CHARS]; + char number[MAX_INTMAX_CHARS]; len = sprintf(number, "%p", va_arg(*vargs, void*)); assert(len >= 0); @@ -2561,10 +2651,17 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, case 's': { - /* UTF-8 */ - const char *s = va_arg(*vargs, const char*); - if (unicode_fromformat_write_cstr(writer, s, width, precision) < 0) - return NULL; + if (sizemod) { + const wchar_t *s = va_arg(*vargs, const wchar_t*); + if (unicode_fromformat_write_wcstr(writer, s, width, precision, flags) < 0) + return NULL; + } + else { + /* UTF-8 */ + const char *s = va_arg(*vargs, const char*); + if (unicode_fromformat_write_cstr(writer, s, width, precision, flags) < 0) + return NULL; + } break; } @@ -2573,7 +2670,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, PyObject *obj = va_arg(*vargs, PyObject *); assert(obj && _PyUnicode_CHECK(obj)); - if (unicode_fromformat_write_str(writer, obj, width, precision) == -1) + if (unicode_fromformat_write_str(writer, obj, width, precision, flags) == -1) return NULL; break; } @@ -2581,15 +2678,27 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, case 'V': { PyObject *obj = va_arg(*vargs, PyObject *); - const char *str = va_arg(*vargs, const char *); + const char *str; + const wchar_t *wstr; + if (sizemod) { + wstr = va_arg(*vargs, const wchar_t*); + } + else { + str = va_arg(*vargs, const char *); + } if (obj) { assert(_PyUnicode_CHECK(obj)); - if (unicode_fromformat_write_str(writer, obj, width, precision) == -1) + if (unicode_fromformat_write_str(writer, obj, width, precision, flags) == -1) + return NULL; + } + else if (sizemod) { + assert(wstr != NULL); + if (unicode_fromformat_write_wcstr(writer, wstr, width, precision, flags) < 0) return NULL; } else { assert(str != NULL); - if (unicode_fromformat_write_cstr(writer, str, width, precision) < 0) + if (unicode_fromformat_write_cstr(writer, str, width, precision, flags) < 0) return NULL; } break; @@ -2603,7 +2712,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, str = PyObject_Str(obj); if (!str) return NULL; - if (unicode_fromformat_write_str(writer, str, width, precision) == -1) { + if (unicode_fromformat_write_str(writer, str, width, precision, flags) == -1) { Py_DECREF(str); return NULL; } @@ -2619,7 +2728,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, repr = PyObject_Repr(obj); if (!repr) return NULL; - if (unicode_fromformat_write_str(writer, repr, width, precision) == -1) { + if (unicode_fromformat_write_str(writer, repr, width, precision, flags) == -1) { Py_DECREF(repr); return NULL; } @@ -2635,7 +2744,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, ascii = PyObject_ASCII(obj); if (!ascii) return NULL; - if (unicode_fromformat_write_str(writer, ascii, width, precision) == -1) { + if (unicode_fromformat_write_str(writer, ascii, width, precision, flags) == -1) { Py_DECREF(ascii); return NULL; } @@ -2644,6 +2753,7 @@ unicode_fromformat_arg(_PyUnicodeWriter *writer, } default: + invalid_format: PyErr_Format(PyExc_SystemError, "invalid format string: %s", p); return NULL; } diff --git a/Objects/unionobject.c b/Objects/unionobject.c index f273f7d15ef25f..f509a161bb9564 100644 --- a/Objects/unionobject.c +++ b/Objects/unionobject.c @@ -1,6 +1,7 @@ // types.UnionType -- used to represent e.g. Union[int, str], int | str #include "Python.h" #include "pycore_object.h" // _PyObject_GC_TRACK/UNTRACK +#include "pycore_typevarobject.h" // _PyTypeAlias_Type #include "pycore_unionobject.h" #include "structmember.h" @@ -147,10 +148,14 @@ get_types(PyObject **obj, Py_ssize_t *size) static int is_unionable(PyObject *obj) { - return (obj == Py_None || + if (obj == Py_None || PyType_Check(obj) || _PyGenericAlias_Check(obj) || - _PyUnion_Check(obj)); + _PyUnion_Check(obj) || + Py_IS_TYPE(obj, &_PyTypeAlias_Type)) { + return 1; + } + return 0; } PyObject * diff --git a/PC/layout/main.py b/PC/layout/main.py index c9246007d47d18..cb2e4878da26b1 100644 --- a/PC/layout/main.py +++ b/PC/layout/main.py @@ -49,8 +49,6 @@ REQUIRED_DLLS = FileStemSet("libcrypto*", "libssl*", "libffi*") -LIB2TO3_GRAMMAR_FILES = FileNameSet("Grammar.txt", "PatternGrammar.txt") - PY_FILES = FileSuffixSet(".py") PYC_FILES = FileSuffixSet(".pyc") CAT_FILES = FileSuffixSet(".cat") @@ -298,27 +296,6 @@ def _write_to_zip(zf, dest, src, ns, checked=True): log_exception("Failed to delete {}", pyc) return - if src in LIB2TO3_GRAMMAR_FILES: - from lib2to3.pgen2.driver import load_grammar - - tmp = ns.temp / src.name - try: - shutil.copy(src, tmp) - load_grammar(str(tmp)) - for f in ns.temp.glob(src.stem + "*.pickle"): - zf.write(str(f), str(dest.parent / f.name)) - try: - f.unlink() - except: - log_exception("Failed to delete {}", f) - except: - log_exception("Failed to compile {}", src) - finally: - try: - tmp.unlink() - except: - log_exception("Failed to delete {}", tmp) - zf.write(str(src), str(dest)) diff --git a/PC/layout/support/props.py b/PC/layout/support/props.py index c7a7a0ce777a6e..f751a4b3f1e437 100644 --- a/PC/layout/support/props.py +++ b/PC/layout/support/props.py @@ -36,7 +36,6 @@ {PYTHON_VERSION} true - false false {PYTHON_TARGET};$(GetPythonRuntimeFilesDependsOn) @@ -67,7 +66,6 @@ DLLs\%(Filename)%(Extension) <_PythonRuntimeLib Include="$(PythonHome)\Lib\**\*" Exclude="$(PythonHome)\Lib\**\*.pyc;$(PythonHome)\Lib\site-packages\**\*" /> - <_PythonRuntimeLib Remove="$(PythonHome)\Lib\lib2to3\**\*" Condition="$(IncludeLib2To3) != 'true'" /> <_PythonRuntimeLib Remove="$(PythonHome)\Lib\ensurepip\**\*" Condition="$(IncludeVEnv) != 'true'" /> <_PythonRuntimeLib Remove="$(PythonHome)\Lib\venv\**\*" Condition="$(IncludeVEnv) != 'true'" /> <_PythonRuntimeLib> diff --git a/PC/layout/support/python.props b/PC/layout/support/python.props index e46891aafcb9fc..c48ecb2f9c1b57 100644 --- a/PC/layout/support/python.props +++ b/PC/layout/support/python.props @@ -8,7 +8,6 @@ $$PYTHON_VERSION$$ true - false false $$PYTHON_TARGET$$;$(GetPythonRuntimeFilesDependsOn) @@ -40,7 +39,6 @@ DLLs\%(Filename)%(Extension) <_PythonRuntimeLib Include="$(PythonHome)\Lib\**\*" Exclude="$(PythonHome)\Lib\**\*.pyc;$(PythonHome)\Lib\site-packages\**\*" /> - <_PythonRuntimeLib Remove="$(PythonHome)\Lib\lib2to3\**\*" Condition="$(IncludeLib2To3) != 'true'" /> <_PythonRuntimeLib Remove="$(PythonHome)\Lib\ensurepip\**\*" Condition="$(IncludeVEnv) != 'true'" /> <_PythonRuntimeLib Remove="$(PythonHome)\Lib\venv\**\*" Condition="$(IncludeVEnv) != 'true'" /> <_PythonRuntimeLib> diff --git a/PC/pyconfig.h b/PC/pyconfig.h index 3415efe2dea117..f9250d6faccbea 100644 --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -308,11 +308,11 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ file in their Makefile (other compilers are generally taken care of by distutils.) */ # if defined(_DEBUG) -# pragma comment(lib,"python312_d.lib") +# pragma comment(lib,"python313_d.lib") # elif defined(Py_LIMITED_API) # pragma comment(lib,"python3.lib") # else -# pragma comment(lib,"python312.lib") +# pragma comment(lib,"python313.lib") # endif /* _DEBUG */ # endif /* _MSC_VER */ # endif /* Py_BUILD_CORE */ diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index d897925f58c0de..3df0a072045208 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -159,6 +159,7 @@ + @@ -241,6 +242,7 @@ + diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 176935a63c4852..d98a4c5ae4e2bb 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -394,6 +394,9 @@ Source Files + + Source Files + Source Files diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 30ee873af9af24..39003d954d705a 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ set libraries= set libraries=%libraries% bzip2-1.0.8 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.4 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1t -set libraries=%libraries% sqlite-3.41.2.0 +set libraries=%libraries% sqlite-3.42.0.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.13.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.13.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 diff --git a/PCbuild/python.props b/PCbuild/python.props index 29add07795f900..1d959699f3cfb0 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -68,7 +68,7 @@ - $(ExternalsDir)sqlite-3.41.2.0\ + $(ExternalsDir)sqlite-3.42.0.0\ $(ExternalsDir)bzip2-1.0.8\ $(ExternalsDir)xz-5.2.5\ $(ExternalsDir)libffi-3.4.4\ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 28b1517c6f6b3a..48cd4418f90fee 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -269,6 +269,7 @@ + @@ -481,6 +482,7 @@ + @@ -565,6 +567,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 75e6fbb13f98ba..5c8c1444e8100e 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -705,6 +705,9 @@ Include\internal + + Include\internal + Include\internal @@ -1265,6 +1268,9 @@ Python + + Python + Python @@ -1364,6 +1370,9 @@ Objects + + Objects + Objects diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 9df56685b76a87..3629525e33d56c 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -188,7 +188,7 @@ _ssl again when building. _sqlite3 - Wraps SQLite 3.41.2, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.42.0, which is itself built by sqlite3.vcxproj Homepage: https://www.sqlite.org/ _tkinter diff --git a/Parser/Python.asdl b/Parser/Python.asdl index e9423a7c984f21..dc2eb802b0436c 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -8,14 +8,15 @@ module Python | Expression(expr body) | FunctionType(expr* argtypes, expr returns) - stmt = FunctionDef(identifier name, arguments args, + stmt = FunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment) - | AsyncFunctionDef(identifier name, arguments args, + | AsyncFunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, + type_param* type_params, expr* bases, keyword* keywords, stmt* body, @@ -24,6 +25,7 @@ module Python | Delete(expr* targets) | Assign(expr* targets, expr value, string? type_comment) + | TypeAlias(expr name, type_param* type_params, expr value) | AugAssign(expr target, operator op, expr value) -- 'simple' indicates that we annotate simple name without parens | AnnAssign(expr target, expr annotation, expr? value, int simple) @@ -142,4 +144,9 @@ module Python attributes (int lineno, int col_offset, int end_lineno, int end_col_offset) type_ignore = TypeIgnore(int lineno, string tag) + + type_param = TypeVar(identifier name, expr? bound) + | ParamSpec(identifier name) + | TypeVarTuple(identifier name) + attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset) } diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 0aaaed64c4037c..06d77b64cacbcc 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -752,7 +752,8 @@ _PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty f assert(function_def != NULL); if (function_def->kind == AsyncFunctionDef_kind) { return _PyAST_AsyncFunctionDef( - function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, + function_def->v.FunctionDef.name, function_def->v.FunctionDef.type_params, + function_def->v.FunctionDef.args, function_def->v.FunctionDef.body, decorators, function_def->v.FunctionDef.returns, function_def->v.FunctionDef.type_comment, function_def->lineno, function_def->col_offset, function_def->end_lineno, function_def->end_col_offset, @@ -760,7 +761,8 @@ _PyPegen_function_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty f } return _PyAST_FunctionDef( - function_def->v.FunctionDef.name, function_def->v.FunctionDef.args, + function_def->v.FunctionDef.name, function_def->v.FunctionDef.type_params, + function_def->v.FunctionDef.args, function_def->v.FunctionDef.body, decorators, function_def->v.FunctionDef.returns, function_def->v.FunctionDef.type_comment, function_def->lineno, @@ -774,8 +776,9 @@ _PyPegen_class_def_decorators(Parser *p, asdl_expr_seq *decorators, stmt_ty clas { assert(class_def != NULL); return _PyAST_ClassDef( - class_def->v.ClassDef.name, class_def->v.ClassDef.bases, - class_def->v.ClassDef.keywords, class_def->v.ClassDef.body, decorators, + class_def->v.ClassDef.name, class_def->v.ClassDef.type_params, + class_def->v.ClassDef.bases, class_def->v.ClassDef.keywords, + class_def->v.ClassDef.body, decorators, class_def->lineno, class_def->col_offset, class_def->end_lineno, class_def->end_col_offset, p->arena); } diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 3f0e29f051a438..7074aba74b728c 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -45,7 +45,10 @@ my_fgets(PyThreadState* tstate, char *buf, int len, FILE *fp) #endif while (1) { - if (PyOS_InputHook != NULL) { + if (PyOS_InputHook != NULL && + // GH-104668: See PyOS_ReadlineFunctionPointer's comment below... + _Py_IsMainInterpreter(tstate->interp)) + { (void)(PyOS_InputHook)(); } @@ -131,7 +134,10 @@ _PyOS_WindowsConsoleReadline(PyThreadState *tstate, HANDLE hStdIn) wbuf = wbuf_local; wbuflen = sizeof(wbuf_local) / sizeof(wbuf_local[0]) - 1; while (1) { - if (PyOS_InputHook != NULL) { + if (PyOS_InputHook != NULL && + // GH-104668: See PyOS_ReadlineFunctionPointer's comment below... + _Py_IsMainInterpreter(tstate->interp)) + { (void)(PyOS_InputHook)(); } if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) { @@ -389,11 +395,23 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt) * a tty. This can happen, for example if python is run like * this: python -i < test1.py */ - if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout))) - rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt); - else - rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, - prompt); + if (!isatty(fileno(sys_stdin)) || !isatty(fileno(sys_stdout)) || + // GH-104668: Don't call global callbacks like PyOS_InputHook or + // PyOS_ReadlineFunctionPointer from subinterpreters, since it seems + // like there's no good way for users (like readline and tkinter) to + // avoid using global state to manage them. Plus, we generally don't + // want to cause trouble for libraries that don't know/care about + // subinterpreter support. If libraries really need better APIs that + // work per-interpreter and have ways to access module state, we can + // certainly add them later (but for now we'll cross our fingers and + // hope that nobody actually cares): + !_Py_IsMainInterpreter(tstate->interp)) + { + rv = PyOS_StdioReadline(sys_stdin, sys_stdout, prompt); + } + else { + rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, prompt); + } Py_END_ALLOW_THREADS PyThread_release_lock(_PyOS_ReadlineLock); diff --git a/Parser/parser.c b/Parser/parser.c index 6eb985a7d3e123..fc5466fea2b3fc 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -75,6 +75,7 @@ static char *soft_keywords[] = { "_", "case", "match", + "type", NULL, }; #define file_type 1000 @@ -175,419 +176,426 @@ static char *soft_keywords[] = { #define positional_patterns_type 1095 #define keyword_patterns_type 1096 #define keyword_pattern_type 1097 -#define expressions_type 1098 -#define expression_type 1099 -#define yield_expr_type 1100 -#define star_expressions_type 1101 -#define star_expression_type 1102 -#define star_named_expressions_type 1103 -#define star_named_expression_type 1104 -#define assignment_expression_type 1105 -#define named_expression_type 1106 -#define disjunction_type 1107 -#define conjunction_type 1108 -#define inversion_type 1109 -#define comparison_type 1110 -#define compare_op_bitwise_or_pair_type 1111 -#define eq_bitwise_or_type 1112 -#define noteq_bitwise_or_type 1113 -#define lte_bitwise_or_type 1114 -#define lt_bitwise_or_type 1115 -#define gte_bitwise_or_type 1116 -#define gt_bitwise_or_type 1117 -#define notin_bitwise_or_type 1118 -#define in_bitwise_or_type 1119 -#define isnot_bitwise_or_type 1120 -#define is_bitwise_or_type 1121 -#define bitwise_or_type 1122 // Left-recursive -#define bitwise_xor_type 1123 // Left-recursive -#define bitwise_and_type 1124 // Left-recursive -#define shift_expr_type 1125 // Left-recursive -#define sum_type 1126 // Left-recursive -#define term_type 1127 // Left-recursive -#define factor_type 1128 -#define power_type 1129 -#define await_primary_type 1130 -#define primary_type 1131 // Left-recursive -#define slices_type 1132 -#define slice_type 1133 -#define atom_type 1134 -#define group_type 1135 -#define lambdef_type 1136 -#define lambda_params_type 1137 -#define lambda_parameters_type 1138 -#define lambda_slash_no_default_type 1139 -#define lambda_slash_with_default_type 1140 -#define lambda_star_etc_type 1141 -#define lambda_kwds_type 1142 -#define lambda_param_no_default_type 1143 -#define lambda_param_with_default_type 1144 -#define lambda_param_maybe_default_type 1145 -#define lambda_param_type 1146 -#define fstring_middle_type 1147 -#define fstring_replacement_field_type 1148 -#define fstring_conversion_type 1149 -#define fstring_full_format_spec_type 1150 -#define fstring_format_spec_type 1151 -#define string_type 1152 -#define strings_type 1153 -#define list_type 1154 -#define tuple_type 1155 -#define set_type 1156 -#define dict_type 1157 -#define double_starred_kvpairs_type 1158 -#define double_starred_kvpair_type 1159 -#define kvpair_type 1160 -#define for_if_clauses_type 1161 -#define for_if_clause_type 1162 -#define listcomp_type 1163 -#define setcomp_type 1164 -#define genexp_type 1165 -#define dictcomp_type 1166 -#define arguments_type 1167 -#define args_type 1168 -#define kwargs_type 1169 -#define starred_expression_type 1170 -#define kwarg_or_starred_type 1171 -#define kwarg_or_double_starred_type 1172 -#define star_targets_type 1173 -#define star_targets_list_seq_type 1174 -#define star_targets_tuple_seq_type 1175 -#define star_target_type 1176 -#define target_with_star_atom_type 1177 -#define star_atom_type 1178 -#define single_target_type 1179 -#define single_subscript_attribute_target_type 1180 -#define t_primary_type 1181 // Left-recursive -#define t_lookahead_type 1182 -#define del_targets_type 1183 -#define del_target_type 1184 -#define del_t_atom_type 1185 -#define type_expressions_type 1186 -#define func_type_comment_type 1187 -#define invalid_arguments_type 1188 -#define invalid_kwarg_type 1189 -#define expression_without_invalid_type 1190 -#define invalid_legacy_expression_type 1191 -#define invalid_expression_type 1192 -#define invalid_named_expression_type 1193 -#define invalid_assignment_type 1194 -#define invalid_ann_assign_target_type 1195 -#define invalid_del_stmt_type 1196 -#define invalid_block_type 1197 -#define invalid_comprehension_type 1198 -#define invalid_dict_comprehension_type 1199 -#define invalid_parameters_type 1200 -#define invalid_default_type 1201 -#define invalid_star_etc_type 1202 -#define invalid_kwds_type 1203 -#define invalid_parameters_helper_type 1204 -#define invalid_lambda_parameters_type 1205 -#define invalid_lambda_parameters_helper_type 1206 -#define invalid_lambda_star_etc_type 1207 -#define invalid_lambda_kwds_type 1208 -#define invalid_double_type_comments_type 1209 -#define invalid_with_item_type 1210 -#define invalid_for_target_type 1211 -#define invalid_group_type 1212 -#define invalid_import_type 1213 -#define invalid_import_from_targets_type 1214 -#define invalid_with_stmt_type 1215 -#define invalid_with_stmt_indent_type 1216 -#define invalid_try_stmt_type 1217 -#define invalid_except_stmt_type 1218 -#define invalid_finally_stmt_type 1219 -#define invalid_except_stmt_indent_type 1220 -#define invalid_except_star_stmt_indent_type 1221 -#define invalid_match_stmt_type 1222 -#define invalid_case_block_type 1223 -#define invalid_as_pattern_type 1224 -#define invalid_class_pattern_type 1225 -#define invalid_class_argument_pattern_type 1226 -#define invalid_if_stmt_type 1227 -#define invalid_elif_stmt_type 1228 -#define invalid_else_stmt_type 1229 -#define invalid_while_stmt_type 1230 -#define invalid_for_stmt_type 1231 -#define invalid_def_raw_type 1232 -#define invalid_class_def_raw_type 1233 -#define invalid_double_starred_kvpairs_type 1234 -#define invalid_kvpair_type 1235 -#define invalid_starred_expression_type 1236 -#define invalid_replacement_field_type 1237 -#define invalid_conversion_character_type 1238 -#define _loop0_1_type 1239 -#define _loop0_2_type 1240 -#define _loop0_3_type 1241 -#define _loop1_4_type 1242 -#define _loop0_6_type 1243 -#define _gather_5_type 1244 -#define _tmp_7_type 1245 -#define _tmp_8_type 1246 -#define _tmp_9_type 1247 -#define _tmp_10_type 1248 -#define _tmp_11_type 1249 -#define _tmp_12_type 1250 -#define _tmp_13_type 1251 -#define _tmp_14_type 1252 -#define _loop1_15_type 1253 -#define _tmp_16_type 1254 -#define _tmp_17_type 1255 -#define _tmp_18_type 1256 -#define _loop0_20_type 1257 -#define _gather_19_type 1258 -#define _loop0_22_type 1259 -#define _gather_21_type 1260 -#define _tmp_23_type 1261 -#define _tmp_24_type 1262 -#define _loop0_25_type 1263 -#define _loop1_26_type 1264 -#define _loop0_28_type 1265 -#define _gather_27_type 1266 -#define _tmp_29_type 1267 -#define _loop0_31_type 1268 -#define _gather_30_type 1269 -#define _tmp_32_type 1270 -#define _loop1_33_type 1271 -#define _tmp_34_type 1272 -#define _tmp_35_type 1273 -#define _tmp_36_type 1274 -#define _loop0_37_type 1275 -#define _loop0_38_type 1276 -#define _loop0_39_type 1277 -#define _loop1_40_type 1278 -#define _loop0_41_type 1279 -#define _loop1_42_type 1280 -#define _loop1_43_type 1281 -#define _loop1_44_type 1282 -#define _loop0_45_type 1283 -#define _loop1_46_type 1284 -#define _loop0_47_type 1285 -#define _loop1_48_type 1286 -#define _loop0_49_type 1287 -#define _loop0_50_type 1288 -#define _loop1_51_type 1289 -#define _loop0_53_type 1290 -#define _gather_52_type 1291 -#define _loop0_55_type 1292 -#define _gather_54_type 1293 -#define _loop0_57_type 1294 -#define _gather_56_type 1295 -#define _loop0_59_type 1296 -#define _gather_58_type 1297 -#define _tmp_60_type 1298 -#define _loop1_61_type 1299 -#define _loop1_62_type 1300 -#define _tmp_63_type 1301 -#define _tmp_64_type 1302 -#define _loop1_65_type 1303 -#define _loop0_67_type 1304 -#define _gather_66_type 1305 -#define _tmp_68_type 1306 -#define _tmp_69_type 1307 -#define _tmp_70_type 1308 -#define _tmp_71_type 1309 -#define _loop0_73_type 1310 -#define _gather_72_type 1311 -#define _loop0_75_type 1312 -#define _gather_74_type 1313 -#define _tmp_76_type 1314 -#define _loop0_78_type 1315 -#define _gather_77_type 1316 -#define _loop0_80_type 1317 -#define _gather_79_type 1318 -#define _loop1_81_type 1319 -#define _loop1_82_type 1320 -#define _loop0_84_type 1321 -#define _gather_83_type 1322 -#define _loop1_85_type 1323 -#define _loop1_86_type 1324 -#define _loop1_87_type 1325 -#define _tmp_88_type 1326 -#define _loop0_90_type 1327 -#define _gather_89_type 1328 -#define _tmp_91_type 1329 -#define _tmp_92_type 1330 -#define _tmp_93_type 1331 -#define _tmp_94_type 1332 -#define _tmp_95_type 1333 -#define _tmp_96_type 1334 -#define _loop0_97_type 1335 -#define _loop0_98_type 1336 -#define _loop0_99_type 1337 -#define _loop1_100_type 1338 -#define _loop0_101_type 1339 -#define _loop1_102_type 1340 -#define _loop1_103_type 1341 -#define _loop1_104_type 1342 -#define _loop0_105_type 1343 -#define _loop1_106_type 1344 -#define _loop0_107_type 1345 -#define _loop1_108_type 1346 -#define _loop0_109_type 1347 -#define _loop1_110_type 1348 -#define _tmp_111_type 1349 -#define _loop0_112_type 1350 -#define _loop1_113_type 1351 -#define _tmp_114_type 1352 -#define _loop0_116_type 1353 -#define _gather_115_type 1354 -#define _loop1_117_type 1355 -#define _loop0_118_type 1356 -#define _loop0_119_type 1357 -#define _tmp_120_type 1358 -#define _loop0_122_type 1359 -#define _gather_121_type 1360 -#define _tmp_123_type 1361 -#define _loop0_125_type 1362 -#define _gather_124_type 1363 -#define _loop0_127_type 1364 -#define _gather_126_type 1365 -#define _loop0_129_type 1366 -#define _gather_128_type 1367 -#define _loop0_131_type 1368 -#define _gather_130_type 1369 -#define _loop0_132_type 1370 -#define _loop0_134_type 1371 -#define _gather_133_type 1372 -#define _loop1_135_type 1373 -#define _tmp_136_type 1374 -#define _loop0_138_type 1375 -#define _gather_137_type 1376 -#define _loop0_140_type 1377 -#define _gather_139_type 1378 -#define _loop0_142_type 1379 -#define _gather_141_type 1380 -#define _loop0_144_type 1381 -#define _gather_143_type 1382 -#define _loop0_146_type 1383 -#define _gather_145_type 1384 -#define _tmp_147_type 1385 -#define _tmp_148_type 1386 -#define _tmp_149_type 1387 -#define _tmp_150_type 1388 -#define _tmp_151_type 1389 -#define _tmp_152_type 1390 -#define _tmp_153_type 1391 -#define _tmp_154_type 1392 -#define _tmp_155_type 1393 -#define _tmp_156_type 1394 -#define _tmp_157_type 1395 -#define _tmp_158_type 1396 -#define _loop0_159_type 1397 -#define _loop0_160_type 1398 -#define _loop0_161_type 1399 -#define _tmp_162_type 1400 -#define _tmp_163_type 1401 -#define _tmp_164_type 1402 -#define _tmp_165_type 1403 -#define _tmp_166_type 1404 -#define _loop0_167_type 1405 -#define _loop0_168_type 1406 -#define _loop0_169_type 1407 -#define _loop1_170_type 1408 -#define _tmp_171_type 1409 -#define _loop0_172_type 1410 -#define _tmp_173_type 1411 -#define _loop0_174_type 1412 -#define _loop1_175_type 1413 -#define _tmp_176_type 1414 -#define _tmp_177_type 1415 -#define _tmp_178_type 1416 -#define _loop0_179_type 1417 -#define _tmp_180_type 1418 -#define _tmp_181_type 1419 -#define _loop1_182_type 1420 -#define _tmp_183_type 1421 -#define _loop0_184_type 1422 -#define _loop0_185_type 1423 -#define _loop0_186_type 1424 -#define _loop0_188_type 1425 -#define _gather_187_type 1426 -#define _tmp_189_type 1427 -#define _loop0_190_type 1428 -#define _tmp_191_type 1429 -#define _loop0_192_type 1430 -#define _loop1_193_type 1431 -#define _loop1_194_type 1432 -#define _tmp_195_type 1433 -#define _tmp_196_type 1434 -#define _loop0_197_type 1435 -#define _tmp_198_type 1436 -#define _tmp_199_type 1437 -#define _tmp_200_type 1438 -#define _loop0_202_type 1439 -#define _gather_201_type 1440 -#define _loop0_204_type 1441 -#define _gather_203_type 1442 -#define _loop0_206_type 1443 -#define _gather_205_type 1444 -#define _loop0_208_type 1445 -#define _gather_207_type 1446 -#define _tmp_209_type 1447 -#define _loop0_210_type 1448 -#define _loop1_211_type 1449 -#define _tmp_212_type 1450 -#define _loop0_213_type 1451 -#define _loop1_214_type 1452 -#define _tmp_215_type 1453 -#define _tmp_216_type 1454 -#define _tmp_217_type 1455 -#define _tmp_218_type 1456 -#define _tmp_219_type 1457 -#define _tmp_220_type 1458 -#define _tmp_221_type 1459 -#define _tmp_222_type 1460 -#define _tmp_223_type 1461 -#define _tmp_224_type 1462 -#define _loop0_226_type 1463 -#define _gather_225_type 1464 -#define _tmp_227_type 1465 -#define _tmp_228_type 1466 -#define _tmp_229_type 1467 -#define _tmp_230_type 1468 -#define _tmp_231_type 1469 -#define _tmp_232_type 1470 -#define _tmp_233_type 1471 -#define _tmp_234_type 1472 -#define _tmp_235_type 1473 -#define _tmp_236_type 1474 -#define _tmp_237_type 1475 -#define _tmp_238_type 1476 -#define _tmp_239_type 1477 -#define _loop0_240_type 1478 -#define _tmp_241_type 1479 -#define _tmp_242_type 1480 -#define _tmp_243_type 1481 -#define _tmp_244_type 1482 -#define _tmp_245_type 1483 -#define _tmp_246_type 1484 -#define _tmp_247_type 1485 -#define _tmp_248_type 1486 -#define _tmp_249_type 1487 -#define _tmp_250_type 1488 -#define _tmp_251_type 1489 -#define _tmp_252_type 1490 -#define _tmp_253_type 1491 -#define _tmp_254_type 1492 -#define _tmp_255_type 1493 -#define _tmp_256_type 1494 -#define _tmp_257_type 1495 -#define _tmp_258_type 1496 -#define _tmp_259_type 1497 -#define _tmp_260_type 1498 -#define _tmp_261_type 1499 -#define _tmp_262_type 1500 -#define _tmp_263_type 1501 -#define _tmp_264_type 1502 -#define _tmp_265_type 1503 -#define _tmp_266_type 1504 -#define _tmp_267_type 1505 -#define _tmp_268_type 1506 -#define _tmp_269_type 1507 -#define _tmp_270_type 1508 -#define _tmp_271_type 1509 -#define _tmp_272_type 1510 +#define type_alias_type 1098 +#define type_params_type 1099 +#define type_param_seq_type 1100 +#define type_param_type 1101 +#define type_param_bound_type 1102 +#define expressions_type 1103 +#define expression_type 1104 +#define yield_expr_type 1105 +#define star_expressions_type 1106 +#define star_expression_type 1107 +#define star_named_expressions_type 1108 +#define star_named_expression_type 1109 +#define assignment_expression_type 1110 +#define named_expression_type 1111 +#define disjunction_type 1112 +#define conjunction_type 1113 +#define inversion_type 1114 +#define comparison_type 1115 +#define compare_op_bitwise_or_pair_type 1116 +#define eq_bitwise_or_type 1117 +#define noteq_bitwise_or_type 1118 +#define lte_bitwise_or_type 1119 +#define lt_bitwise_or_type 1120 +#define gte_bitwise_or_type 1121 +#define gt_bitwise_or_type 1122 +#define notin_bitwise_or_type 1123 +#define in_bitwise_or_type 1124 +#define isnot_bitwise_or_type 1125 +#define is_bitwise_or_type 1126 +#define bitwise_or_type 1127 // Left-recursive +#define bitwise_xor_type 1128 // Left-recursive +#define bitwise_and_type 1129 // Left-recursive +#define shift_expr_type 1130 // Left-recursive +#define sum_type 1131 // Left-recursive +#define term_type 1132 // Left-recursive +#define factor_type 1133 +#define power_type 1134 +#define await_primary_type 1135 +#define primary_type 1136 // Left-recursive +#define slices_type 1137 +#define slice_type 1138 +#define atom_type 1139 +#define group_type 1140 +#define lambdef_type 1141 +#define lambda_params_type 1142 +#define lambda_parameters_type 1143 +#define lambda_slash_no_default_type 1144 +#define lambda_slash_with_default_type 1145 +#define lambda_star_etc_type 1146 +#define lambda_kwds_type 1147 +#define lambda_param_no_default_type 1148 +#define lambda_param_with_default_type 1149 +#define lambda_param_maybe_default_type 1150 +#define lambda_param_type 1151 +#define fstring_middle_type 1152 +#define fstring_replacement_field_type 1153 +#define fstring_conversion_type 1154 +#define fstring_full_format_spec_type 1155 +#define fstring_format_spec_type 1156 +#define string_type 1157 +#define strings_type 1158 +#define list_type 1159 +#define tuple_type 1160 +#define set_type 1161 +#define dict_type 1162 +#define double_starred_kvpairs_type 1163 +#define double_starred_kvpair_type 1164 +#define kvpair_type 1165 +#define for_if_clauses_type 1166 +#define for_if_clause_type 1167 +#define listcomp_type 1168 +#define setcomp_type 1169 +#define genexp_type 1170 +#define dictcomp_type 1171 +#define arguments_type 1172 +#define args_type 1173 +#define kwargs_type 1174 +#define starred_expression_type 1175 +#define kwarg_or_starred_type 1176 +#define kwarg_or_double_starred_type 1177 +#define star_targets_type 1178 +#define star_targets_list_seq_type 1179 +#define star_targets_tuple_seq_type 1180 +#define star_target_type 1181 +#define target_with_star_atom_type 1182 +#define star_atom_type 1183 +#define single_target_type 1184 +#define single_subscript_attribute_target_type 1185 +#define t_primary_type 1186 // Left-recursive +#define t_lookahead_type 1187 +#define del_targets_type 1188 +#define del_target_type 1189 +#define del_t_atom_type 1190 +#define type_expressions_type 1191 +#define func_type_comment_type 1192 +#define invalid_arguments_type 1193 +#define invalid_kwarg_type 1194 +#define expression_without_invalid_type 1195 +#define invalid_legacy_expression_type 1196 +#define invalid_expression_type 1197 +#define invalid_named_expression_type 1198 +#define invalid_assignment_type 1199 +#define invalid_ann_assign_target_type 1200 +#define invalid_del_stmt_type 1201 +#define invalid_block_type 1202 +#define invalid_comprehension_type 1203 +#define invalid_dict_comprehension_type 1204 +#define invalid_parameters_type 1205 +#define invalid_default_type 1206 +#define invalid_star_etc_type 1207 +#define invalid_kwds_type 1208 +#define invalid_parameters_helper_type 1209 +#define invalid_lambda_parameters_type 1210 +#define invalid_lambda_parameters_helper_type 1211 +#define invalid_lambda_star_etc_type 1212 +#define invalid_lambda_kwds_type 1213 +#define invalid_double_type_comments_type 1214 +#define invalid_with_item_type 1215 +#define invalid_for_target_type 1216 +#define invalid_group_type 1217 +#define invalid_import_type 1218 +#define invalid_import_from_targets_type 1219 +#define invalid_with_stmt_type 1220 +#define invalid_with_stmt_indent_type 1221 +#define invalid_try_stmt_type 1222 +#define invalid_except_stmt_type 1223 +#define invalid_finally_stmt_type 1224 +#define invalid_except_stmt_indent_type 1225 +#define invalid_except_star_stmt_indent_type 1226 +#define invalid_match_stmt_type 1227 +#define invalid_case_block_type 1228 +#define invalid_as_pattern_type 1229 +#define invalid_class_pattern_type 1230 +#define invalid_class_argument_pattern_type 1231 +#define invalid_if_stmt_type 1232 +#define invalid_elif_stmt_type 1233 +#define invalid_else_stmt_type 1234 +#define invalid_while_stmt_type 1235 +#define invalid_for_stmt_type 1236 +#define invalid_def_raw_type 1237 +#define invalid_class_def_raw_type 1238 +#define invalid_double_starred_kvpairs_type 1239 +#define invalid_kvpair_type 1240 +#define invalid_starred_expression_type 1241 +#define invalid_replacement_field_type 1242 +#define invalid_conversion_character_type 1243 +#define _loop0_1_type 1244 +#define _loop0_2_type 1245 +#define _loop0_3_type 1246 +#define _loop1_4_type 1247 +#define _loop0_6_type 1248 +#define _gather_5_type 1249 +#define _tmp_7_type 1250 +#define _tmp_8_type 1251 +#define _tmp_9_type 1252 +#define _tmp_10_type 1253 +#define _tmp_11_type 1254 +#define _tmp_12_type 1255 +#define _tmp_13_type 1256 +#define _tmp_14_type 1257 +#define _loop1_15_type 1258 +#define _tmp_16_type 1259 +#define _tmp_17_type 1260 +#define _tmp_18_type 1261 +#define _loop0_20_type 1262 +#define _gather_19_type 1263 +#define _loop0_22_type 1264 +#define _gather_21_type 1265 +#define _tmp_23_type 1266 +#define _tmp_24_type 1267 +#define _loop0_25_type 1268 +#define _loop1_26_type 1269 +#define _loop0_28_type 1270 +#define _gather_27_type 1271 +#define _tmp_29_type 1272 +#define _loop0_31_type 1273 +#define _gather_30_type 1274 +#define _tmp_32_type 1275 +#define _loop1_33_type 1276 +#define _tmp_34_type 1277 +#define _tmp_35_type 1278 +#define _tmp_36_type 1279 +#define _loop0_37_type 1280 +#define _loop0_38_type 1281 +#define _loop0_39_type 1282 +#define _loop1_40_type 1283 +#define _loop0_41_type 1284 +#define _loop1_42_type 1285 +#define _loop1_43_type 1286 +#define _loop1_44_type 1287 +#define _loop0_45_type 1288 +#define _loop1_46_type 1289 +#define _loop0_47_type 1290 +#define _loop1_48_type 1291 +#define _loop0_49_type 1292 +#define _loop0_50_type 1293 +#define _loop1_51_type 1294 +#define _loop0_53_type 1295 +#define _gather_52_type 1296 +#define _loop0_55_type 1297 +#define _gather_54_type 1298 +#define _loop0_57_type 1299 +#define _gather_56_type 1300 +#define _loop0_59_type 1301 +#define _gather_58_type 1302 +#define _tmp_60_type 1303 +#define _loop1_61_type 1304 +#define _loop1_62_type 1305 +#define _tmp_63_type 1306 +#define _tmp_64_type 1307 +#define _loop1_65_type 1308 +#define _loop0_67_type 1309 +#define _gather_66_type 1310 +#define _tmp_68_type 1311 +#define _tmp_69_type 1312 +#define _tmp_70_type 1313 +#define _tmp_71_type 1314 +#define _loop0_73_type 1315 +#define _gather_72_type 1316 +#define _loop0_75_type 1317 +#define _gather_74_type 1318 +#define _tmp_76_type 1319 +#define _loop0_78_type 1320 +#define _gather_77_type 1321 +#define _loop0_80_type 1322 +#define _gather_79_type 1323 +#define _loop0_82_type 1324 +#define _gather_81_type 1325 +#define _loop1_83_type 1326 +#define _loop1_84_type 1327 +#define _loop0_86_type 1328 +#define _gather_85_type 1329 +#define _loop1_87_type 1330 +#define _loop1_88_type 1331 +#define _loop1_89_type 1332 +#define _tmp_90_type 1333 +#define _loop0_92_type 1334 +#define _gather_91_type 1335 +#define _tmp_93_type 1336 +#define _tmp_94_type 1337 +#define _tmp_95_type 1338 +#define _tmp_96_type 1339 +#define _tmp_97_type 1340 +#define _tmp_98_type 1341 +#define _loop0_99_type 1342 +#define _loop0_100_type 1343 +#define _loop0_101_type 1344 +#define _loop1_102_type 1345 +#define _loop0_103_type 1346 +#define _loop1_104_type 1347 +#define _loop1_105_type 1348 +#define _loop1_106_type 1349 +#define _loop0_107_type 1350 +#define _loop1_108_type 1351 +#define _loop0_109_type 1352 +#define _loop1_110_type 1353 +#define _loop0_111_type 1354 +#define _loop1_112_type 1355 +#define _tmp_113_type 1356 +#define _loop0_114_type 1357 +#define _loop1_115_type 1358 +#define _tmp_116_type 1359 +#define _loop0_118_type 1360 +#define _gather_117_type 1361 +#define _loop1_119_type 1362 +#define _loop0_120_type 1363 +#define _loop0_121_type 1364 +#define _tmp_122_type 1365 +#define _loop0_124_type 1366 +#define _gather_123_type 1367 +#define _tmp_125_type 1368 +#define _loop0_127_type 1369 +#define _gather_126_type 1370 +#define _loop0_129_type 1371 +#define _gather_128_type 1372 +#define _loop0_131_type 1373 +#define _gather_130_type 1374 +#define _loop0_133_type 1375 +#define _gather_132_type 1376 +#define _loop0_134_type 1377 +#define _loop0_136_type 1378 +#define _gather_135_type 1379 +#define _loop1_137_type 1380 +#define _tmp_138_type 1381 +#define _loop0_140_type 1382 +#define _gather_139_type 1383 +#define _loop0_142_type 1384 +#define _gather_141_type 1385 +#define _loop0_144_type 1386 +#define _gather_143_type 1387 +#define _loop0_146_type 1388 +#define _gather_145_type 1389 +#define _loop0_148_type 1390 +#define _gather_147_type 1391 +#define _tmp_149_type 1392 +#define _tmp_150_type 1393 +#define _tmp_151_type 1394 +#define _tmp_152_type 1395 +#define _tmp_153_type 1396 +#define _tmp_154_type 1397 +#define _tmp_155_type 1398 +#define _tmp_156_type 1399 +#define _tmp_157_type 1400 +#define _tmp_158_type 1401 +#define _tmp_159_type 1402 +#define _tmp_160_type 1403 +#define _loop0_161_type 1404 +#define _loop0_162_type 1405 +#define _loop0_163_type 1406 +#define _tmp_164_type 1407 +#define _tmp_165_type 1408 +#define _tmp_166_type 1409 +#define _tmp_167_type 1410 +#define _tmp_168_type 1411 +#define _loop0_169_type 1412 +#define _loop0_170_type 1413 +#define _loop0_171_type 1414 +#define _loop1_172_type 1415 +#define _tmp_173_type 1416 +#define _loop0_174_type 1417 +#define _tmp_175_type 1418 +#define _loop0_176_type 1419 +#define _loop1_177_type 1420 +#define _tmp_178_type 1421 +#define _tmp_179_type 1422 +#define _tmp_180_type 1423 +#define _loop0_181_type 1424 +#define _tmp_182_type 1425 +#define _tmp_183_type 1426 +#define _loop1_184_type 1427 +#define _tmp_185_type 1428 +#define _loop0_186_type 1429 +#define _loop0_187_type 1430 +#define _loop0_188_type 1431 +#define _loop0_190_type 1432 +#define _gather_189_type 1433 +#define _tmp_191_type 1434 +#define _loop0_192_type 1435 +#define _tmp_193_type 1436 +#define _loop0_194_type 1437 +#define _loop1_195_type 1438 +#define _loop1_196_type 1439 +#define _tmp_197_type 1440 +#define _tmp_198_type 1441 +#define _loop0_199_type 1442 +#define _tmp_200_type 1443 +#define _tmp_201_type 1444 +#define _tmp_202_type 1445 +#define _loop0_204_type 1446 +#define _gather_203_type 1447 +#define _loop0_206_type 1448 +#define _gather_205_type 1449 +#define _loop0_208_type 1450 +#define _gather_207_type 1451 +#define _loop0_210_type 1452 +#define _gather_209_type 1453 +#define _tmp_211_type 1454 +#define _loop0_212_type 1455 +#define _loop1_213_type 1456 +#define _tmp_214_type 1457 +#define _loop0_215_type 1458 +#define _loop1_216_type 1459 +#define _tmp_217_type 1460 +#define _tmp_218_type 1461 +#define _tmp_219_type 1462 +#define _tmp_220_type 1463 +#define _tmp_221_type 1464 +#define _tmp_222_type 1465 +#define _tmp_223_type 1466 +#define _tmp_224_type 1467 +#define _tmp_225_type 1468 +#define _tmp_226_type 1469 +#define _loop0_228_type 1470 +#define _gather_227_type 1471 +#define _tmp_229_type 1472 +#define _tmp_230_type 1473 +#define _tmp_231_type 1474 +#define _tmp_232_type 1475 +#define _tmp_233_type 1476 +#define _tmp_234_type 1477 +#define _tmp_235_type 1478 +#define _tmp_236_type 1479 +#define _tmp_237_type 1480 +#define _tmp_238_type 1481 +#define _tmp_239_type 1482 +#define _tmp_240_type 1483 +#define _tmp_241_type 1484 +#define _loop0_242_type 1485 +#define _tmp_243_type 1486 +#define _tmp_244_type 1487 +#define _tmp_245_type 1488 +#define _tmp_246_type 1489 +#define _tmp_247_type 1490 +#define _tmp_248_type 1491 +#define _tmp_249_type 1492 +#define _tmp_250_type 1493 +#define _tmp_251_type 1494 +#define _tmp_252_type 1495 +#define _tmp_253_type 1496 +#define _tmp_254_type 1497 +#define _tmp_255_type 1498 +#define _tmp_256_type 1499 +#define _tmp_257_type 1500 +#define _tmp_258_type 1501 +#define _tmp_259_type 1502 +#define _tmp_260_type 1503 +#define _tmp_261_type 1504 +#define _tmp_262_type 1505 +#define _tmp_263_type 1506 +#define _tmp_264_type 1507 +#define _tmp_265_type 1508 +#define _tmp_266_type 1509 +#define _tmp_267_type 1510 +#define _tmp_268_type 1511 +#define _tmp_269_type 1512 +#define _tmp_270_type 1513 +#define _tmp_271_type 1514 +#define _tmp_272_type 1515 +#define _tmp_273_type 1516 +#define _tmp_274_type 1517 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -687,6 +695,11 @@ static pattern_ty class_pattern_rule(Parser *p); static asdl_pattern_seq* positional_patterns_rule(Parser *p); static asdl_seq* keyword_patterns_rule(Parser *p); static KeyPatternPair* keyword_pattern_rule(Parser *p); +static stmt_ty type_alias_rule(Parser *p); +static asdl_type_param_seq* type_params_rule(Parser *p); +static asdl_type_param_seq* type_param_seq_rule(Parser *p); +static type_param_ty type_param_rule(Parser *p); +static expr_ty type_param_bound_rule(Parser *p); static expr_ty expressions_rule(Parser *p); static expr_ty expression_rule(Parser *p); static expr_ty yield_expr_rule(Parser *p); @@ -908,64 +921,64 @@ static asdl_seq *_loop0_78_rule(Parser *p); static asdl_seq *_gather_77_rule(Parser *p); static asdl_seq *_loop0_80_rule(Parser *p); static asdl_seq *_gather_79_rule(Parser *p); -static asdl_seq *_loop1_81_rule(Parser *p); -static asdl_seq *_loop1_82_rule(Parser *p); -static asdl_seq *_loop0_84_rule(Parser *p); -static asdl_seq *_gather_83_rule(Parser *p); -static asdl_seq *_loop1_85_rule(Parser *p); -static asdl_seq *_loop1_86_rule(Parser *p); +static asdl_seq *_loop0_82_rule(Parser *p); +static asdl_seq *_gather_81_rule(Parser *p); +static asdl_seq *_loop1_83_rule(Parser *p); +static asdl_seq *_loop1_84_rule(Parser *p); +static asdl_seq *_loop0_86_rule(Parser *p); +static asdl_seq *_gather_85_rule(Parser *p); static asdl_seq *_loop1_87_rule(Parser *p); -static void *_tmp_88_rule(Parser *p); -static asdl_seq *_loop0_90_rule(Parser *p); -static asdl_seq *_gather_89_rule(Parser *p); -static void *_tmp_91_rule(Parser *p); -static void *_tmp_92_rule(Parser *p); +static asdl_seq *_loop1_88_rule(Parser *p); +static asdl_seq *_loop1_89_rule(Parser *p); +static void *_tmp_90_rule(Parser *p); +static asdl_seq *_loop0_92_rule(Parser *p); +static asdl_seq *_gather_91_rule(Parser *p); static void *_tmp_93_rule(Parser *p); static void *_tmp_94_rule(Parser *p); static void *_tmp_95_rule(Parser *p); static void *_tmp_96_rule(Parser *p); -static asdl_seq *_loop0_97_rule(Parser *p); -static asdl_seq *_loop0_98_rule(Parser *p); +static void *_tmp_97_rule(Parser *p); +static void *_tmp_98_rule(Parser *p); static asdl_seq *_loop0_99_rule(Parser *p); -static asdl_seq *_loop1_100_rule(Parser *p); +static asdl_seq *_loop0_100_rule(Parser *p); static asdl_seq *_loop0_101_rule(Parser *p); static asdl_seq *_loop1_102_rule(Parser *p); -static asdl_seq *_loop1_103_rule(Parser *p); +static asdl_seq *_loop0_103_rule(Parser *p); static asdl_seq *_loop1_104_rule(Parser *p); -static asdl_seq *_loop0_105_rule(Parser *p); +static asdl_seq *_loop1_105_rule(Parser *p); static asdl_seq *_loop1_106_rule(Parser *p); static asdl_seq *_loop0_107_rule(Parser *p); static asdl_seq *_loop1_108_rule(Parser *p); static asdl_seq *_loop0_109_rule(Parser *p); static asdl_seq *_loop1_110_rule(Parser *p); -static void *_tmp_111_rule(Parser *p); -static asdl_seq *_loop0_112_rule(Parser *p); -static asdl_seq *_loop1_113_rule(Parser *p); -static void *_tmp_114_rule(Parser *p); -static asdl_seq *_loop0_116_rule(Parser *p); -static asdl_seq *_gather_115_rule(Parser *p); -static asdl_seq *_loop1_117_rule(Parser *p); +static asdl_seq *_loop0_111_rule(Parser *p); +static asdl_seq *_loop1_112_rule(Parser *p); +static void *_tmp_113_rule(Parser *p); +static asdl_seq *_loop0_114_rule(Parser *p); +static asdl_seq *_loop1_115_rule(Parser *p); +static void *_tmp_116_rule(Parser *p); static asdl_seq *_loop0_118_rule(Parser *p); -static asdl_seq *_loop0_119_rule(Parser *p); -static void *_tmp_120_rule(Parser *p); -static asdl_seq *_loop0_122_rule(Parser *p); -static asdl_seq *_gather_121_rule(Parser *p); -static void *_tmp_123_rule(Parser *p); -static asdl_seq *_loop0_125_rule(Parser *p); -static asdl_seq *_gather_124_rule(Parser *p); +static asdl_seq *_gather_117_rule(Parser *p); +static asdl_seq *_loop1_119_rule(Parser *p); +static asdl_seq *_loop0_120_rule(Parser *p); +static asdl_seq *_loop0_121_rule(Parser *p); +static void *_tmp_122_rule(Parser *p); +static asdl_seq *_loop0_124_rule(Parser *p); +static asdl_seq *_gather_123_rule(Parser *p); +static void *_tmp_125_rule(Parser *p); static asdl_seq *_loop0_127_rule(Parser *p); static asdl_seq *_gather_126_rule(Parser *p); static asdl_seq *_loop0_129_rule(Parser *p); static asdl_seq *_gather_128_rule(Parser *p); static asdl_seq *_loop0_131_rule(Parser *p); static asdl_seq *_gather_130_rule(Parser *p); -static asdl_seq *_loop0_132_rule(Parser *p); +static asdl_seq *_loop0_133_rule(Parser *p); +static asdl_seq *_gather_132_rule(Parser *p); static asdl_seq *_loop0_134_rule(Parser *p); -static asdl_seq *_gather_133_rule(Parser *p); -static asdl_seq *_loop1_135_rule(Parser *p); -static void *_tmp_136_rule(Parser *p); -static asdl_seq *_loop0_138_rule(Parser *p); -static asdl_seq *_gather_137_rule(Parser *p); +static asdl_seq *_loop0_136_rule(Parser *p); +static asdl_seq *_gather_135_rule(Parser *p); +static asdl_seq *_loop1_137_rule(Parser *p); +static void *_tmp_138_rule(Parser *p); static asdl_seq *_loop0_140_rule(Parser *p); static asdl_seq *_gather_139_rule(Parser *p); static asdl_seq *_loop0_142_rule(Parser *p); @@ -974,8 +987,8 @@ static asdl_seq *_loop0_144_rule(Parser *p); static asdl_seq *_gather_143_rule(Parser *p); static asdl_seq *_loop0_146_rule(Parser *p); static asdl_seq *_gather_145_rule(Parser *p); -static void *_tmp_147_rule(Parser *p); -static void *_tmp_148_rule(Parser *p); +static asdl_seq *_loop0_148_rule(Parser *p); +static asdl_seq *_gather_147_rule(Parser *p); static void *_tmp_149_rule(Parser *p); static void *_tmp_150_rule(Parser *p); static void *_tmp_151_rule(Parser *p); @@ -986,64 +999,64 @@ static void *_tmp_155_rule(Parser *p); static void *_tmp_156_rule(Parser *p); static void *_tmp_157_rule(Parser *p); static void *_tmp_158_rule(Parser *p); -static asdl_seq *_loop0_159_rule(Parser *p); -static asdl_seq *_loop0_160_rule(Parser *p); +static void *_tmp_159_rule(Parser *p); +static void *_tmp_160_rule(Parser *p); static asdl_seq *_loop0_161_rule(Parser *p); -static void *_tmp_162_rule(Parser *p); -static void *_tmp_163_rule(Parser *p); +static asdl_seq *_loop0_162_rule(Parser *p); +static asdl_seq *_loop0_163_rule(Parser *p); static void *_tmp_164_rule(Parser *p); static void *_tmp_165_rule(Parser *p); static void *_tmp_166_rule(Parser *p); -static asdl_seq *_loop0_167_rule(Parser *p); -static asdl_seq *_loop0_168_rule(Parser *p); +static void *_tmp_167_rule(Parser *p); +static void *_tmp_168_rule(Parser *p); static asdl_seq *_loop0_169_rule(Parser *p); -static asdl_seq *_loop1_170_rule(Parser *p); -static void *_tmp_171_rule(Parser *p); -static asdl_seq *_loop0_172_rule(Parser *p); +static asdl_seq *_loop0_170_rule(Parser *p); +static asdl_seq *_loop0_171_rule(Parser *p); +static asdl_seq *_loop1_172_rule(Parser *p); static void *_tmp_173_rule(Parser *p); static asdl_seq *_loop0_174_rule(Parser *p); -static asdl_seq *_loop1_175_rule(Parser *p); -static void *_tmp_176_rule(Parser *p); -static void *_tmp_177_rule(Parser *p); +static void *_tmp_175_rule(Parser *p); +static asdl_seq *_loop0_176_rule(Parser *p); +static asdl_seq *_loop1_177_rule(Parser *p); static void *_tmp_178_rule(Parser *p); -static asdl_seq *_loop0_179_rule(Parser *p); +static void *_tmp_179_rule(Parser *p); static void *_tmp_180_rule(Parser *p); -static void *_tmp_181_rule(Parser *p); -static asdl_seq *_loop1_182_rule(Parser *p); +static asdl_seq *_loop0_181_rule(Parser *p); +static void *_tmp_182_rule(Parser *p); static void *_tmp_183_rule(Parser *p); -static asdl_seq *_loop0_184_rule(Parser *p); -static asdl_seq *_loop0_185_rule(Parser *p); +static asdl_seq *_loop1_184_rule(Parser *p); +static void *_tmp_185_rule(Parser *p); static asdl_seq *_loop0_186_rule(Parser *p); +static asdl_seq *_loop0_187_rule(Parser *p); static asdl_seq *_loop0_188_rule(Parser *p); -static asdl_seq *_gather_187_rule(Parser *p); -static void *_tmp_189_rule(Parser *p); static asdl_seq *_loop0_190_rule(Parser *p); +static asdl_seq *_gather_189_rule(Parser *p); static void *_tmp_191_rule(Parser *p); static asdl_seq *_loop0_192_rule(Parser *p); -static asdl_seq *_loop1_193_rule(Parser *p); -static asdl_seq *_loop1_194_rule(Parser *p); -static void *_tmp_195_rule(Parser *p); -static void *_tmp_196_rule(Parser *p); -static asdl_seq *_loop0_197_rule(Parser *p); +static void *_tmp_193_rule(Parser *p); +static asdl_seq *_loop0_194_rule(Parser *p); +static asdl_seq *_loop1_195_rule(Parser *p); +static asdl_seq *_loop1_196_rule(Parser *p); +static void *_tmp_197_rule(Parser *p); static void *_tmp_198_rule(Parser *p); -static void *_tmp_199_rule(Parser *p); +static asdl_seq *_loop0_199_rule(Parser *p); static void *_tmp_200_rule(Parser *p); -static asdl_seq *_loop0_202_rule(Parser *p); -static asdl_seq *_gather_201_rule(Parser *p); +static void *_tmp_201_rule(Parser *p); +static void *_tmp_202_rule(Parser *p); static asdl_seq *_loop0_204_rule(Parser *p); static asdl_seq *_gather_203_rule(Parser *p); static asdl_seq *_loop0_206_rule(Parser *p); static asdl_seq *_gather_205_rule(Parser *p); static asdl_seq *_loop0_208_rule(Parser *p); static asdl_seq *_gather_207_rule(Parser *p); -static void *_tmp_209_rule(Parser *p); static asdl_seq *_loop0_210_rule(Parser *p); -static asdl_seq *_loop1_211_rule(Parser *p); -static void *_tmp_212_rule(Parser *p); -static asdl_seq *_loop0_213_rule(Parser *p); -static asdl_seq *_loop1_214_rule(Parser *p); -static void *_tmp_215_rule(Parser *p); -static void *_tmp_216_rule(Parser *p); +static asdl_seq *_gather_209_rule(Parser *p); +static void *_tmp_211_rule(Parser *p); +static asdl_seq *_loop0_212_rule(Parser *p); +static asdl_seq *_loop1_213_rule(Parser *p); +static void *_tmp_214_rule(Parser *p); +static asdl_seq *_loop0_215_rule(Parser *p); +static asdl_seq *_loop1_216_rule(Parser *p); static void *_tmp_217_rule(Parser *p); static void *_tmp_218_rule(Parser *p); static void *_tmp_219_rule(Parser *p); @@ -1052,10 +1065,10 @@ static void *_tmp_221_rule(Parser *p); static void *_tmp_222_rule(Parser *p); static void *_tmp_223_rule(Parser *p); static void *_tmp_224_rule(Parser *p); -static asdl_seq *_loop0_226_rule(Parser *p); -static asdl_seq *_gather_225_rule(Parser *p); -static void *_tmp_227_rule(Parser *p); -static void *_tmp_228_rule(Parser *p); +static void *_tmp_225_rule(Parser *p); +static void *_tmp_226_rule(Parser *p); +static asdl_seq *_loop0_228_rule(Parser *p); +static asdl_seq *_gather_227_rule(Parser *p); static void *_tmp_229_rule(Parser *p); static void *_tmp_230_rule(Parser *p); static void *_tmp_231_rule(Parser *p); @@ -1067,9 +1080,9 @@ static void *_tmp_236_rule(Parser *p); static void *_tmp_237_rule(Parser *p); static void *_tmp_238_rule(Parser *p); static void *_tmp_239_rule(Parser *p); -static asdl_seq *_loop0_240_rule(Parser *p); +static void *_tmp_240_rule(Parser *p); static void *_tmp_241_rule(Parser *p); -static void *_tmp_242_rule(Parser *p); +static asdl_seq *_loop0_242_rule(Parser *p); static void *_tmp_243_rule(Parser *p); static void *_tmp_244_rule(Parser *p); static void *_tmp_245_rule(Parser *p); @@ -1100,6 +1113,8 @@ static void *_tmp_269_rule(Parser *p); static void *_tmp_270_rule(Parser *p); static void *_tmp_271_rule(Parser *p); static void *_tmp_272_rule(Parser *p); +static void *_tmp_273_rule(Parser *p); +static void *_tmp_274_rule(Parser *p); // file: statements? $ @@ -1681,6 +1696,7 @@ simple_stmts_rule(Parser *p) // simple_stmt: // | assignment +// | &"type" type_alias // | star_expressions // | &'return' return_stmt // | &('import' | 'from') import_stmt @@ -1738,6 +1754,27 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c%s simple_stmt[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment")); } + { // &"type" type_alias + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&\"type\" type_alias")); + stmt_ty type_alias_var; + if ( + _PyPegen_lookahead_with_string(1, _PyPegen_expect_soft_keyword, p, "type") + && + (type_alias_var = type_alias_rule(p)) // type_alias + ) + { + D(fprintf(stderr, "%*c+ simple_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&\"type\" type_alias")); + _res = type_alias_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s simple_stmt[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "&\"type\" type_alias")); + } { // star_expressions if (p->error_indicator) { p->level--; @@ -4308,7 +4345,9 @@ class_def_rule(Parser *p) return _res; } -// class_def_raw: invalid_class_def_raw | 'class' NAME ['(' arguments? ')'] ':' block +// class_def_raw: +// | invalid_class_def_raw +// | 'class' NAME type_params? ['(' arguments? ')'] ':' block static stmt_ty class_def_raw_rule(Parser *p) { @@ -4350,22 +4389,25 @@ class_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c%s class_def_raw[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_class_def_raw")); } - { // 'class' NAME ['(' arguments? ')'] ':' block + { // 'class' NAME type_params? ['(' arguments? ')'] ':' block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' block")); + D(fprintf(stderr, "%*c> class_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' block")); Token * _keyword; Token * _literal; expr_ty a; void *b; asdl_stmt_seq* c; + void *t; if ( (_keyword = _PyPegen_expect_token(p, 654)) // token='class' && (a = _PyPegen_name_token(p)) // NAME && + (t = type_params_rule(p), !p->error_indicator) // type_params? + && (b = _tmp_34_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' @@ -4373,7 +4415,7 @@ class_def_raw_rule(Parser *p) (c = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' block")); + D(fprintf(stderr, "%*c+ class_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -4383,7 +4425,7 @@ class_def_raw_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_ClassDef ( a -> v . Name . id , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , EXTRA ); + _res = _PyAST_ClassDef ( a -> v . Name . id , t , ( b ) ? ( ( expr_ty ) b ) -> v . Call . args : NULL , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , c , NULL , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -4393,7 +4435,7 @@ class_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s class_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME ['(' arguments? ')'] ':' block")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class' NAME type_params? ['(' arguments? ')'] ':' block")); } _res = NULL; done: @@ -4469,8 +4511,8 @@ function_def_rule(Parser *p) // function_def_raw: // | invalid_def_raw -// | 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block -// | ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block +// | 'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block +// | ASYNC 'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block static stmt_ty function_def_raw_rule(Parser *p) { @@ -4512,12 +4554,12 @@ function_def_raw_rule(Parser *p) D(fprintf(stderr, "%*c%s function_def_raw[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_def_raw")); } - { // 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block + { // 'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token * _keyword; Token * _literal; Token * _literal_1; @@ -4526,12 +4568,15 @@ function_def_raw_rule(Parser *p) asdl_stmt_seq* b; expr_ty n; void *params; + void *t; void *tc; if ( (_keyword = _PyPegen_expect_token(p, 652)) // token='def' && (n = _PyPegen_name_token(p)) // NAME && + (t = type_params_rule(p), !p->error_indicator) // type_params? + && (_literal = _PyPegen_expect_forced_token(p, 7, "(")) // forced_token='(' && (params = params_rule(p), !p->error_indicator) // params? @@ -4547,7 +4592,7 @@ function_def_raw_rule(Parser *p) (b = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -4557,7 +4602,7 @@ function_def_raw_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_FunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); + _res = _PyAST_FunctionDef ( n -> v . Name . id , t , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -4567,14 +4612,14 @@ function_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s function_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); } - { // ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block + { // ASYNC 'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c> function_def_raw[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token * _keyword; Token * _literal; Token * _literal_1; @@ -4584,6 +4629,7 @@ function_def_raw_rule(Parser *p) asdl_stmt_seq* b; expr_ty n; void *params; + void *t; void *tc; if ( (async_var = _PyPegen_expect_token(p, ASYNC)) // token='ASYNC' @@ -4592,6 +4638,8 @@ function_def_raw_rule(Parser *p) && (n = _PyPegen_name_token(p)) // NAME && + (t = type_params_rule(p), !p->error_indicator) // type_params? + && (_literal = _PyPegen_expect_forced_token(p, 7, "(")) // forced_token='(' && (params = params_rule(p), !p->error_indicator) // params? @@ -4607,7 +4655,7 @@ function_def_raw_rule(Parser *p) (b = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); + D(fprintf(stderr, "%*c+ function_def_raw[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -4617,7 +4665,7 @@ function_def_raw_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 = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); + _res = CHECK_VERSION ( stmt_ty , 5 , "Async functions are" , _PyAST_AsyncFunctionDef ( n -> v . Name . id , t , ( params ) ? params : CHECK ( arguments_ty , _PyPegen_empty_arguments ( p ) ) , b , NULL , a , NEW_TYPE_COMMENT ( p , tc ) , EXTRA ) ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -4627,7 +4675,7 @@ function_def_raw_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s function_def_raw[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'def' NAME &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "ASYNC 'def' NAME type_params? &&'(' params? ')' ['->' expression] &&':' func_type_comment? block")); } _res = NULL; done: @@ -10530,6 +10578,438 @@ keyword_pattern_rule(Parser *p) return _res; } +// type_alias: "type" NAME type_params? '=' expression +static stmt_ty +type_alias_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + stmt_ty _res = NULL; + int _mark = p->mark; + if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { + p->error_indicator = 1; + p->level--; + return NULL; + } + int _start_lineno = p->tokens[_mark]->lineno; + UNUSED(_start_lineno); // Only used by EXTRA macro + int _start_col_offset = p->tokens[_mark]->col_offset; + UNUSED(_start_col_offset); // Only used by EXTRA macro + { // "type" NAME type_params? '=' expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_alias[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"type\" NAME type_params? '=' expression")); + expr_ty _keyword; + Token * _literal; + expr_ty b; + expr_ty n; + void *t; + if ( + (_keyword = _PyPegen_expect_soft_keyword(p, "type")) // soft_keyword='"type"' + && + (n = _PyPegen_name_token(p)) // NAME + && + (t = type_params_rule(p), !p->error_indicator) // type_params? + && + (_literal = _PyPegen_expect_token(p, 22)) // token='=' + && + (b = expression_rule(p)) // expression + ) + { + D(fprintf(stderr, "%*c+ type_alias[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"type\" NAME type_params? '=' expression")); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + p->level--; + return NULL; + } + int _end_lineno = _token->end_lineno; + 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 = CHECK_VERSION ( stmt_ty , 12 , "Type statement is" , _PyAST_TypeAlias ( CHECK ( expr_ty , _PyPegen_set_expr_context ( p , n , Store ) ) , t , b , EXTRA ) ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_alias[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\"type\" NAME type_params? '=' expression")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// type_params: '[' type_param_seq ']' +static asdl_type_param_seq* +type_params_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_type_param_seq* _res = NULL; + int _mark = p->mark; + { // '[' type_param_seq ']' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_params[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' type_param_seq ']'")); + Token * _literal; + Token * _literal_1; + asdl_type_param_seq* t; + if ( + (_literal = _PyPegen_expect_token(p, 9)) // token='[' + && + (t = type_param_seq_rule(p)) // type_param_seq + && + (_literal_1 = _PyPegen_expect_token(p, 10)) // token=']' + ) + { + D(fprintf(stderr, "%*c+ type_params[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' type_param_seq ']'")); + _res = CHECK_VERSION ( asdl_type_param_seq* , 12 , "Type parameter lists are" , t ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_params[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'[' type_param_seq ']'")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// type_param_seq: ','.type_param+ ','? +static asdl_type_param_seq* +type_param_seq_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_type_param_seq* _res = NULL; + int _mark = p->mark; + { // ','.type_param+ ','? + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.type_param+ ','?")); + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + asdl_type_param_seq* a; + if ( + (a = (asdl_type_param_seq*)_gather_81_rule(p)) // ','.type_param+ + && + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? + ) + { + D(fprintf(stderr, "%*c+ type_param_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.type_param+ ','?")); + _res = a; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param_seq[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.type_param+ ','?")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// type_param: +// | NAME type_param_bound? +// | '*' NAME ":" expression +// | '*' NAME +// | '**' NAME ":" expression +// | '**' NAME +static type_param_ty +type_param_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + type_param_ty _res = NULL; + if (_PyPegen_is_memoized(p, type_param_type, &_res)) { + p->level--; + return _res; + } + int _mark = p->mark; + if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) { + p->error_indicator = 1; + p->level--; + return NULL; + } + int _start_lineno = p->tokens[_mark]->lineno; + UNUSED(_start_lineno); // Only used by EXTRA macro + int _start_col_offset = p->tokens[_mark]->col_offset; + UNUSED(_start_col_offset); // Only used by EXTRA macro + { // NAME type_param_bound? + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME type_param_bound?")); + expr_ty a; + void *b; + if ( + (a = _PyPegen_name_token(p)) // NAME + && + (b = type_param_bound_rule(p), !p->error_indicator) // type_param_bound? + ) + { + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME type_param_bound?")); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + p->level--; + return NULL; + } + int _end_lineno = _token->end_lineno; + 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_TypeVar ( a -> v . Name . id , b , EXTRA ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME type_param_bound?")); + } + { // '*' NAME ":" expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' NAME \":\" expression")); + Token * _literal; + expr_ty a; + Token * colon; + expr_ty e; + if ( + (_literal = _PyPegen_expect_token(p, 16)) // token='*' + && + (a = _PyPegen_name_token(p)) // NAME + && + (colon = _PyPegen_expect_token(p, 11)) // token=':' + && + (e = expression_rule(p)) // expression + ) + { + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME \":\" expression")); + _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with TypeVarTuple" : "cannot use bound with TypeVarTuple" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME \":\" expression")); + } + { // '*' NAME + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' NAME")); + Token * _literal; + expr_ty a; + if ( + (_literal = _PyPegen_expect_token(p, 16)) // token='*' + && + (a = _PyPegen_name_token(p)) // NAME + ) + { + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' NAME")); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + p->level--; + return NULL; + } + int _end_lineno = _token->end_lineno; + 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_TypeVarTuple ( a -> v . Name . id , EXTRA ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' NAME")); + } + { // '**' NAME ":" expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' NAME \":\" expression")); + Token * _literal; + expr_ty a; + Token * colon; + expr_ty e; + if ( + (_literal = _PyPegen_expect_token(p, 35)) // token='**' + && + (a = _PyPegen_name_token(p)) // NAME + && + (colon = _PyPegen_expect_token(p, 11)) // token=':' + && + (e = expression_rule(p)) // expression + ) + { + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME \":\" expression")); + _res = RAISE_SYNTAX_ERROR_STARTING_FROM ( colon , e -> kind == Tuple_kind ? "cannot use constraints with ParamSpec" : "cannot use bound with ParamSpec" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' NAME \":\" expression")); + } + { // '**' NAME + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**' NAME")); + Token * _literal; + expr_ty a; + if ( + (_literal = _PyPegen_expect_token(p, 35)) // token='**' + && + (a = _PyPegen_name_token(p)) // NAME + ) + { + D(fprintf(stderr, "%*c+ type_param[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' NAME")); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + p->level--; + return NULL; + } + int _end_lineno = _token->end_lineno; + 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_ParamSpec ( a -> v . Name . id , EXTRA ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' NAME")); + } + _res = NULL; + done: + _PyPegen_insert_memo(p, _mark, type_param_type, _res); + p->level--; + return _res; +} + +// type_param_bound: ":" expression +static expr_ty +type_param_bound_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + expr_ty _res = NULL; + int _mark = p->mark; + { // ":" expression + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> type_param_bound[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\":\" expression")); + Token * _literal; + expr_ty e; + if ( + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + && + (e = expression_rule(p)) // expression + ) + { + D(fprintf(stderr, "%*c+ type_param_bound[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\":\" expression")); + _res = e; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s type_param_bound[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\":\" expression")); + } + _res = NULL; + done: + p->level--; + return _res; +} + // expressions: expression ((',' expression))+ ','? | expression ',' | expression static expr_ty expressions_rule(Parser *p) @@ -10566,7 +11046,7 @@ expressions_rule(Parser *p) if ( (a = expression_rule(p)) // expression && - (b = _loop1_81_rule(p)) // ((',' expression))+ + (b = _loop1_83_rule(p)) // ((',' expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -10957,7 +11437,7 @@ star_expressions_rule(Parser *p) if ( (a = star_expression_rule(p)) // star_expression && - (b = _loop1_82_rule(p)) // ((',' star_expression))+ + (b = _loop1_84_rule(p)) // ((',' star_expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11158,7 +11638,7 @@ star_named_expressions_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_83_rule(p)) // ','.star_named_expression+ + (a = (asdl_expr_seq*)_gather_85_rule(p)) // ','.star_named_expression+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11458,7 +11938,7 @@ disjunction_rule(Parser *p) if ( (a = conjunction_rule(p)) // conjunction && - (b = _loop1_85_rule(p)) // (('or' conjunction))+ + (b = _loop1_87_rule(p)) // (('or' conjunction))+ ) { D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -11547,7 +12027,7 @@ conjunction_rule(Parser *p) if ( (a = inversion_rule(p)) // inversion && - (b = _loop1_86_rule(p)) // (('and' inversion))+ + (b = _loop1_88_rule(p)) // (('and' inversion))+ ) { D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -11721,7 +12201,7 @@ comparison_rule(Parser *p) if ( (a = bitwise_or_rule(p)) // bitwise_or && - (b = _loop1_87_rule(p)) // compare_op_bitwise_or_pair+ + (b = _loop1_89_rule(p)) // compare_op_bitwise_or_pair+ ) { D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -12058,10 +12538,10 @@ noteq_bitwise_or_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); - void *_tmp_88_var; + void *_tmp_90_var; expr_ty a; if ( - (_tmp_88_var = _tmp_88_rule(p)) // '!=' + (_tmp_90_var = _tmp_90_rule(p)) // '!=' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -14096,7 +14576,7 @@ slices_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_89_rule(p)) // ','.(slice | starred_expression)+ + (a = (asdl_expr_seq*)_gather_91_rule(p)) // ','.(slice | starred_expression)+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -14169,7 +14649,7 @@ slice_rule(Parser *p) && (b = expression_rule(p), !p->error_indicator) // expression? && - (c = _tmp_91_rule(p), !p->error_indicator) // [':' expression?] + (c = _tmp_93_rule(p), !p->error_indicator) // [':' expression?] ) { D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -14383,7 +14863,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&(STRING | FSTRING_START) strings")); expr_ty strings_var; if ( - _PyPegen_lookahead(1, _tmp_92_rule, p) + _PyPegen_lookahead(1, _tmp_94_rule, p) && (strings_var = strings_rule(p)) // strings ) @@ -14421,15 +14901,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - void *_tmp_93_var; + void *_tmp_95_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 7) // token='(' && - (_tmp_93_var = _tmp_93_rule(p)) // tuple | group | genexp + (_tmp_95_var = _tmp_95_rule(p)) // tuple | group | genexp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - _res = _tmp_93_var; + _res = _tmp_95_var; goto done; } p->mark = _mark; @@ -14442,15 +14922,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - void *_tmp_94_var; + void *_tmp_96_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 9) // token='[' && - (_tmp_94_var = _tmp_94_rule(p)) // list | listcomp + (_tmp_96_var = _tmp_96_rule(p)) // list | listcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - _res = _tmp_94_var; + _res = _tmp_96_var; goto done; } p->mark = _mark; @@ -14463,15 +14943,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - void *_tmp_95_var; + void *_tmp_97_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 25) // token='{' && - (_tmp_95_var = _tmp_95_rule(p)) // dict | set | dictcomp | setcomp + (_tmp_97_var = _tmp_97_rule(p)) // dict | set | dictcomp | setcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - _res = _tmp_95_var; + _res = _tmp_97_var; goto done; } p->mark = _mark; @@ -14543,7 +15023,7 @@ group_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_96_rule(p)) // yield_expr | named_expression + (a = _tmp_98_rule(p)) // yield_expr | named_expression && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -14747,9 +15227,9 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_no_default_rule(p)) // lambda_slash_no_default && - (b = (asdl_arg_seq*)_loop0_97_rule(p)) // lambda_param_no_default* + (b = (asdl_arg_seq*)_loop0_99_rule(p)) // lambda_param_no_default* && - (c = _loop0_98_rule(p)) // lambda_param_with_default* + (c = _loop0_100_rule(p)) // lambda_param_with_default* && (d = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -14779,7 +15259,7 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_with_default_rule(p)) // lambda_slash_with_default && - (b = _loop0_99_rule(p)) // lambda_param_with_default* + (b = _loop0_101_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -14807,9 +15287,9 @@ lambda_parameters_rule(Parser *p) asdl_seq * b; void *c; if ( - (a = (asdl_arg_seq*)_loop1_100_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_102_rule(p)) // lambda_param_no_default+ && - (b = _loop0_101_rule(p)) // lambda_param_with_default* + (b = _loop0_103_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -14836,7 +15316,7 @@ lambda_parameters_rule(Parser *p) asdl_seq * a; void *b; if ( - (a = _loop1_102_rule(p)) // lambda_param_with_default+ + (a = _loop1_104_rule(p)) // lambda_param_with_default+ && (b = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -14910,7 +15390,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal_1; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_103_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_105_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -14939,7 +15419,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_104_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_106_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -14992,9 +15472,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_105_rule(p)) // lambda_param_no_default* + (a = _loop0_107_rule(p)) // lambda_param_no_default* && - (b = _loop1_106_rule(p)) // lambda_param_with_default+ + (b = _loop1_108_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15024,9 +15504,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_107_rule(p)) // lambda_param_no_default* + (a = _loop0_109_rule(p)) // lambda_param_no_default* && - (b = _loop1_108_rule(p)) // lambda_param_with_default+ + (b = _loop1_110_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15104,7 +15584,7 @@ lambda_star_etc_rule(Parser *p) && (a = lambda_param_no_default_rule(p)) // lambda_param_no_default && - (b = _loop0_109_rule(p)) // lambda_param_maybe_default* + (b = _loop0_111_rule(p)) // lambda_param_maybe_default* && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -15137,7 +15617,7 @@ lambda_star_etc_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _loop1_110_rule(p)) // lambda_param_maybe_default+ + (b = _loop1_112_rule(p)) // lambda_param_maybe_default+ && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -15647,7 +16127,7 @@ fstring_replacement_field_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (a = _tmp_111_rule(p)) // yield_expr | star_expressions + (a = _tmp_113_rule(p)) // yield_expr | star_expressions && (debug_expr = _PyPegen_expect_token(p, 22), !p->error_indicator) // "="? && @@ -15786,7 +16266,7 @@ fstring_full_format_spec_rule(Parser *p) if ( (colon = _PyPegen_expect_token(p, 11)) // token=':' && - (spec = _loop0_112_rule(p)) // fstring_format_spec* + (spec = _loop0_114_rule(p)) // fstring_format_spec* ) { D(fprintf(stderr, "%*c+ fstring_full_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' fstring_format_spec*")); @@ -15959,7 +16439,7 @@ strings_rule(Parser *p) D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((fstring | string))+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_loop1_113_rule(p)) // ((fstring | string))+ + (a = (asdl_expr_seq*)_loop1_115_rule(p)) // ((fstring | string))+ ) { D(fprintf(stderr, "%*c+ strings[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((fstring | string))+")); @@ -16094,7 +16574,7 @@ tuple_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_114_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] + (a = _tmp_116_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -16312,7 +16792,7 @@ double_starred_kvpairs_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_115_rule(p)) // ','.double_starred_kvpair+ + (a = _gather_117_rule(p)) // ','.double_starred_kvpair+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -16474,7 +16954,7 @@ for_if_clauses_rule(Parser *p) D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); asdl_comprehension_seq* a; if ( - (a = (asdl_comprehension_seq*)_loop1_117_rule(p)) // for_if_clause+ + (a = (asdl_comprehension_seq*)_loop1_119_rule(p)) // for_if_clause+ ) { D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); @@ -16539,7 +17019,7 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_118_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_120_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -16582,7 +17062,7 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_119_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_121_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -16845,7 +17325,7 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_120_rule(p)) // assignment_expression | expression !':=' + (a = _tmp_122_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && @@ -17097,9 +17577,9 @@ args_rule(Parser *p) asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_121_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + (a = (asdl_expr_seq*)_gather_123_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && - (b = _tmp_123_rule(p), !p->error_indicator) // [',' kwargs] + (b = _tmp_125_rule(p), !p->error_indicator) // [',' kwargs] ) { D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); @@ -17190,11 +17670,11 @@ kwargs_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _gather_124_rule(p)) // ','.kwarg_or_starred+ + (a = _gather_126_rule(p)) // ','.kwarg_or_starred+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _gather_126_rule(p)) // ','.kwarg_or_double_starred+ + (b = _gather_128_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -17216,13 +17696,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - asdl_seq * _gather_128_var; + asdl_seq * _gather_130_var; if ( - (_gather_128_var = _gather_128_rule(p)) // ','.kwarg_or_starred+ + (_gather_130_var = _gather_130_rule(p)) // ','.kwarg_or_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - _res = _gather_128_var; + _res = _gather_130_var; goto done; } p->mark = _mark; @@ -17235,13 +17715,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - asdl_seq * _gather_130_var; + asdl_seq * _gather_132_var; if ( - (_gather_130_var = _gather_130_rule(p)) // ','.kwarg_or_double_starred+ + (_gather_132_var = _gather_132_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - _res = _gather_130_var; + _res = _gather_132_var; goto done; } p->mark = _mark; @@ -17634,7 +18114,7 @@ star_targets_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop0_132_rule(p)) // ((',' star_target))* + (b = _loop0_134_rule(p)) // ((',' star_target))* && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -17691,7 +18171,7 @@ star_targets_list_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_133_rule(p)) // ','.star_target+ + (a = (asdl_expr_seq*)_gather_135_rule(p)) // ','.star_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -17742,7 +18222,7 @@ star_targets_tuple_seq_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop1_135_rule(p)) // ((',' star_target))+ + (b = _loop1_137_rule(p)) // ((',' star_target))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -17831,7 +18311,7 @@ star_target_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (a = _tmp_136_rule(p)) // !'*' star_target + (a = _tmp_138_rule(p)) // !'*' star_target ) { D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -18762,7 +19242,7 @@ del_targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_137_rule(p)) // ','.del_target+ + (a = (asdl_expr_seq*)_gather_139_rule(p)) // ','.del_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -19123,7 +19603,7 @@ type_expressions_rule(Parser *p) expr_ty b; expr_ty c; if ( - (a = _gather_139_rule(p)) // ','.expression+ + (a = _gather_141_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19162,7 +19642,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_141_rule(p)) // ','.expression+ + (a = _gather_143_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19195,7 +19675,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_143_rule(p)) // ','.expression+ + (a = _gather_145_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19315,7 +19795,7 @@ type_expressions_rule(Parser *p) D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_145_rule(p)) // ','.expression+ + (a = (asdl_expr_seq*)_gather_147_rule(p)) // ','.expression+ ) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -19367,7 +19847,7 @@ func_type_comment_rule(Parser *p) && (t = _PyPegen_expect_token(p, TYPE_COMMENT)) // token='TYPE_COMMENT' && - _PyPegen_lookahead(1, _tmp_147_rule, p) + _PyPegen_lookahead(1, _tmp_149_rule, p) ) { D(fprintf(stderr, "%*c+ func_type_comment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -19496,7 +19976,7 @@ invalid_arguments_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_148_rule(p), !p->error_indicator) // [args | expression for_if_clauses] + (_opt_var = _tmp_150_rule(p), !p->error_indicator) // [args | expression for_if_clauses] ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -19556,13 +20036,13 @@ invalid_arguments_rule(Parser *p) expr_ty a; Token * b; if ( - (_opt_var = _tmp_149_rule(p), !p->error_indicator) // [(args ',')] + (_opt_var = _tmp_151_rule(p), !p->error_indicator) // [(args ',')] && (a = _PyPegen_name_token(p)) // NAME && (b = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, _tmp_150_rule, p) + _PyPegen_lookahead(1, _tmp_152_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(args ',')] NAME '=' &(',' | ')')")); @@ -19701,7 +20181,7 @@ invalid_kwarg_rule(Parser *p) Token* a; Token * b; if ( - (a = (Token*)_tmp_151_rule(p)) // 'True' | 'False' | 'None' + (a = (Token*)_tmp_153_rule(p)) // 'True' | 'False' | 'None' && (b = _PyPegen_expect_token(p, 22)) // token='=' ) @@ -19761,7 +20241,7 @@ invalid_kwarg_rule(Parser *p) expr_ty a; Token * b; if ( - _PyPegen_lookahead(0, _tmp_152_rule, p) + _PyPegen_lookahead(0, _tmp_154_rule, p) && (a = expression_rule(p)) // expression && @@ -20020,7 +20500,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, _tmp_153_rule, p) + _PyPegen_lookahead(0, _tmp_155_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -20056,7 +20536,7 @@ invalid_expression_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, _tmp_154_rule, p) + _PyPegen_lookahead(0, _tmp_156_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -20089,7 +20569,7 @@ invalid_expression_rule(Parser *p) && (b = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_155_rule, p) + _PyPegen_lookahead(1, _tmp_157_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'lambda' lambda_params? ':' &(FSTRING_MIDDLE | fstring_replacement_field)")); @@ -20178,7 +20658,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_156_rule, p) + _PyPegen_lookahead(0, _tmp_158_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -20204,7 +20684,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, _tmp_157_rule, p) + _PyPegen_lookahead(0, _tmp_159_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -20212,7 +20692,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, _tmp_158_rule, p) + _PyPegen_lookahead(0, _tmp_160_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 !('=' | ':=')")); @@ -20293,7 +20773,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_159_var; + asdl_seq * _loop0_161_var; expr_ty a; expr_ty expression_var; if ( @@ -20301,7 +20781,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_159_var = _loop0_159_rule(p)) // star_named_expressions* + (_loop0_161_var = _loop0_161_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20358,10 +20838,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_160_var; + asdl_seq * _loop0_162_var; expr_ty a; if ( - (_loop0_160_var = _loop0_160_rule(p)) // ((star_targets '='))* + (_loop0_162_var = _loop0_162_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -20388,10 +20868,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_161_var; + asdl_seq * _loop0_163_var; expr_ty a; if ( - (_loop0_161_var = _loop0_161_rule(p)) // ((star_targets '='))* + (_loop0_163_var = _loop0_163_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -20417,7 +20897,7 @@ invalid_assignment_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_162_var; + void *_tmp_164_var; expr_ty a; AugOperator* augassign_var; if ( @@ -20425,7 +20905,7 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_162_var = _tmp_162_rule(p)) // yield_expr | star_expressions + (_tmp_164_var = _tmp_164_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -20651,11 +21131,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_163_var; + void *_tmp_165_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_163_var = _tmp_163_rule(p)) // '[' | '(' | '{' + (_tmp_165_var = _tmp_165_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -20682,12 +21162,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_164_var; + void *_tmp_166_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_164_var = _tmp_164_rule(p)) // '[' | '{' + (_tmp_166_var = _tmp_166_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -20717,12 +21197,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_165_var; + void *_tmp_167_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_165_var = _tmp_165_rule(p)) // '[' | '{' + (_tmp_167_var = _tmp_167_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -20859,13 +21339,13 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slash_no_default | slash_with_default) param_maybe_default* '/'")); - asdl_seq * _loop0_167_var; - void *_tmp_166_var; + asdl_seq * _loop0_169_var; + void *_tmp_168_var; Token * a; if ( - (_tmp_166_var = _tmp_166_rule(p)) // slash_no_default | slash_with_default + (_tmp_168_var = _tmp_168_rule(p)) // slash_no_default | slash_with_default && - (_loop0_167_var = _loop0_167_rule(p)) // param_maybe_default* + (_loop0_169_var = _loop0_169_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -20889,7 +21369,7 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default? param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_168_var; + asdl_seq * _loop0_170_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -20897,7 +21377,7 @@ invalid_parameters_rule(Parser *p) if ( (_opt_var = slash_no_default_rule(p), !p->error_indicator) // slash_no_default? && - (_loop0_168_var = _loop0_168_rule(p)) // param_no_default* + (_loop0_170_var = _loop0_170_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -20923,18 +21403,18 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); - asdl_seq * _loop0_169_var; - asdl_seq * _loop1_170_var; + asdl_seq * _loop0_171_var; + asdl_seq * _loop1_172_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_169_var = _loop0_169_rule(p)) // param_no_default* + (_loop0_171_var = _loop0_171_rule(p)) // param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_loop1_170_var = _loop1_170_rule(p)) // param_no_default+ + (_loop1_172_var = _loop1_172_rule(p)) // param_no_default+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -20961,22 +21441,22 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[(slash_no_default | slash_with_default)] param_maybe_default* '*' (',' | param_no_default) param_maybe_default* '/'")); Token * _literal; - asdl_seq * _loop0_172_var; asdl_seq * _loop0_174_var; + asdl_seq * _loop0_176_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_173_var; + void *_tmp_175_var; Token * a; if ( - (_opt_var = _tmp_171_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] + (_opt_var = _tmp_173_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] && - (_loop0_172_var = _loop0_172_rule(p)) // param_maybe_default* + (_loop0_174_var = _loop0_174_rule(p)) // param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_173_var = _tmp_173_rule(p)) // ',' | param_no_default + (_tmp_175_var = _tmp_175_rule(p)) // ',' | param_no_default && - (_loop0_174_var = _loop0_174_rule(p)) // param_maybe_default* + (_loop0_176_var = _loop0_176_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21001,10 +21481,10 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_175_var; + asdl_seq * _loop1_177_var; Token * a; if ( - (_loop1_175_var = _loop1_175_rule(p)) // param_maybe_default+ + (_loop1_177_var = _loop1_177_rule(p)) // param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -21054,7 +21534,7 @@ invalid_default_rule(Parser *p) if ( (a = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, _tmp_176_rule, p) + _PyPegen_lookahead(1, _tmp_178_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' &(')' | ',')")); @@ -21100,12 +21580,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_177_var; + void *_tmp_179_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_177_var = _tmp_177_rule(p)) // ')' | ',' (')' | '**') + (_tmp_179_var = _tmp_179_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -21188,20 +21668,20 @@ invalid_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_179_var; - void *_tmp_178_var; + asdl_seq * _loop0_181_var; void *_tmp_180_var; + void *_tmp_182_var; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_178_var = _tmp_178_rule(p)) // param_no_default | ',' + (_tmp_180_var = _tmp_180_rule(p)) // param_no_default | ',' && - (_loop0_179_var = _loop0_179_rule(p)) // param_maybe_default* + (_loop0_181_var = _loop0_181_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_180_var = _tmp_180_rule(p)) // param_no_default | ',' + (_tmp_182_var = _tmp_182_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 | ',')")); @@ -21317,7 +21797,7 @@ invalid_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_181_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_183_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' ('*' | '**' | '/')")); @@ -21383,13 +21863,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_182_var; + asdl_seq * _loop1_184_var; if ( - (_loop1_182_var = _loop1_182_rule(p)) // param_with_default+ + (_loop1_184_var = _loop1_184_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_182_var; + _res = _loop1_184_var; goto done; } p->mark = _mark; @@ -21455,13 +21935,13 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* '/'")); - asdl_seq * _loop0_184_var; - void *_tmp_183_var; + asdl_seq * _loop0_186_var; + void *_tmp_185_var; Token * a; if ( - (_tmp_183_var = _tmp_183_rule(p)) // lambda_slash_no_default | lambda_slash_with_default + (_tmp_185_var = _tmp_185_rule(p)) // lambda_slash_no_default | lambda_slash_with_default && - (_loop0_184_var = _loop0_184_rule(p)) // lambda_param_maybe_default* + (_loop0_186_var = _loop0_186_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21485,7 +21965,7 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_185_var; + asdl_seq * _loop0_187_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -21493,7 +21973,7 @@ invalid_lambda_parameters_rule(Parser *p) if ( (_opt_var = lambda_slash_no_default_rule(p), !p->error_indicator) // lambda_slash_no_default? && - (_loop0_185_var = _loop0_185_rule(p)) // lambda_param_no_default* + (_loop0_187_var = _loop0_187_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -21519,18 +21999,18 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); - asdl_seq * _gather_187_var; - asdl_seq * _loop0_186_var; + asdl_seq * _gather_189_var; + asdl_seq * _loop0_188_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_186_var = _loop0_186_rule(p)) // lambda_param_no_default* + (_loop0_188_var = _loop0_188_rule(p)) // lambda_param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_187_var = _gather_187_rule(p)) // ','.lambda_param+ + (_gather_189_var = _gather_189_rule(p)) // ','.lambda_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -21557,22 +22037,22 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[(lambda_slash_no_default | lambda_slash_with_default)] lambda_param_maybe_default* '*' (',' | lambda_param_no_default) lambda_param_maybe_default* '/'")); Token * _literal; - asdl_seq * _loop0_190_var; asdl_seq * _loop0_192_var; + asdl_seq * _loop0_194_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_191_var; + void *_tmp_193_var; Token * a; if ( - (_opt_var = _tmp_189_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] + (_opt_var = _tmp_191_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] && - (_loop0_190_var = _loop0_190_rule(p)) // lambda_param_maybe_default* + (_loop0_192_var = _loop0_192_rule(p)) // lambda_param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_191_var = _tmp_191_rule(p)) // ',' | lambda_param_no_default + (_tmp_193_var = _tmp_193_rule(p)) // ',' | lambda_param_no_default && - (_loop0_192_var = _loop0_192_rule(p)) // lambda_param_maybe_default* + (_loop0_194_var = _loop0_194_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21597,10 +22077,10 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_193_var; + asdl_seq * _loop1_195_var; Token * a; if ( - (_loop1_193_var = _loop1_193_rule(p)) // lambda_param_maybe_default+ + (_loop1_195_var = _loop1_195_rule(p)) // lambda_param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -21672,13 +22152,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_194_var; + asdl_seq * _loop1_196_var; if ( - (_loop1_194_var = _loop1_194_rule(p)) // lambda_param_with_default+ + (_loop1_196_var = _loop1_196_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_194_var; + _res = _loop1_196_var; goto done; } p->mark = _mark; @@ -21715,11 +22195,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_195_var; + void *_tmp_197_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_195_var = _tmp_195_rule(p)) // ':' | ',' (':' | '**') + (_tmp_197_var = _tmp_197_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -21772,20 +22252,20 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_197_var; - void *_tmp_196_var; + asdl_seq * _loop0_199_var; void *_tmp_198_var; + void *_tmp_200_var; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_196_var = _tmp_196_rule(p)) // lambda_param_no_default | ',' + (_tmp_198_var = _tmp_198_rule(p)) // lambda_param_no_default | ',' && - (_loop0_197_var = _loop0_197_rule(p)) // lambda_param_maybe_default* + (_loop0_199_var = _loop0_199_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_198_var = _tmp_198_rule(p)) // lambda_param_no_default | ',' + (_tmp_200_var = _tmp_200_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 | ',')")); @@ -21904,7 +22384,7 @@ invalid_lambda_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_199_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_201_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' ('*' | '**' | '/')")); @@ -22012,7 +22492,7 @@ invalid_with_item_rule(Parser *p) && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, _tmp_200_rule, p) + _PyPegen_lookahead(1, _tmp_202_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -22293,7 +22773,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_201_var; + asdl_seq * _gather_203_var; Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22303,7 +22783,7 @@ invalid_with_stmt_rule(Parser *p) && (_keyword = _PyPegen_expect_token(p, 615)) // token='with' && - (_gather_201_var = _gather_201_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_203_var = _gather_203_rule(p)) // ','.(expression ['as' star_target])+ && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -22327,7 +22807,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_203_var; + asdl_seq * _gather_205_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -22343,7 +22823,7 @@ invalid_with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_203_var = _gather_203_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_205_var = _gather_205_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22393,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' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_205_var; + asdl_seq * _gather_207_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22404,7 +22884,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (a = _PyPegen_expect_token(p, 615)) // token='with' && - (_gather_205_var = _gather_205_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_207_var = _gather_207_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -22432,7 +22912,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "ASYNC? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_207_var; + asdl_seq * _gather_209_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -22449,7 +22929,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_207_var = _gather_207_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_209_var = _gather_209_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22547,7 +23027,7 @@ invalid_try_stmt_rule(Parser *p) && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, _tmp_209_rule, p) + _PyPegen_lookahead(0, _tmp_211_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -22572,8 +23052,8 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_210_var; - asdl_seq * _loop1_211_var; + asdl_seq * _loop0_212_var; + asdl_seq * _loop1_213_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; @@ -22584,9 +23064,9 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_210_var = _loop0_210_rule(p)) // block* + (_loop0_212_var = _loop0_212_rule(p)) // block* && - (_loop1_211_var = _loop1_211_rule(p)) // except_block+ + (_loop1_213_var = _loop1_213_rule(p)) // except_block+ && (a = _PyPegen_expect_token(p, 637)) // token='except' && @@ -22594,7 +23074,7 @@ invalid_try_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_212_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_214_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -22621,8 +23101,8 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_213_var; - asdl_seq * _loop1_214_var; + asdl_seq * _loop0_215_var; + asdl_seq * _loop1_216_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; @@ -22631,13 +23111,13 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_213_var = _loop0_213_rule(p)) // block* + (_loop0_215_var = _loop0_215_rule(p)) // block* && - (_loop1_214_var = _loop1_214_rule(p)) // except_star_block+ + (_loop1_216_var = _loop1_216_rule(p)) // except_star_block+ && (a = _PyPegen_expect_token(p, 637)) // token='except' && - (_opt_var = _tmp_215_rule(p), !p->error_indicator) // [expression ['as' NAME]] + (_opt_var = _tmp_217_rule(p), !p->error_indicator) // [expression ['as' NAME]] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -22705,7 +23185,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var_1 = _tmp_216_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_218_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -22743,7 +23223,7 @@ invalid_except_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var_1 = _tmp_217_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var_1 = _tmp_219_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -22795,14 +23275,14 @@ invalid_except_stmt_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_except_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); Token * _literal; - void *_tmp_218_var; + void *_tmp_220_var; Token * a; if ( (a = _PyPegen_expect_token(p, 637)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_218_var = _tmp_218_rule(p)) // NEWLINE | ':' + (_tmp_220_var = _tmp_220_rule(p)) // NEWLINE | ':' ) { D(fprintf(stderr, "%*c+ invalid_except_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); @@ -22909,7 +23389,7 @@ invalid_except_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_219_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_221_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23004,7 +23484,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_220_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_222_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23373,7 +23853,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_221_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_223_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -23867,7 +24347,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_2 = _tmp_222_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_2 = _tmp_224_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23927,7 +24407,7 @@ invalid_class_def_raw_rule(Parser *p) && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_223_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = _tmp_225_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -23962,7 +24442,7 @@ invalid_class_def_raw_rule(Parser *p) && (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _tmp_224_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var = _tmp_226_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24013,11 +24493,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_225_var; + asdl_seq * _gather_227_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_225_var = _gather_225_rule(p)) // ','.double_starred_kvpair+ + (_gather_227_var = _gather_227_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -24025,7 +24505,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_225_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_227_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -24078,7 +24558,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_227_rule, p) + _PyPegen_lookahead(1, _tmp_229_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -24189,7 +24669,7 @@ invalid_kvpair_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, _tmp_228_rule, p) + _PyPegen_lookahead(1, _tmp_230_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -24407,7 +24887,7 @@ invalid_replacement_field_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - _PyPegen_lookahead(0, _tmp_229_rule, p) + _PyPegen_lookahead(0, _tmp_231_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' !(yield_expr | star_expressions)")); @@ -24430,13 +24910,13 @@ invalid_replacement_field_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')")); Token * _literal; - void *_tmp_230_var; + void *_tmp_232_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_230_var = _tmp_230_rule(p)) // yield_expr | star_expressions + (_tmp_232_var = _tmp_232_rule(p)) // yield_expr | star_expressions && - _PyPegen_lookahead(0, _tmp_231_rule, p) + _PyPegen_lookahead(0, _tmp_233_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}')")); @@ -24460,15 +24940,15 @@ invalid_replacement_field_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')")); Token * _literal; Token * _literal_1; - void *_tmp_232_var; + void *_tmp_234_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_232_var = _tmp_232_rule(p)) // yield_expr | star_expressions + (_tmp_234_var = _tmp_234_rule(p)) // yield_expr | star_expressions && (_literal_1 = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(0, _tmp_233_rule, p) + _PyPegen_lookahead(0, _tmp_235_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '=' !('!' | ':' | '}')")); @@ -24493,12 +24973,12 @@ invalid_replacement_field_rule(Parser *p) Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_234_var; + void *_tmp_236_var; void *invalid_conversion_character_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_234_var = _tmp_234_rule(p)) // yield_expr | star_expressions + (_tmp_236_var = _tmp_236_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && @@ -24506,7 +24986,7 @@ invalid_replacement_field_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? invalid_conversion_character")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_234_var, _opt_var, invalid_conversion_character_var); + _res = _PyPegen_dummy_name(p, _literal, _tmp_236_var, _opt_var, invalid_conversion_character_var); goto done; } p->mark = _mark; @@ -24524,17 +25004,17 @@ invalid_replacement_field_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_235_var; + void *_tmp_237_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_235_var = _tmp_235_rule(p)) // yield_expr | star_expressions + (_tmp_237_var = _tmp_237_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_236_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_238_rule(p), !p->error_indicator) // ['!' NAME] && - _PyPegen_lookahead(0, _tmp_237_rule, p) + _PyPegen_lookahead(0, _tmp_239_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}')")); @@ -24558,24 +25038,24 @@ invalid_replacement_field_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}'")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_240_var; + asdl_seq * _loop0_242_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_238_var; + void *_tmp_240_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_238_var = _tmp_238_rule(p)) // yield_expr | star_expressions + (_tmp_240_var = _tmp_240_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_239_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_241_rule(p), !p->error_indicator) // ['!' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_240_var = _loop0_240_rule(p)) // fstring_format_spec* + (_loop0_242_var = _loop0_242_rule(p)) // fstring_format_spec* && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) @@ -24604,15 +25084,15 @@ invalid_replacement_field_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; UNUSED(_opt_var_1); // Silence compiler warnings - void *_tmp_241_var; + void *_tmp_243_var; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' && - (_tmp_241_var = _tmp_241_rule(p)) // yield_expr | star_expressions + (_tmp_243_var = _tmp_243_rule(p)) // yield_expr | star_expressions && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_242_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_244_rule(p), !p->error_indicator) // ['!' NAME] && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) @@ -24660,7 +25140,7 @@ invalid_conversion_character_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' && - _PyPegen_lookahead(1, _tmp_243_rule, p) + _PyPegen_lookahead(1, _tmp_245_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); @@ -25605,12 +26085,12 @@ _loop1_15_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_244_var; + void *_tmp_246_var; while ( - (_tmp_244_var = _tmp_244_rule(p)) // star_targets '=' + (_tmp_246_var = _tmp_246_rule(p)) // star_targets '=' ) { - _res = _tmp_244_var; + _res = _tmp_246_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26184,12 +26664,12 @@ _loop0_25_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_245_var; + void *_tmp_247_var; while ( - (_tmp_245_var = _tmp_245_rule(p)) // '.' | '...' + (_tmp_247_var = _tmp_247_rule(p)) // '.' | '...' ) { - _res = _tmp_245_var; + _res = _tmp_247_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26252,12 +26732,12 @@ _loop1_26_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_246_var; + void *_tmp_248_var; while ( - (_tmp_246_var = _tmp_246_rule(p)) // '.' | '...' + (_tmp_248_var = _tmp_248_rule(p)) // '.' | '...' ) { - _res = _tmp_246_var; + _res = _tmp_248_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26657,12 +27137,12 @@ _loop1_33_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_247_var; + void *_tmp_249_var; while ( - (_tmp_247_var = _tmp_247_rule(p)) // '@' named_expression NEWLINE + (_tmp_249_var = _tmp_249_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_247_var; + _res = _tmp_249_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29511,8 +29991,127 @@ _loop0_78_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_78[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' pattern")); + D(fprintf(stderr, "%*c%s _loop0_78[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' pattern")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _gather_77: pattern _loop0_78 +static asdl_seq * +_gather_77_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // pattern _loop0_78 + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _gather_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_78")); + pattern_ty elem; + asdl_seq * seq; + if ( + (elem = pattern_rule(p)) // pattern + && + (seq = _loop0_78_rule(p)) // _loop0_78 + ) + { + D(fprintf(stderr, "%*c+ _gather_77[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_78")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _gather_77[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_78")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _loop0_80: ',' keyword_pattern +static asdl_seq * +_loop0_80_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + 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; + { // ',' keyword_pattern + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); + Token * _literal; + KeyPatternPair* elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = keyword_pattern_rule(p)) // keyword_pattern + ) + { + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_80[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' keyword_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -29528,9 +30127,9 @@ _loop0_78_rule(Parser *p) return _seq; } -// _gather_77: pattern _loop0_78 +// _gather_79: keyword_pattern _loop0_80 static asdl_seq * -_gather_77_rule(Parser *p) +_gather_79_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29542,27 +30141,27 @@ _gather_77_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // pattern _loop0_78 + { // keyword_pattern _loop0_80 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_78")); - pattern_ty elem; + D(fprintf(stderr, "%*c> _gather_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_80")); + KeyPatternPair* elem; asdl_seq * seq; if ( - (elem = pattern_rule(p)) // pattern + (elem = keyword_pattern_rule(p)) // keyword_pattern && - (seq = _loop0_78_rule(p)) // _loop0_78 + (seq = _loop0_80_rule(p)) // _loop0_80 ) { - D(fprintf(stderr, "%*c+ _gather_77[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_78")); + D(fprintf(stderr, "%*c+ _gather_79[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_80")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_77[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_78")); + D(fprintf(stderr, "%*c%s _gather_79[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_80")); } _res = NULL; done: @@ -29570,9 +30169,9 @@ _gather_77_rule(Parser *p) return _res; } -// _loop0_80: ',' keyword_pattern +// _loop0_82: ',' type_param static asdl_seq * -_loop0_80_rule(Parser *p) +_loop0_82_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29593,18 +30192,18 @@ _loop0_80_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' keyword_pattern + { // ',' type_param if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); + D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' type_param")); Token * _literal; - KeyPatternPair* elem; + type_param_ty elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = keyword_pattern_rule(p)) // keyword_pattern + (elem = type_param_rule(p)) // type_param ) { _res = elem; @@ -29630,8 +30229,8 @@ _loop0_80_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_80[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' keyword_pattern")); + D(fprintf(stderr, "%*c%s _loop0_82[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' type_param")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -29647,9 +30246,9 @@ _loop0_80_rule(Parser *p) return _seq; } -// _gather_79: keyword_pattern _loop0_80 +// _gather_81: type_param _loop0_82 static asdl_seq * -_gather_79_rule(Parser *p) +_gather_81_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29661,27 +30260,27 @@ _gather_79_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // keyword_pattern _loop0_80 + { // type_param _loop0_82 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_80")); - KeyPatternPair* elem; + D(fprintf(stderr, "%*c> _gather_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "type_param _loop0_82")); + type_param_ty elem; asdl_seq * seq; if ( - (elem = keyword_pattern_rule(p)) // keyword_pattern + (elem = type_param_rule(p)) // type_param && - (seq = _loop0_80_rule(p)) // _loop0_80 + (seq = _loop0_82_rule(p)) // _loop0_82 ) { - D(fprintf(stderr, "%*c+ _gather_79[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_80")); + D(fprintf(stderr, "%*c+ _gather_81[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "type_param _loop0_82")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_79[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_80")); + D(fprintf(stderr, "%*c%s _gather_81[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "type_param _loop0_82")); } _res = NULL; done: @@ -29689,9 +30288,9 @@ _gather_79_rule(Parser *p) return _res; } -// _loop1_81: (',' expression) +// _loop1_83: (',' expression) static asdl_seq * -_loop1_81_rule(Parser *p) +_loop1_83_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29717,13 +30316,13 @@ _loop1_81_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_248_var; + D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); + void *_tmp_250_var; while ( - (_tmp_248_var = _tmp_248_rule(p)) // ',' expression + (_tmp_250_var = _tmp_250_rule(p)) // ',' expression ) { - _res = _tmp_248_var; + _res = _tmp_250_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29740,7 +30339,7 @@ _loop1_81_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_81[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' expression)")); } if (_n == 0 || p->error_indicator) { @@ -29762,9 +30361,9 @@ _loop1_81_rule(Parser *p) return _seq; } -// _loop1_82: (',' star_expression) +// _loop1_84: (',' star_expression) static asdl_seq * -_loop1_82_rule(Parser *p) +_loop1_84_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29790,13 +30389,13 @@ _loop1_82_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_249_var; + D(fprintf(stderr, "%*c> _loop1_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); + void *_tmp_251_var; while ( - (_tmp_249_var = _tmp_249_rule(p)) // ',' star_expression + (_tmp_251_var = _tmp_251_rule(p)) // ',' star_expression ) { - _res = _tmp_249_var; + _res = _tmp_251_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29813,7 +30412,7 @@ _loop1_82_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_82[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_84[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_expression)")); } if (_n == 0 || p->error_indicator) { @@ -29835,9 +30434,9 @@ _loop1_82_rule(Parser *p) return _seq; } -// _loop0_84: ',' star_named_expression +// _loop0_86: ',' star_named_expression static asdl_seq * -_loop0_84_rule(Parser *p) +_loop0_86_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29863,7 +30462,7 @@ _loop0_84_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); + D(fprintf(stderr, "%*c> _loop0_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); Token * _literal; expr_ty elem; while ( @@ -29895,7 +30494,7 @@ _loop0_84_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_84[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_86[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_named_expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -29912,9 +30511,9 @@ _loop0_84_rule(Parser *p) return _seq; } -// _gather_83: star_named_expression _loop0_84 +// _gather_85: star_named_expression _loop0_86 static asdl_seq * -_gather_83_rule(Parser *p) +_gather_85_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29926,27 +30525,27 @@ _gather_83_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_named_expression _loop0_84 + { // star_named_expression _loop0_86 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_84")); + D(fprintf(stderr, "%*c> _gather_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_86")); expr_ty elem; asdl_seq * seq; if ( (elem = star_named_expression_rule(p)) // star_named_expression && - (seq = _loop0_84_rule(p)) // _loop0_84 + (seq = _loop0_86_rule(p)) // _loop0_86 ) { - D(fprintf(stderr, "%*c+ _gather_83[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_84")); + D(fprintf(stderr, "%*c+ _gather_85[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_86")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_83[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_84")); + D(fprintf(stderr, "%*c%s _gather_85[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_86")); } _res = NULL; done: @@ -29954,9 +30553,9 @@ _gather_83_rule(Parser *p) return _res; } -// _loop1_85: ('or' conjunction) +// _loop1_87: ('or' conjunction) static asdl_seq * -_loop1_85_rule(Parser *p) +_loop1_87_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -29982,13 +30581,13 @@ _loop1_85_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_250_var; + D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); + void *_tmp_252_var; while ( - (_tmp_250_var = _tmp_250_rule(p)) // 'or' conjunction + (_tmp_252_var = _tmp_252_rule(p)) // 'or' conjunction ) { - _res = _tmp_250_var; + _res = _tmp_252_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30005,7 +30604,7 @@ _loop1_85_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_85[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_87[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('or' conjunction)")); } if (_n == 0 || p->error_indicator) { @@ -30027,9 +30626,9 @@ _loop1_85_rule(Parser *p) return _seq; } -// _loop1_86: ('and' inversion) +// _loop1_88: ('and' inversion) static asdl_seq * -_loop1_86_rule(Parser *p) +_loop1_88_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30055,13 +30654,13 @@ _loop1_86_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_251_var; + D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); + void *_tmp_253_var; while ( - (_tmp_251_var = _tmp_251_rule(p)) // 'and' inversion + (_tmp_253_var = _tmp_253_rule(p)) // 'and' inversion ) { - _res = _tmp_251_var; + _res = _tmp_253_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30078,7 +30677,7 @@ _loop1_86_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_86[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_88[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('and' inversion)")); } if (_n == 0 || p->error_indicator) { @@ -30100,9 +30699,9 @@ _loop1_86_rule(Parser *p) return _seq; } -// _loop1_87: compare_op_bitwise_or_pair +// _loop1_89: compare_op_bitwise_or_pair static asdl_seq * -_loop1_87_rule(Parser *p) +_loop1_89_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30128,7 +30727,7 @@ _loop1_87_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); + D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); CmpopExprPair* compare_op_bitwise_or_pair_var; while ( (compare_op_bitwise_or_pair_var = compare_op_bitwise_or_pair_rule(p)) // compare_op_bitwise_or_pair @@ -30151,7 +30750,7 @@ _loop1_87_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_87[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_89[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "compare_op_bitwise_or_pair")); } if (_n == 0 || p->error_indicator) { @@ -30173,9 +30772,9 @@ _loop1_87_rule(Parser *p) return _seq; } -// _tmp_88: '!=' +// _tmp_90: '!=' static void * -_tmp_88_rule(Parser *p) +_tmp_90_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30192,13 +30791,13 @@ _tmp_88_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); + D(fprintf(stderr, "%*c> _tmp_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); Token * tok; if ( (tok = _PyPegen_expect_token(p, 28)) // token='!=' ) { - D(fprintf(stderr, "%*c+ _tmp_88[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); + D(fprintf(stderr, "%*c+ _tmp_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -30208,7 +30807,7 @@ _tmp_88_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_88[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_90[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!='")); } _res = NULL; @@ -30217,9 +30816,9 @@ _tmp_88_rule(Parser *p) return _res; } -// _loop0_90: ',' (slice | starred_expression) +// _loop0_92: ',' (slice | starred_expression) static asdl_seq * -_loop0_90_rule(Parser *p) +_loop0_92_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30245,13 +30844,13 @@ _loop0_90_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (slice | starred_expression)")); + D(fprintf(stderr, "%*c> _loop0_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (slice | starred_expression)")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_252_rule(p)) // slice | starred_expression + (elem = _tmp_254_rule(p)) // slice | starred_expression ) { _res = elem; @@ -30277,7 +30876,7 @@ _loop0_90_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_90[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_92[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (slice | starred_expression)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30294,9 +30893,9 @@ _loop0_90_rule(Parser *p) return _seq; } -// _gather_89: (slice | starred_expression) _loop0_90 +// _gather_91: (slice | starred_expression) _loop0_92 static asdl_seq * -_gather_89_rule(Parser *p) +_gather_91_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30308,27 +30907,27 @@ _gather_89_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (slice | starred_expression) _loop0_90 + { // (slice | starred_expression) _loop0_92 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_90")); + D(fprintf(stderr, "%*c> _gather_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_92")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_252_rule(p)) // slice | starred_expression + (elem = _tmp_254_rule(p)) // slice | starred_expression && - (seq = _loop0_90_rule(p)) // _loop0_90 + (seq = _loop0_92_rule(p)) // _loop0_92 ) { - D(fprintf(stderr, "%*c+ _gather_89[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_90")); + D(fprintf(stderr, "%*c+ _gather_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_92")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_89[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(slice | starred_expression) _loop0_90")); + D(fprintf(stderr, "%*c%s _gather_91[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(slice | starred_expression) _loop0_92")); } _res = NULL; done: @@ -30336,9 +30935,9 @@ _gather_89_rule(Parser *p) return _res; } -// _tmp_91: ':' expression? +// _tmp_93: ':' expression? static void * -_tmp_91_rule(Parser *p) +_tmp_93_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30355,7 +30954,7 @@ _tmp_91_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); + D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); Token * _literal; void *d; if ( @@ -30364,7 +30963,7 @@ _tmp_91_rule(Parser *p) (d = expression_rule(p), !p->error_indicator) // expression? ) { - D(fprintf(stderr, "%*c+ _tmp_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); + D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -30374,7 +30973,7 @@ _tmp_91_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_91[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression?")); } _res = NULL; @@ -30383,9 +30982,9 @@ _tmp_91_rule(Parser *p) return _res; } -// _tmp_92: STRING | FSTRING_START +// _tmp_94: STRING | FSTRING_START static void * -_tmp_92_rule(Parser *p) +_tmp_94_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30402,18 +31001,18 @@ _tmp_92_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); + D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); expr_ty string_var; if ( (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING")); + D(fprintf(stderr, "%*c+ _tmp_94[%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_92[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "STRING")); } { // FSTRING_START @@ -30421,18 +31020,18 @@ _tmp_92_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); + D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); Token * fstring_start_var; if ( (fstring_start_var = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' ) { - D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); + D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); _res = fstring_start_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_92[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_START")); } _res = NULL; @@ -30441,9 +31040,9 @@ _tmp_92_rule(Parser *p) return _res; } -// _tmp_93: tuple | group | genexp +// _tmp_95: tuple | group | genexp static void * -_tmp_93_rule(Parser *p) +_tmp_95_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30460,18 +31059,18 @@ _tmp_93_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c> _tmp_95[%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_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_95[%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_93[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } { // group @@ -30479,18 +31078,18 @@ _tmp_93_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); + D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); expr_ty group_var; if ( (group_var = group_rule(p)) // group ) { - D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); + D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); _res = group_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "group")); } { // genexp @@ -30498,18 +31097,18 @@ _tmp_93_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c> _tmp_95[%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_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_95[%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_93[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } _res = NULL; @@ -30518,9 +31117,9 @@ _tmp_93_rule(Parser *p) return _res; } -// _tmp_94: list | listcomp +// _tmp_96: list | listcomp static void * -_tmp_94_rule(Parser *p) +_tmp_96_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30537,18 +31136,18 @@ _tmp_94_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c> _tmp_96[%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_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_96[%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_94[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } { // listcomp @@ -30556,18 +31155,18 @@ _tmp_94_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); + D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); expr_ty listcomp_var; if ( (listcomp_var = listcomp_rule(p)) // listcomp ) { - D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); + D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); _res = listcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "listcomp")); } _res = NULL; @@ -30576,9 +31175,9 @@ _tmp_94_rule(Parser *p) return _res; } -// _tmp_95: dict | set | dictcomp | setcomp +// _tmp_97: dict | set | dictcomp | setcomp static void * -_tmp_95_rule(Parser *p) +_tmp_97_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30595,18 +31194,18 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); + D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); expr_ty dict_var; if ( (dict_var = dict_rule(p)) // dict ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); + D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); _res = dict_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dict")); } { // set @@ -30614,18 +31213,18 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); + D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); expr_ty set_var; if ( (set_var = set_rule(p)) // set ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); + D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); _res = set_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "set")); } { // dictcomp @@ -30633,18 +31232,18 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); + D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); expr_ty dictcomp_var; if ( (dictcomp_var = dictcomp_rule(p)) // dictcomp ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); + D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); _res = dictcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dictcomp")); } { // setcomp @@ -30652,18 +31251,18 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); + D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); expr_ty setcomp_var; if ( (setcomp_var = setcomp_rule(p)) // setcomp ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); + D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); _res = setcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "setcomp")); } _res = NULL; @@ -30672,9 +31271,9 @@ _tmp_95_rule(Parser *p) return _res; } -// _tmp_96: yield_expr | named_expression +// _tmp_98: yield_expr | named_expression static void * -_tmp_96_rule(Parser *p) +_tmp_98_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30691,18 +31290,18 @@ _tmp_96_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_98[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_98[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // named_expression @@ -30710,18 +31309,18 @@ _tmp_96_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); + D(fprintf(stderr, "%*c> _tmp_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); expr_ty named_expression_var; if ( (named_expression_var = named_expression_rule(p)) // named_expression ) { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); + D(fprintf(stderr, "%*c+ _tmp_98[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); _res = named_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_98[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression")); } _res = NULL; @@ -30730,9 +31329,9 @@ _tmp_96_rule(Parser *p) return _res; } -// _loop0_97: lambda_param_no_default +// _loop0_99: lambda_param_no_default static asdl_seq * -_loop0_97_rule(Parser *p) +_loop0_99_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30758,7 +31357,7 @@ _loop0_97_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -30781,7 +31380,7 @@ _loop0_97_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_97[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_99[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30798,9 +31397,9 @@ _loop0_97_rule(Parser *p) return _seq; } -// _loop0_98: lambda_param_with_default +// _loop0_100: lambda_param_with_default static asdl_seq * -_loop0_98_rule(Parser *p) +_loop0_100_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30826,7 +31425,7 @@ _loop0_98_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -30849,7 +31448,7 @@ _loop0_98_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_98[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_100[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30866,9 +31465,9 @@ _loop0_98_rule(Parser *p) return _seq; } -// _loop0_99: lambda_param_with_default +// _loop0_101: lambda_param_with_default static asdl_seq * -_loop0_99_rule(Parser *p) +_loop0_101_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30894,7 +31493,7 @@ _loop0_99_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -30917,7 +31516,7 @@ _loop0_99_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_99[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_101[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -30934,9 +31533,9 @@ _loop0_99_rule(Parser *p) return _seq; } -// _loop1_100: lambda_param_no_default +// _loop1_102: lambda_param_no_default static asdl_seq * -_loop1_100_rule(Parser *p) +_loop1_102_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -30962,7 +31561,7 @@ _loop1_100_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -30985,7 +31584,7 @@ _loop1_100_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_100[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_102[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -31007,9 +31606,9 @@ _loop1_100_rule(Parser *p) return _seq; } -// _loop0_101: lambda_param_with_default +// _loop0_103: lambda_param_with_default static asdl_seq * -_loop0_101_rule(Parser *p) +_loop0_103_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31035,7 +31634,7 @@ _loop0_101_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop0_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31058,7 +31657,7 @@ _loop0_101_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_101[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_103[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31075,9 +31674,9 @@ _loop0_101_rule(Parser *p) return _seq; } -// _loop1_102: lambda_param_with_default +// _loop1_104: lambda_param_with_default static asdl_seq * -_loop1_102_rule(Parser *p) +_loop1_104_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31103,7 +31702,7 @@ _loop1_102_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31126,7 +31725,7 @@ _loop1_102_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_102[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_104[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -31148,9 +31747,9 @@ _loop1_102_rule(Parser *p) return _seq; } -// _loop1_103: lambda_param_no_default +// _loop1_105: lambda_param_no_default static asdl_seq * -_loop1_103_rule(Parser *p) +_loop1_105_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31176,7 +31775,7 @@ _loop1_103_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31199,7 +31798,7 @@ _loop1_103_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_103[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_105[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -31221,9 +31820,9 @@ _loop1_103_rule(Parser *p) return _seq; } -// _loop1_104: lambda_param_no_default +// _loop1_106: lambda_param_no_default static asdl_seq * -_loop1_104_rule(Parser *p) +_loop1_106_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31249,7 +31848,7 @@ _loop1_104_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop1_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31272,7 +31871,7 @@ _loop1_104_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_104[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_106[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -31294,9 +31893,9 @@ _loop1_104_rule(Parser *p) return _seq; } -// _loop0_105: lambda_param_no_default +// _loop0_107: lambda_param_no_default static asdl_seq * -_loop0_105_rule(Parser *p) +_loop0_107_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31322,7 +31921,7 @@ _loop0_105_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31345,7 +31944,7 @@ _loop0_105_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_105[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_107[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31362,9 +31961,9 @@ _loop0_105_rule(Parser *p) return _seq; } -// _loop1_106: lambda_param_with_default +// _loop1_108: lambda_param_with_default static asdl_seq * -_loop1_106_rule(Parser *p) +_loop1_108_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31390,7 +31989,7 @@ _loop1_106_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31413,7 +32012,7 @@ _loop1_106_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_106[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_108[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -31435,9 +32034,9 @@ _loop1_106_rule(Parser *p) return _seq; } -// _loop0_107: lambda_param_no_default +// _loop0_109: lambda_param_no_default static asdl_seq * -_loop0_107_rule(Parser *p) +_loop0_109_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31463,7 +32062,7 @@ _loop0_107_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -31486,7 +32085,7 @@ _loop0_107_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_107[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_109[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31503,9 +32102,9 @@ _loop0_107_rule(Parser *p) return _seq; } -// _loop1_108: lambda_param_with_default +// _loop1_110: lambda_param_with_default static asdl_seq * -_loop1_108_rule(Parser *p) +_loop1_110_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31531,7 +32130,7 @@ _loop1_108_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -31554,7 +32153,7 @@ _loop1_108_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_108[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_110[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -31576,9 +32175,9 @@ _loop1_108_rule(Parser *p) return _seq; } -// _loop0_109: lambda_param_maybe_default +// _loop0_111: lambda_param_maybe_default static asdl_seq * -_loop0_109_rule(Parser *p) +_loop0_111_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31604,7 +32203,7 @@ _loop0_109_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -31627,7 +32226,7 @@ _loop0_109_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_109[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_111[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31644,9 +32243,9 @@ _loop0_109_rule(Parser *p) return _seq; } -// _loop1_110: lambda_param_maybe_default +// _loop1_112: lambda_param_maybe_default static asdl_seq * -_loop1_110_rule(Parser *p) +_loop1_112_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31672,7 +32271,7 @@ _loop1_110_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -31695,7 +32294,7 @@ _loop1_110_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_110[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -31717,9 +32316,9 @@ _loop1_110_rule(Parser *p) return _seq; } -// _tmp_111: yield_expr | star_expressions +// _tmp_113: yield_expr | star_expressions static void * -_tmp_111_rule(Parser *p) +_tmp_113_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31736,18 +32335,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, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_111[%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, "yield_expr")); } { // star_expressions @@ -31755,18 +32354,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, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_111[%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, "star_expressions")); } _res = NULL; @@ -31775,9 +32374,9 @@ _tmp_111_rule(Parser *p) return _res; } -// _loop0_112: fstring_format_spec +// _loop0_114: fstring_format_spec static asdl_seq * -_loop0_112_rule(Parser *p) +_loop0_114_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31803,7 +32402,7 @@ _loop0_112_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); + D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); expr_ty fstring_format_spec_var; while ( (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec @@ -31826,7 +32425,7 @@ _loop0_112_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_112[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -31843,9 +32442,9 @@ _loop0_112_rule(Parser *p) return _seq; } -// _loop1_113: (fstring | string) +// _loop1_115: (fstring | string) static asdl_seq * -_loop1_113_rule(Parser *p) +_loop1_115_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31871,13 +32470,13 @@ _loop1_113_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); - void *_tmp_253_var; + D(fprintf(stderr, "%*c> _loop1_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); + void *_tmp_255_var; while ( - (_tmp_253_var = _tmp_253_rule(p)) // fstring | string + (_tmp_255_var = _tmp_255_rule(p)) // fstring | string ) { - _res = _tmp_253_var; + _res = _tmp_255_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31894,7 +32493,7 @@ _loop1_113_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_115[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(fstring | string)")); } if (_n == 0 || p->error_indicator) { @@ -31916,9 +32515,9 @@ _loop1_113_rule(Parser *p) return _seq; } -// _tmp_114: star_named_expression ',' star_named_expressions? +// _tmp_116: star_named_expression ',' star_named_expressions? static void * -_tmp_114_rule(Parser *p) +_tmp_116_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31935,7 +32534,7 @@ _tmp_114_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + D(fprintf(stderr, "%*c> _tmp_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); Token * _literal; expr_ty y; void *z; @@ -31947,7 +32546,7 @@ _tmp_114_rule(Parser *p) (z = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? ) { - D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + D(fprintf(stderr, "%*c+ _tmp_116[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -31957,7 +32556,7 @@ _tmp_114_rule(Parser *p) 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_116[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression ',' star_named_expressions?")); } _res = NULL; @@ -31966,9 +32565,9 @@ _tmp_114_rule(Parser *p) return _res; } -// _loop0_116: ',' double_starred_kvpair +// _loop0_118: ',' double_starred_kvpair static asdl_seq * -_loop0_116_rule(Parser *p) +_loop0_118_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -31994,7 +32593,7 @@ _loop0_116_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -32026,7 +32625,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_118[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32043,9 +32642,9 @@ _loop0_116_rule(Parser *p) return _seq; } -// _gather_115: double_starred_kvpair _loop0_116 +// _gather_117: double_starred_kvpair _loop0_118 static asdl_seq * -_gather_115_rule(Parser *p) +_gather_117_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32057,27 +32656,27 @@ _gather_115_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_116 + { // double_starred_kvpair _loop0_118 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_116")); + D(fprintf(stderr, "%*c> _gather_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_118")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_116_rule(p)) // _loop0_116 + (seq = _loop0_118_rule(p)) // _loop0_118 ) { - D(fprintf(stderr, "%*c+ _gather_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_116")); + D(fprintf(stderr, "%*c+ _gather_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_118")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_115[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_116")); + D(fprintf(stderr, "%*c%s _gather_117[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_118")); } _res = NULL; done: @@ -32085,9 +32684,9 @@ _gather_115_rule(Parser *p) return _res; } -// _loop1_117: for_if_clause +// _loop1_119: for_if_clause static asdl_seq * -_loop1_117_rule(Parser *p) +_loop1_119_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32113,7 +32712,7 @@ _loop1_117_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); + D(fprintf(stderr, "%*c> _loop1_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); comprehension_ty for_if_clause_var; while ( (for_if_clause_var = for_if_clause_rule(p)) // for_if_clause @@ -32136,7 +32735,7 @@ _loop1_117_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_117[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_119[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "for_if_clause")); } if (_n == 0 || p->error_indicator) { @@ -32158,9 +32757,9 @@ _loop1_117_rule(Parser *p) return _seq; } -// _loop0_118: ('if' disjunction) +// _loop0_120: ('if' disjunction) static asdl_seq * -_loop0_118_rule(Parser *p) +_loop0_120_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32186,13 +32785,13 @@ _loop0_118_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_254_var; + D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_256_var; while ( - (_tmp_254_var = _tmp_254_rule(p)) // 'if' disjunction + (_tmp_256_var = _tmp_256_rule(p)) // 'if' disjunction ) { - _res = _tmp_254_var; + _res = _tmp_256_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32209,7 +32808,7 @@ _loop0_118_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_118[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32226,9 +32825,9 @@ _loop0_118_rule(Parser *p) return _seq; } -// _loop0_119: ('if' disjunction) +// _loop0_121: ('if' disjunction) static asdl_seq * -_loop0_119_rule(Parser *p) +_loop0_121_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32254,13 +32853,13 @@ _loop0_119_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_255_var; + D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_257_var; while ( - (_tmp_255_var = _tmp_255_rule(p)) // 'if' disjunction + (_tmp_257_var = _tmp_257_rule(p)) // 'if' disjunction ) { - _res = _tmp_255_var; + _res = _tmp_257_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32277,7 +32876,7 @@ _loop0_119_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_119[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_121[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32294,9 +32893,9 @@ _loop0_119_rule(Parser *p) return _seq; } -// _tmp_120: assignment_expression | expression !':=' +// _tmp_122: assignment_expression | expression !':=' static void * -_tmp_120_rule(Parser *p) +_tmp_122_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32313,18 +32912,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, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -32332,7 +32931,7 @@ _tmp_120_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -32340,12 +32939,12 @@ _tmp_120_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -32354,9 +32953,9 @@ _tmp_120_rule(Parser *p) return _res; } -// _loop0_122: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +// _loop0_124: ',' (starred_expression | (assignment_expression | expression !':=') !'=') static asdl_seq * -_loop0_122_rule(Parser *p) +_loop0_124_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32382,13 +32981,13 @@ _loop0_122_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); Token * _literal; void *elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_256_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_258_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { _res = elem; @@ -32414,7 +33013,7 @@ _loop0_122_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_122[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -32431,10 +33030,10 @@ _loop0_122_rule(Parser *p) return _seq; } -// _gather_121: -// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_122 +// _gather_123: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 static asdl_seq * -_gather_121_rule(Parser *p) +_gather_123_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32446,27 +33045,27 @@ _gather_121_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_122 + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_122")); + D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_256_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (elem = _tmp_258_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' && - (seq = _loop0_122_rule(p)) // _loop0_122 + (seq = _loop0_124_rule(p)) // _loop0_124 ) { - D(fprintf(stderr, "%*c+ _gather_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_122")); + D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_121[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_122")); + D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_124")); } _res = NULL; done: @@ -32474,9 +33073,9 @@ _gather_121_rule(Parser *p) return _res; } -// _tmp_123: ',' kwargs +// _tmp_125: ',' kwargs static void * -_tmp_123_rule(Parser *p) +_tmp_125_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32493,7 +33092,7 @@ _tmp_123_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); Token * _literal; asdl_seq* k; if ( @@ -32502,7 +33101,7 @@ _tmp_123_rule(Parser *p) (k = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -32512,7 +33111,7 @@ _tmp_123_rule(Parser *p) 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_125[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); } _res = NULL; @@ -32521,9 +33120,9 @@ _tmp_123_rule(Parser *p) return _res; } -// _loop0_125: ',' kwarg_or_starred +// _loop0_127: ',' kwarg_or_starred static asdl_seq * -_loop0_125_rule(Parser *p) +_loop0_127_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -32549,7 +33148,7 @@ _loop0_125_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -32581,127 +33180,8 @@ _loop0_125_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_125[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_124: kwarg_or_starred _loop0_125 -static asdl_seq * -_gather_124_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // kwarg_or_starred _loop0_125 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_125")); - KeywordOrStarred* elem; - asdl_seq * seq; - if ( - (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred - && - (seq = _loop0_125_rule(p)) // _loop0_125 - ) - { - D(fprintf(stderr, "%*c+ _gather_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_125")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_124[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_125")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_127: ',' kwarg_or_double_starred -static asdl_seq * -_loop0_127_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - p->error_indicator = 1; - PyErr_NoMemory(); - } - 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; - { // ',' kwarg_or_double_starred - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); - Token * _literal; - KeywordOrStarred* elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -32717,7 +33197,7 @@ _loop0_127_rule(Parser *p) return _seq; } -// _gather_126: kwarg_or_double_starred _loop0_127 +// _gather_126: kwarg_or_starred _loop0_127 static asdl_seq * _gather_126_rule(Parser *p) { @@ -32731,27 +33211,27 @@ _gather_126_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_127 + { // kwarg_or_starred _loop0_127 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_127")); + D(fprintf(stderr, "%*c> _gather_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); KeywordOrStarred* elem; asdl_seq * seq; if ( - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred + (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && (seq = _loop0_127_rule(p)) // _loop0_127 ) { - D(fprintf(stderr, "%*c+ _gather_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_127")); + D(fprintf(stderr, "%*c+ _gather_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_127")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _gather_126[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_127")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_127")); } _res = NULL; done: @@ -32759,7 +33239,7 @@ _gather_126_rule(Parser *p) return _res; } -// _loop0_129: ',' kwarg_or_starred +// _loop0_129: ',' kwarg_or_double_starred static asdl_seq * _loop0_129_rule(Parser *p) { @@ -32782,18 +33262,18 @@ _loop0_129_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' kwarg_or_starred + { // ',' kwarg_or_double_starred if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred + (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred ) { _res = elem; @@ -32820,7 +33300,7 @@ _loop0_129_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -32836,7 +33316,7 @@ _loop0_129_rule(Parser *p) return _seq; } -// _gather_128: kwarg_or_starred _loop0_129 +// _gather_128: kwarg_or_double_starred _loop0_129 static asdl_seq * _gather_128_rule(Parser *p) { @@ -32850,27 +33330,27 @@ _gather_128_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_129 + { // kwarg_or_double_starred _loop0_129 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_129")); + D(fprintf(stderr, "%*c> _gather_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); KeywordOrStarred* elem; asdl_seq * seq; if ( - (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred + (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && (seq = _loop0_129_rule(p)) // _loop0_129 ) { - D(fprintf(stderr, "%*c+ _gather_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_129")); + D(fprintf(stderr, "%*c+ _gather_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_129")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _gather_128[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_129")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_129")); } _res = NULL; done: @@ -32878,7 +33358,7 @@ _gather_128_rule(Parser *p) return _res; } -// _loop0_131: ',' kwarg_or_double_starred +// _loop0_131: ',' kwarg_or_starred static asdl_seq * _loop0_131_rule(Parser *p) { @@ -32901,18 +33381,18 @@ _loop0_131_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' kwarg_or_double_starred + { // ',' kwarg_or_starred if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred + (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred ) { _res = elem; @@ -32939,7 +33419,7 @@ _loop0_131_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s _loop0_131[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -32955,7 +33435,7 @@ _loop0_131_rule(Parser *p) return _seq; } -// _gather_130: kwarg_or_double_starred _loop0_131 +// _gather_130: kwarg_or_starred _loop0_131 static asdl_seq * _gather_130_rule(Parser *p) { @@ -32969,27 +33449,27 @@ _gather_130_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_131 + { // kwarg_or_starred _loop0_131 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_131")); + D(fprintf(stderr, "%*c> _gather_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); KeywordOrStarred* elem; asdl_seq * seq; if ( - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred + (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && (seq = _loop0_131_rule(p)) // _loop0_131 ) { - D(fprintf(stderr, "%*c+ _gather_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_131")); + D(fprintf(stderr, "%*c+ _gather_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_131")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _gather_130[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_131")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_131")); } _res = NULL; done: @@ -32997,9 +33477,128 @@ _gather_130_rule(Parser *p) return _res; } -// _loop0_132: (',' star_target) +// _loop0_133: ',' kwarg_or_double_starred static asdl_seq * -_loop0_132_rule(Parser *p) +_loop0_133_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + 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; + { // ',' kwarg_or_double_starred + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + Token * _literal; + KeywordOrStarred* elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred + ) + { + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _gather_132: kwarg_or_double_starred _loop0_133 +static asdl_seq * +_gather_132_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + p->error_indicator = 1; + PyErr_NoMemory(); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // kwarg_or_double_starred _loop0_133 + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _gather_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); + KeywordOrStarred* elem; + asdl_seq * seq; + if ( + (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred + && + (seq = _loop0_133_rule(p)) // _loop0_133 + ) + { + D(fprintf(stderr, "%*c+ _gather_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_133")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _gather_132[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_133")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _loop0_134: (',' star_target) +static asdl_seq * +_loop0_134_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33025,13 +33624,13 @@ _loop0_132_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_257_var; + D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_259_var; while ( - (_tmp_257_var = _tmp_257_rule(p)) // ',' star_target + (_tmp_259_var = _tmp_259_rule(p)) // ',' star_target ) { - _res = _tmp_257_var; + _res = _tmp_259_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -33048,7 +33647,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_134[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33065,9 +33664,9 @@ _loop0_132_rule(Parser *p) return _seq; } -// _loop0_134: ',' star_target +// _loop0_136: ',' star_target static asdl_seq * -_loop0_134_rule(Parser *p) +_loop0_136_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33093,7 +33692,7 @@ _loop0_134_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _loop0_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty elem; while ( @@ -33125,7 +33724,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_136[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33142,9 +33741,9 @@ _loop0_134_rule(Parser *p) return _seq; } -// _gather_133: star_target _loop0_134 +// _gather_135: star_target _loop0_136 static asdl_seq * -_gather_133_rule(Parser *p) +_gather_135_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33156,27 +33755,27 @@ _gather_133_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_target _loop0_134 + { // star_target _loop0_136 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_134")); + D(fprintf(stderr, "%*c> _gather_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); expr_ty elem; asdl_seq * seq; if ( (elem = star_target_rule(p)) // star_target && - (seq = _loop0_134_rule(p)) // _loop0_134 + (seq = _loop0_136_rule(p)) // _loop0_136 ) { - D(fprintf(stderr, "%*c+ _gather_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_134")); + D(fprintf(stderr, "%*c+ _gather_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_136")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_133[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_134")); + D(fprintf(stderr, "%*c%s _gather_135[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_136")); } _res = NULL; done: @@ -33184,9 +33783,9 @@ _gather_133_rule(Parser *p) return _res; } -// _loop1_135: (',' star_target) +// _loop1_137: (',' star_target) static asdl_seq * -_loop1_135_rule(Parser *p) +_loop1_137_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33212,13 +33811,13 @@ _loop1_135_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_258_var; + D(fprintf(stderr, "%*c> _loop1_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_260_var; while ( - (_tmp_258_var = _tmp_258_rule(p)) // ',' star_target + (_tmp_260_var = _tmp_260_rule(p)) // ',' star_target ) { - _res = _tmp_258_var; + _res = _tmp_260_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -33235,7 +33834,7 @@ _loop1_135_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_135[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_137[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } if (_n == 0 || p->error_indicator) { @@ -33257,9 +33856,9 @@ _loop1_135_rule(Parser *p) return _seq; } -// _tmp_136: !'*' star_target +// _tmp_138: !'*' star_target static void * -_tmp_136_rule(Parser *p) +_tmp_138_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33276,7 +33875,7 @@ _tmp_136_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); expr_ty star_target_var; if ( _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' @@ -33284,12 +33883,12 @@ _tmp_136_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); _res = star_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); } _res = NULL; @@ -33298,9 +33897,9 @@ _tmp_136_rule(Parser *p) return _res; } -// _loop0_138: ',' del_target +// _loop0_140: ',' del_target static asdl_seq * -_loop0_138_rule(Parser *p) +_loop0_140_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33326,7 +33925,7 @@ _loop0_138_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); + D(fprintf(stderr, "%*c> _loop0_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); Token * _literal; expr_ty elem; while ( @@ -33358,7 +33957,7 @@ _loop0_138_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_138[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_140[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33375,9 +33974,9 @@ _loop0_138_rule(Parser *p) return _seq; } -// _gather_137: del_target _loop0_138 +// _gather_139: del_target _loop0_140 static asdl_seq * -_gather_137_rule(Parser *p) +_gather_139_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33389,27 +33988,27 @@ _gather_137_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // del_target _loop0_138 + { // del_target _loop0_140 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_138")); + D(fprintf(stderr, "%*c> _gather_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); expr_ty elem; asdl_seq * seq; if ( (elem = del_target_rule(p)) // del_target && - (seq = _loop0_138_rule(p)) // _loop0_138 + (seq = _loop0_140_rule(p)) // _loop0_140 ) { - D(fprintf(stderr, "%*c+ _gather_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_138")); + D(fprintf(stderr, "%*c+ _gather_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_140")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_137[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_138")); + D(fprintf(stderr, "%*c%s _gather_139[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_140")); } _res = NULL; done: @@ -33417,9 +34016,9 @@ _gather_137_rule(Parser *p) return _res; } -// _loop0_140: ',' expression +// _loop0_142: ',' expression static asdl_seq * -_loop0_140_rule(Parser *p) +_loop0_142_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33445,7 +34044,7 @@ _loop0_140_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -33477,7 +34076,7 @@ _loop0_140_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_140[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_142[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33494,9 +34093,9 @@ _loop0_140_rule(Parser *p) return _seq; } -// _gather_139: expression _loop0_140 +// _gather_141: expression _loop0_142 static asdl_seq * -_gather_139_rule(Parser *p) +_gather_141_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33508,27 +34107,27 @@ _gather_139_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_140 + { // expression _loop0_142 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_140")); + D(fprintf(stderr, "%*c> _gather_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_140_rule(p)) // _loop0_140 + (seq = _loop0_142_rule(p)) // _loop0_142 ) { - D(fprintf(stderr, "%*c+ _gather_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_140")); + D(fprintf(stderr, "%*c+ _gather_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_139[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_140")); + D(fprintf(stderr, "%*c%s _gather_141[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_142")); } _res = NULL; done: @@ -33536,9 +34135,9 @@ _gather_139_rule(Parser *p) return _res; } -// _loop0_142: ',' expression +// _loop0_144: ',' expression static asdl_seq * -_loop0_142_rule(Parser *p) +_loop0_144_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33564,7 +34163,7 @@ _loop0_142_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -33596,7 +34195,7 @@ _loop0_142_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33613,9 +34212,9 @@ _loop0_142_rule(Parser *p) return _seq; } -// _gather_141: expression _loop0_142 +// _gather_143: expression _loop0_144 static asdl_seq * -_gather_141_rule(Parser *p) +_gather_143_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33627,27 +34226,27 @@ _gather_141_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_142 + { // expression _loop0_144 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); + D(fprintf(stderr, "%*c> _gather_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_142_rule(p)) // _loop0_142 + (seq = _loop0_144_rule(p)) // _loop0_144 ) { - D(fprintf(stderr, "%*c+ _gather_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_142")); + D(fprintf(stderr, "%*c+ _gather_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_141[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_142")); + D(fprintf(stderr, "%*c%s _gather_143[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_144")); } _res = NULL; done: @@ -33655,9 +34254,9 @@ _gather_141_rule(Parser *p) return _res; } -// _loop0_144: ',' expression +// _loop0_146: ',' expression static asdl_seq * -_loop0_144_rule(Parser *p) +_loop0_146_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33683,7 +34282,7 @@ _loop0_144_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -33715,7 +34314,7 @@ _loop0_144_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33732,9 +34331,9 @@ _loop0_144_rule(Parser *p) return _seq; } -// _gather_143: expression _loop0_144 +// _gather_145: expression _loop0_146 static asdl_seq * -_gather_143_rule(Parser *p) +_gather_145_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33746,27 +34345,27 @@ _gather_143_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_144 + { // expression _loop0_146 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); + D(fprintf(stderr, "%*c> _gather_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_144_rule(p)) // _loop0_144 + (seq = _loop0_146_rule(p)) // _loop0_146 ) { - D(fprintf(stderr, "%*c+ _gather_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_144")); + D(fprintf(stderr, "%*c+ _gather_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_143[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_144")); + D(fprintf(stderr, "%*c%s _gather_145[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_146")); } _res = NULL; done: @@ -33774,9 +34373,9 @@ _gather_143_rule(Parser *p) return _res; } -// _loop0_146: ',' expression +// _loop0_148: ',' expression static asdl_seq * -_loop0_146_rule(Parser *p) +_loop0_148_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33802,7 +34401,7 @@ _loop0_146_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _loop0_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty elem; while ( @@ -33834,7 +34433,7 @@ _loop0_146_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -33851,9 +34450,9 @@ _loop0_146_rule(Parser *p) return _seq; } -// _gather_145: expression _loop0_146 +// _gather_147: expression _loop0_148 static asdl_seq * -_gather_145_rule(Parser *p) +_gather_147_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33865,27 +34464,27 @@ _gather_145_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // expression _loop0_146 + { // expression _loop0_148 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); + D(fprintf(stderr, "%*c> _gather_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_148")); expr_ty elem; asdl_seq * seq; if ( (elem = expression_rule(p)) // expression && - (seq = _loop0_146_rule(p)) // _loop0_146 + (seq = _loop0_148_rule(p)) // _loop0_148 ) { - D(fprintf(stderr, "%*c+ _gather_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_146")); + D(fprintf(stderr, "%*c+ _gather_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_148")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_145[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_146")); + D(fprintf(stderr, "%*c%s _gather_147[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_148")); } _res = NULL; done: @@ -33893,9 +34492,9 @@ _gather_145_rule(Parser *p) return _res; } -// _tmp_147: NEWLINE INDENT +// _tmp_149: NEWLINE INDENT static void * -_tmp_147_rule(Parser *p) +_tmp_149_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33912,7 +34511,7 @@ _tmp_147_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); Token * indent_var; Token * newline_var; if ( @@ -33921,12 +34520,12 @@ _tmp_147_rule(Parser *p) (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); _res = _PyPegen_dummy_name(p, newline_var, indent_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE INDENT")); } _res = NULL; @@ -33935,9 +34534,9 @@ _tmp_147_rule(Parser *p) return _res; } -// _tmp_148: args | expression for_if_clauses +// _tmp_150: args | expression for_if_clauses static void * -_tmp_148_rule(Parser *p) +_tmp_150_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -33954,18 +34553,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, "args")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); expr_ty args_var; if ( (args_var = args_rule(p)) // args ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); _res = args_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "args")); } { // expression for_if_clauses @@ -33973,7 +34572,7 @@ _tmp_148_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); expr_ty expression_var; asdl_comprehension_seq* for_if_clauses_var; if ( @@ -33982,12 +34581,12 @@ _tmp_148_rule(Parser *p) (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%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, "expression for_if_clauses")); } _res = NULL; @@ -33996,9 +34595,9 @@ _tmp_148_rule(Parser *p) return _res; } -// _tmp_149: args ',' +// _tmp_151: args ',' static void * -_tmp_149_rule(Parser *p) +_tmp_151_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34015,7 +34614,7 @@ _tmp_149_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); + D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); Token * _literal; expr_ty args_var; if ( @@ -34024,12 +34623,12 @@ _tmp_149_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); + D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); _res = _PyPegen_dummy_name(p, args_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%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, "args ','")); } _res = NULL; @@ -34038,9 +34637,9 @@ _tmp_149_rule(Parser *p) return _res; } -// _tmp_150: ',' | ')' +// _tmp_152: ',' | ')' static void * -_tmp_150_rule(Parser *p) +_tmp_152_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34057,18 +34656,18 @@ _tmp_150_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%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, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_150[%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_150[%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, "','")); } { // ')' @@ -34076,18 +34675,18 @@ _tmp_150_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%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, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_150[%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_150[%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; @@ -34096,9 +34695,9 @@ _tmp_150_rule(Parser *p) return _res; } -// _tmp_151: 'True' | 'False' | 'None' +// _tmp_153: 'True' | 'False' | 'None' static void * -_tmp_151_rule(Parser *p) +_tmp_153_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34115,18 +34714,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, "'True'")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 601)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; 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_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'False' @@ -34134,18 +34733,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, "'False'")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 603)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; 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_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } { // 'None' @@ -34153,18 +34752,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, "'None'")); + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 602)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; 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_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } _res = NULL; @@ -34173,9 +34772,9 @@ _tmp_151_rule(Parser *p) return _res; } -// _tmp_152: NAME '=' +// _tmp_154: NAME '=' static void * -_tmp_152_rule(Parser *p) +_tmp_154_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34192,7 +34791,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, "NAME '='")); + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); Token * _literal; expr_ty name_var; if ( @@ -34201,12 +34800,12 @@ _tmp_152_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); _res = _PyPegen_dummy_name(p, name_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%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, "NAME '='")); } _res = NULL; @@ -34215,9 +34814,9 @@ _tmp_152_rule(Parser *p) return _res; } -// _tmp_153: NAME STRING | SOFT_KEYWORD +// _tmp_155: NAME STRING | SOFT_KEYWORD static void * -_tmp_153_rule(Parser *p) +_tmp_155_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34234,7 +34833,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, "NAME STRING")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); expr_ty name_var; expr_ty string_var; if ( @@ -34243,12 +34842,12 @@ _tmp_153_rule(Parser *p) (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + D(fprintf(stderr, "%*c+ _tmp_155[%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_153[%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, "NAME STRING")); } { // SOFT_KEYWORD @@ -34256,18 +34855,18 @@ _tmp_153_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c> _tmp_155[%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_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + D(fprintf(stderr, "%*c+ _tmp_155[%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_153[%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, "SOFT_KEYWORD")); } _res = NULL; @@ -34276,9 +34875,9 @@ _tmp_153_rule(Parser *p) return _res; } -// _tmp_154: 'else' | ':' +// _tmp_156: 'else' | ':' static void * -_tmp_154_rule(Parser *p) +_tmp_156_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34295,18 +34894,18 @@ _tmp_154_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 645)) // token='else' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); _res = _keyword; 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_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } { // ':' @@ -34314,18 +34913,18 @@ _tmp_154_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; 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_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -34334,9 +34933,9 @@ _tmp_154_rule(Parser *p) return _res; } -// _tmp_155: FSTRING_MIDDLE | fstring_replacement_field +// _tmp_157: FSTRING_MIDDLE | fstring_replacement_field static void * -_tmp_155_rule(Parser *p) +_tmp_157_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34353,18 +34952,18 @@ _tmp_155_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); Token * fstring_middle_var; if ( (fstring_middle_var = _PyPegen_expect_token(p, FSTRING_MIDDLE)) // token='FSTRING_MIDDLE' ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_MIDDLE")); _res = fstring_middle_var; 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_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_MIDDLE")); } { // fstring_replacement_field @@ -34372,18 +34971,18 @@ _tmp_155_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_replacement_field")); + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_replacement_field")); expr_ty fstring_replacement_field_var; if ( (fstring_replacement_field_var = fstring_replacement_field_rule(p)) // fstring_replacement_field ) { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring_replacement_field")); + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring_replacement_field")); _res = fstring_replacement_field_var; 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_157[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_replacement_field")); } _res = NULL; @@ -34392,9 +34991,9 @@ _tmp_155_rule(Parser *p) return _res; } -// _tmp_156: '=' | ':=' +// _tmp_158: '=' | ':=' static void * -_tmp_156_rule(Parser *p) +_tmp_158_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34411,18 +35010,18 @@ _tmp_156_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // ':=' @@ -34430,18 +35029,18 @@ _tmp_156_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -34450,9 +35049,9 @@ _tmp_156_rule(Parser *p) return _res; } -// _tmp_157: list | tuple | genexp | 'True' | 'None' | 'False' +// _tmp_159: list | tuple | genexp | 'True' | 'None' | 'False' static void * -_tmp_157_rule(Parser *p) +_tmp_159_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34469,18 +35068,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, "list")); + D(fprintf(stderr, "%*c> _tmp_159[%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_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + D(fprintf(stderr, "%*c+ _tmp_159[%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_157[%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, "list")); } { // tuple @@ -34488,18 +35087,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, "tuple")); + D(fprintf(stderr, "%*c> _tmp_159[%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_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + D(fprintf(stderr, "%*c+ _tmp_159[%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_157[%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, "tuple")); } { // genexp @@ -34507,18 +35106,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, "genexp")); + D(fprintf(stderr, "%*c> _tmp_159[%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_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c+ _tmp_159[%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_157[%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, "genexp")); } { // 'True' @@ -34526,18 +35125,18 @@ _tmp_157_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 601)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } { // 'None' @@ -34545,18 +35144,18 @@ _tmp_157_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 602)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } { // 'False' @@ -34564,18 +35163,18 @@ _tmp_157_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 603)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; @@ -34584,9 +35183,9 @@ _tmp_157_rule(Parser *p) return _res; } -// _tmp_158: '=' | ':=' +// _tmp_160: '=' | ':=' static void * -_tmp_158_rule(Parser *p) +_tmp_160_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34603,18 +35202,18 @@ _tmp_158_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%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, "'='")); } { // ':=' @@ -34622,18 +35221,18 @@ _tmp_158_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; @@ -34642,9 +35241,9 @@ _tmp_158_rule(Parser *p) return _res; } -// _loop0_159: star_named_expressions +// _loop0_161: star_named_expressions static asdl_seq * -_loop0_159_rule(Parser *p) +_loop0_161_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34670,7 +35269,7 @@ _loop0_159_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_161[%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 @@ -34693,7 +35292,7 @@ _loop0_159_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_159[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_161[%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); @@ -34710,9 +35309,9 @@ _loop0_159_rule(Parser *p) return _seq; } -// _loop0_160: (star_targets '=') +// _loop0_162: (star_targets '=') static asdl_seq * -_loop0_160_rule(Parser *p) +_loop0_162_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34738,13 +35337,13 @@ _loop0_160_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_259_var; + D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_261_var; while ( - (_tmp_259_var = _tmp_259_rule(p)) // star_targets '=' + (_tmp_261_var = _tmp_261_rule(p)) // star_targets '=' ) { - _res = _tmp_259_var; + _res = _tmp_261_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -34761,7 +35360,7 @@ _loop0_160_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_160[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_162[%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); @@ -34778,9 +35377,9 @@ _loop0_160_rule(Parser *p) return _seq; } -// _loop0_161: (star_targets '=') +// _loop0_163: (star_targets '=') static asdl_seq * -_loop0_161_rule(Parser *p) +_loop0_163_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34806,13 +35405,13 @@ _loop0_161_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_260_var; + D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_262_var; while ( - (_tmp_260_var = _tmp_260_rule(p)) // star_targets '=' + (_tmp_262_var = _tmp_262_rule(p)) // star_targets '=' ) { - _res = _tmp_260_var; + _res = _tmp_262_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -34829,7 +35428,7 @@ _loop0_161_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_161[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -34846,9 +35445,9 @@ _loop0_161_rule(Parser *p) return _seq; } -// _tmp_162: yield_expr | star_expressions +// _tmp_164: yield_expr | star_expressions static void * -_tmp_162_rule(Parser *p) +_tmp_164_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34865,18 +35464,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_164[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -34884,18 +35483,18 @@ _tmp_162_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_164[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -34904,9 +35503,9 @@ _tmp_162_rule(Parser *p) return _res; } -// _tmp_163: '[' | '(' | '{' +// _tmp_165: '[' | '(' | '{' static void * -_tmp_163_rule(Parser *p) +_tmp_165_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -34923,18 +35522,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, 9)) // 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, "'['")); } { // '(' @@ -34942,18 +35541,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, 7)) // 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, "'('")); } { // '{' @@ -34961,18 +35560,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, 25)) // 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; @@ -34981,9 +35580,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) { p->error_indicator = 1; @@ -35000,18 +35599,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, 9)) // 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, "'['")); } { // '{' @@ -35019,18 +35618,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, 25)) // 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; @@ -35039,9 +35638,9 @@ _tmp_164_rule(Parser *p) return _res; } -// _tmp_165: '[' | '{' +// _tmp_167: '[' | '{' static void * -_tmp_165_rule(Parser *p) +_tmp_167_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35058,18 +35657,18 @@ _tmp_165_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '{' @@ -35077,18 +35676,18 @@ _tmp_165_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -35097,9 +35696,9 @@ _tmp_165_rule(Parser *p) return _res; } -// _tmp_166: slash_no_default | slash_with_default +// _tmp_168: slash_no_default | slash_with_default static void * -_tmp_166_rule(Parser *p) +_tmp_168_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35116,18 +35715,18 @@ _tmp_166_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_168[%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_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_168[%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_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, "slash_no_default")); } { // slash_with_default @@ -35135,18 +35734,18 @@ _tmp_166_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_168[%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_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_168[%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_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, "slash_with_default")); } _res = NULL; @@ -35155,9 +35754,9 @@ _tmp_166_rule(Parser *p) return _res; } -// _loop0_167: param_maybe_default +// _loop0_169: param_maybe_default static asdl_seq * -_loop0_167_rule(Parser *p) +_loop0_169_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35183,7 +35782,7 @@ _loop0_167_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -35206,7 +35805,7 @@ _loop0_167_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_167[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35223,9 +35822,9 @@ _loop0_167_rule(Parser *p) return _seq; } -// _loop0_168: param_no_default +// _loop0_170: param_no_default static asdl_seq * -_loop0_168_rule(Parser *p) +_loop0_170_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35251,7 +35850,7 @@ _loop0_168_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -35274,7 +35873,7 @@ _loop0_168_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_168[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35291,9 +35890,9 @@ _loop0_168_rule(Parser *p) return _seq; } -// _loop0_169: param_no_default +// _loop0_171: param_no_default static asdl_seq * -_loop0_169_rule(Parser *p) +_loop0_171_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35319,7 +35918,7 @@ _loop0_169_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -35342,7 +35941,7 @@ _loop0_169_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35359,9 +35958,9 @@ _loop0_169_rule(Parser *p) return _seq; } -// _loop1_170: param_no_default +// _loop1_172: param_no_default static asdl_seq * -_loop1_170_rule(Parser *p) +_loop1_172_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35387,7 +35986,7 @@ _loop1_170_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -35410,7 +36009,7 @@ _loop1_170_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_170[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_172[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -35432,9 +36031,9 @@ _loop1_170_rule(Parser *p) return _seq; } -// _tmp_171: slash_no_default | slash_with_default +// _tmp_173: slash_no_default | slash_with_default static void * -_tmp_171_rule(Parser *p) +_tmp_173_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35451,18 +36050,18 @@ _tmp_171_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); asdl_arg_seq* slash_no_default_var; if ( (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); _res = slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); } { // slash_with_default @@ -35470,18 +36069,18 @@ _tmp_171_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); SlashWithDefault* slash_with_default_var; if ( (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_171[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_171[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } _res = NULL; @@ -35490,9 +36089,9 @@ _tmp_171_rule(Parser *p) return _res; } -// _loop0_172: param_maybe_default +// _loop0_174: param_maybe_default static asdl_seq * -_loop0_172_rule(Parser *p) +_loop0_174_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35518,7 +36117,7 @@ _loop0_172_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -35541,7 +36140,7 @@ _loop0_172_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_172[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_174[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35558,9 +36157,9 @@ _loop0_172_rule(Parser *p) return _seq; } -// _tmp_173: ',' | param_no_default +// _tmp_175: ',' | param_no_default static void * -_tmp_173_rule(Parser *p) +_tmp_175_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35577,18 +36176,18 @@ _tmp_173_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // param_no_default @@ -35596,18 +36195,18 @@ _tmp_173_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_175[%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_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_175[%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_173[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } _res = NULL; @@ -35616,9 +36215,9 @@ _tmp_173_rule(Parser *p) return _res; } -// _loop0_174: param_maybe_default +// _loop0_176: param_maybe_default static asdl_seq * -_loop0_174_rule(Parser *p) +_loop0_176_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35644,7 +36243,7 @@ _loop0_174_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -35667,7 +36266,7 @@ _loop0_174_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_174[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_176[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -35684,9 +36283,9 @@ _loop0_174_rule(Parser *p) return _seq; } -// _loop1_175: param_maybe_default +// _loop1_177: param_maybe_default static asdl_seq * -_loop1_175_rule(Parser *p) +_loop1_177_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35712,7 +36311,7 @@ _loop1_175_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -35735,7 +36334,7 @@ _loop1_175_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_175[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_177[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -35757,9 +36356,9 @@ _loop1_175_rule(Parser *p) return _seq; } -// _tmp_176: ')' | ',' +// _tmp_178: ')' | ',' static void * -_tmp_176_rule(Parser *p) +_tmp_178_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35776,18 +36375,18 @@ _tmp_176_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' @@ -35795,18 +36394,18 @@ _tmp_176_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_176[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_176[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -35815,9 +36414,9 @@ _tmp_176_rule(Parser *p) return _res; } -// _tmp_177: ')' | ',' (')' | '**') +// _tmp_179: ')' | ',' (')' | '**') static void * -_tmp_177_rule(Parser *p) +_tmp_179_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35834,18 +36433,18 @@ _tmp_177_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -35853,21 +36452,21 @@ _tmp_177_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_261_var; + void *_tmp_263_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_261_var = _tmp_261_rule(p)) // ')' | '**' + (_tmp_263_var = _tmp_263_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_177[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_261_var); + D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_263_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_177[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -35876,9 +36475,9 @@ _tmp_177_rule(Parser *p) return _res; } -// _tmp_178: param_no_default | ',' +// _tmp_180: param_no_default | ',' static void * -_tmp_178_rule(Parser *p) +_tmp_180_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35895,18 +36494,18 @@ _tmp_178_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; if ( (param_no_default_var = param_no_default_rule(p)) // param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); _res = param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } { // ',' @@ -35914,18 +36513,18 @@ _tmp_178_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -35934,9 +36533,9 @@ _tmp_178_rule(Parser *p) return _res; } -// _loop0_179: param_maybe_default +// _loop0_181: param_maybe_default static asdl_seq * -_loop0_179_rule(Parser *p) +_loop0_181_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -35962,7 +36561,7 @@ _loop0_179_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); NameDefaultPair* param_maybe_default_var; while ( (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default @@ -35985,7 +36584,7 @@ _loop0_179_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_179[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_181[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36002,9 +36601,9 @@ _loop0_179_rule(Parser *p) return _seq; } -// _tmp_180: param_no_default | ',' +// _tmp_182: param_no_default | ',' static void * -_tmp_180_rule(Parser *p) +_tmp_182_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36021,18 +36620,18 @@ _tmp_180_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _tmp_182[%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_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_182[%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_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } { // ',' @@ -36040,18 +36639,18 @@ _tmp_180_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -36060,9 +36659,9 @@ _tmp_180_rule(Parser *p) return _res; } -// _tmp_181: '*' | '**' | '/' +// _tmp_183: '*' | '**' | '/' static void * -_tmp_181_rule(Parser *p) +_tmp_183_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36079,18 +36678,18 @@ _tmp_181_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } { // '**' @@ -36098,18 +36697,18 @@ _tmp_181_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } { // '/' @@ -36117,18 +36716,18 @@ _tmp_181_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_181[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_181[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } _res = NULL; @@ -36137,9 +36736,9 @@ _tmp_181_rule(Parser *p) return _res; } -// _loop1_182: param_with_default +// _loop1_184: param_with_default static asdl_seq * -_loop1_182_rule(Parser *p) +_loop1_184_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36165,7 +36764,7 @@ _loop1_182_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -36188,7 +36787,7 @@ _loop1_182_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_182[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_184[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -36210,9 +36809,9 @@ _loop1_182_rule(Parser *p) return _seq; } -// _tmp_183: lambda_slash_no_default | lambda_slash_with_default +// _tmp_185: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_183_rule(Parser *p) +_tmp_185_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36229,18 +36828,18 @@ _tmp_183_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_185[%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_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_185[%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_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); } { // lambda_slash_with_default @@ -36248,18 +36847,18 @@ _tmp_183_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_185[%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_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_185[%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_183[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; @@ -36268,9 +36867,9 @@ _tmp_183_rule(Parser *p) return _res; } -// _loop0_184: lambda_param_maybe_default +// _loop0_186: lambda_param_maybe_default static asdl_seq * -_loop0_184_rule(Parser *p) +_loop0_186_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36296,7 +36895,7 @@ _loop0_184_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -36319,7 +36918,7 @@ _loop0_184_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_184[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_186[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36336,9 +36935,9 @@ _loop0_184_rule(Parser *p) return _seq; } -// _loop0_185: lambda_param_no_default +// _loop0_187: lambda_param_no_default static asdl_seq * -_loop0_185_rule(Parser *p) +_loop0_187_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36364,7 +36963,7 @@ _loop0_185_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -36387,7 +36986,7 @@ _loop0_185_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_185[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_187[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36404,9 +37003,9 @@ _loop0_185_rule(Parser *p) return _seq; } -// _loop0_186: lambda_param_no_default +// _loop0_188: lambda_param_no_default static asdl_seq * -_loop0_186_rule(Parser *p) +_loop0_188_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36432,7 +37031,7 @@ _loop0_186_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -36455,7 +37054,7 @@ _loop0_186_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_186[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_188[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36472,9 +37071,9 @@ _loop0_186_rule(Parser *p) return _seq; } -// _loop0_188: ',' lambda_param +// _loop0_190: ',' lambda_param static asdl_seq * -_loop0_188_rule(Parser *p) +_loop0_190_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36500,7 +37099,7 @@ _loop0_188_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); + D(fprintf(stderr, "%*c> _loop0_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); Token * _literal; arg_ty elem; while ( @@ -36532,7 +37131,7 @@ _loop0_188_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_188[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_190[%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); @@ -36549,9 +37148,9 @@ _loop0_188_rule(Parser *p) return _seq; } -// _gather_187: lambda_param _loop0_188 +// _gather_189: lambda_param _loop0_190 static asdl_seq * -_gather_187_rule(Parser *p) +_gather_189_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36563,27 +37162,27 @@ _gather_187_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // lambda_param _loop0_188 + { // lambda_param _loop0_190 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_188")); + D(fprintf(stderr, "%*c> _gather_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_190")); arg_ty elem; asdl_seq * seq; if ( (elem = lambda_param_rule(p)) // lambda_param && - (seq = _loop0_188_rule(p)) // _loop0_188 + (seq = _loop0_190_rule(p)) // _loop0_190 ) { - D(fprintf(stderr, "%*c+ _gather_187[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_188")); + D(fprintf(stderr, "%*c+ _gather_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_190")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_187[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_188")); + D(fprintf(stderr, "%*c%s _gather_189[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_190")); } _res = NULL; done: @@ -36591,9 +37190,9 @@ _gather_187_rule(Parser *p) return _res; } -// _tmp_189: lambda_slash_no_default | lambda_slash_with_default +// _tmp_191: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_189_rule(Parser *p) +_tmp_191_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36610,18 +37209,18 @@ _tmp_189_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c> _tmp_191[%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_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + D(fprintf(stderr, "%*c+ _tmp_191[%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_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); } { // lambda_slash_with_default @@ -36629,18 +37228,18 @@ _tmp_189_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_191[%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_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_191[%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_189[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; @@ -36649,9 +37248,9 @@ _tmp_189_rule(Parser *p) return _res; } -// _loop0_190: lambda_param_maybe_default +// _loop0_192: lambda_param_maybe_default static asdl_seq * -_loop0_190_rule(Parser *p) +_loop0_192_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36677,7 +37276,7 @@ _loop0_190_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -36700,7 +37299,7 @@ _loop0_190_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_190[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_192[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36717,9 +37316,9 @@ _loop0_190_rule(Parser *p) return _seq; } -// _tmp_191: ',' | lambda_param_no_default +// _tmp_193: ',' | lambda_param_no_default static void * -_tmp_191_rule(Parser *p) +_tmp_193_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36736,18 +37335,18 @@ _tmp_191_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // lambda_param_no_default @@ -36755,18 +37354,18 @@ _tmp_191_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_193[%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_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_193[%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_191[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } _res = NULL; @@ -36775,9 +37374,9 @@ _tmp_191_rule(Parser *p) return _res; } -// _loop0_192: lambda_param_maybe_default +// _loop0_194: lambda_param_maybe_default static asdl_seq * -_loop0_192_rule(Parser *p) +_loop0_194_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36803,7 +37402,7 @@ _loop0_192_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -36826,7 +37425,7 @@ _loop0_192_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_192[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_194[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -36843,9 +37442,9 @@ _loop0_192_rule(Parser *p) return _seq; } -// _loop1_193: lambda_param_maybe_default +// _loop1_195: lambda_param_maybe_default static asdl_seq * -_loop1_193_rule(Parser *p) +_loop1_195_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36871,7 +37470,7 @@ _loop1_193_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop1_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -36894,7 +37493,7 @@ _loop1_193_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_193[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_195[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } if (_n == 0 || p->error_indicator) { @@ -36916,9 +37515,9 @@ _loop1_193_rule(Parser *p) return _seq; } -// _loop1_194: lambda_param_with_default +// _loop1_196: lambda_param_with_default static asdl_seq * -_loop1_194_rule(Parser *p) +_loop1_196_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -36944,7 +37543,7 @@ _loop1_194_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -36967,7 +37566,7 @@ _loop1_194_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_194[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_196[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -36989,9 +37588,9 @@ _loop1_194_rule(Parser *p) return _seq; } -// _tmp_195: ':' | ',' (':' | '**') +// _tmp_197: ':' | ',' (':' | '**') static void * -_tmp_195_rule(Parser *p) +_tmp_197_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37008,18 +37607,18 @@ _tmp_195_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -37027,21 +37626,21 @@ _tmp_195_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_262_var; + void *_tmp_264_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_262_var = _tmp_262_rule(p)) // ':' | '**' + (_tmp_264_var = _tmp_264_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_195[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_262_var); + D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_264_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_195[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -37050,9 +37649,9 @@ _tmp_195_rule(Parser *p) return _res; } -// _tmp_196: lambda_param_no_default | ',' +// _tmp_198: lambda_param_no_default | ',' static void * -_tmp_196_rule(Parser *p) +_tmp_198_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37069,18 +37668,18 @@ _tmp_196_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; if ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } { // ',' @@ -37088,18 +37687,18 @@ _tmp_196_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_196[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_196[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -37108,9 +37707,9 @@ _tmp_196_rule(Parser *p) return _res; } -// _loop0_197: lambda_param_maybe_default +// _loop0_199: lambda_param_maybe_default static asdl_seq * -_loop0_197_rule(Parser *p) +_loop0_199_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37136,7 +37735,7 @@ _loop0_197_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c> _loop0_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); NameDefaultPair* lambda_param_maybe_default_var; while ( (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default @@ -37159,7 +37758,7 @@ _loop0_197_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_197[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_199[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -37176,9 +37775,9 @@ _loop0_197_rule(Parser *p) return _seq; } -// _tmp_198: lambda_param_no_default | ',' +// _tmp_200: lambda_param_no_default | ',' static void * -_tmp_198_rule(Parser *p) +_tmp_200_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37195,18 +37794,18 @@ _tmp_198_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _tmp_200[%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_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c+ _tmp_200[%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_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } { // ',' @@ -37214,18 +37813,18 @@ _tmp_198_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -37234,9 +37833,9 @@ _tmp_198_rule(Parser *p) return _res; } -// _tmp_199: '*' | '**' | '/' +// _tmp_201: '*' | '**' | '/' static void * -_tmp_199_rule(Parser *p) +_tmp_201_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37253,18 +37852,18 @@ _tmp_199_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } { // '**' @@ -37272,18 +37871,18 @@ _tmp_199_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } { // '/' @@ -37291,18 +37890,18 @@ _tmp_199_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_199[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_199[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } _res = NULL; @@ -37311,9 +37910,9 @@ _tmp_199_rule(Parser *p) return _res; } -// _tmp_200: ',' | ')' | ':' +// _tmp_202: ',' | ')' | ':' static void * -_tmp_200_rule(Parser *p) +_tmp_202_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37330,18 +37929,18 @@ _tmp_200_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } { // ')' @@ -37349,18 +37948,18 @@ _tmp_200_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ':' @@ -37368,18 +37967,18 @@ _tmp_200_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -37388,9 +37987,9 @@ _tmp_200_rule(Parser *p) return _res; } -// _loop0_202: ',' (expression ['as' star_target]) +// _loop0_204: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_202_rule(Parser *p) +_loop0_204_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37416,13 +38015,13 @@ _loop0_202_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_204[%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_263_rule(p)) // expression ['as' star_target] + (elem = _tmp_265_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -37448,7 +38047,7 @@ _loop0_202_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_202[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_204[%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); @@ -37465,9 +38064,9 @@ _loop0_202_rule(Parser *p) return _seq; } -// _gather_201: (expression ['as' star_target]) _loop0_202 +// _gather_203: (expression ['as' star_target]) _loop0_204 static asdl_seq * -_gather_201_rule(Parser *p) +_gather_203_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37479,27 +38078,27 @@ _gather_201_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_202 + { // (expression ['as' star_target]) _loop0_204 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_202")); + D(fprintf(stderr, "%*c> _gather_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_204")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_263_rule(p)) // expression ['as' star_target] + (elem = _tmp_265_rule(p)) // expression ['as' star_target] && - (seq = _loop0_202_rule(p)) // _loop0_202 + (seq = _loop0_204_rule(p)) // _loop0_204 ) { - D(fprintf(stderr, "%*c+ _gather_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_202")); + D(fprintf(stderr, "%*c+ _gather_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_204")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_201[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_202")); + D(fprintf(stderr, "%*c%s _gather_203[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_204")); } _res = NULL; done: @@ -37507,9 +38106,9 @@ _gather_201_rule(Parser *p) return _res; } -// _loop0_204: ',' (expressions ['as' star_target]) +// _loop0_206: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_204_rule(Parser *p) +_loop0_206_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37535,13 +38134,13 @@ _loop0_204_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_206[%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_264_rule(p)) // expressions ['as' star_target] + (elem = _tmp_266_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -37567,7 +38166,7 @@ _loop0_204_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_204[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_206[%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); @@ -37584,9 +38183,9 @@ _loop0_204_rule(Parser *p) return _seq; } -// _gather_203: (expressions ['as' star_target]) _loop0_204 +// _gather_205: (expressions ['as' star_target]) _loop0_206 static asdl_seq * -_gather_203_rule(Parser *p) +_gather_205_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37598,27 +38197,27 @@ _gather_203_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_204 + { // (expressions ['as' star_target]) _loop0_206 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_204")); + D(fprintf(stderr, "%*c> _gather_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_206")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_264_rule(p)) // expressions ['as' star_target] + (elem = _tmp_266_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_204_rule(p)) // _loop0_204 + (seq = _loop0_206_rule(p)) // _loop0_206 ) { - D(fprintf(stderr, "%*c+ _gather_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_204")); + D(fprintf(stderr, "%*c+ _gather_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_206")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_203[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_204")); + D(fprintf(stderr, "%*c%s _gather_205[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_206")); } _res = NULL; done: @@ -37626,9 +38225,9 @@ _gather_203_rule(Parser *p) return _res; } -// _loop0_206: ',' (expression ['as' star_target]) +// _loop0_208: ',' (expression ['as' star_target]) static asdl_seq * -_loop0_206_rule(Parser *p) +_loop0_208_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37654,13 +38253,13 @@ _loop0_206_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_208[%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_265_rule(p)) // expression ['as' star_target] + (elem = _tmp_267_rule(p)) // expression ['as' star_target] ) { _res = elem; @@ -37686,7 +38285,7 @@ _loop0_206_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_206[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_208[%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); @@ -37703,9 +38302,9 @@ _loop0_206_rule(Parser *p) return _seq; } -// _gather_205: (expression ['as' star_target]) _loop0_206 +// _gather_207: (expression ['as' star_target]) _loop0_208 static asdl_seq * -_gather_205_rule(Parser *p) +_gather_207_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37717,27 +38316,27 @@ _gather_205_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_206 + { // (expression ['as' star_target]) _loop0_208 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_206")); + D(fprintf(stderr, "%*c> _gather_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_208")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_265_rule(p)) // expression ['as' star_target] + (elem = _tmp_267_rule(p)) // expression ['as' star_target] && - (seq = _loop0_206_rule(p)) // _loop0_206 + (seq = _loop0_208_rule(p)) // _loop0_208 ) { - D(fprintf(stderr, "%*c+ _gather_205[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_206")); + D(fprintf(stderr, "%*c+ _gather_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_208")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_205[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_206")); + D(fprintf(stderr, "%*c%s _gather_207[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_208")); } _res = NULL; done: @@ -37745,9 +38344,9 @@ _gather_205_rule(Parser *p) return _res; } -// _loop0_208: ',' (expressions ['as' star_target]) +// _loop0_210: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_208_rule(Parser *p) +_loop0_210_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37773,13 +38372,13 @@ _loop0_208_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _loop0_210[%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_266_rule(p)) // expressions ['as' star_target] + (elem = _tmp_268_rule(p)) // expressions ['as' star_target] ) { _res = elem; @@ -37805,7 +38404,7 @@ _loop0_208_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_208[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_210[%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); @@ -37822,9 +38421,9 @@ _loop0_208_rule(Parser *p) return _seq; } -// _gather_207: (expressions ['as' star_target]) _loop0_208 +// _gather_209: (expressions ['as' star_target]) _loop0_210 static asdl_seq * -_gather_207_rule(Parser *p) +_gather_209_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37836,27 +38435,27 @@ _gather_207_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_208 + { // (expressions ['as' star_target]) _loop0_210 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_208")); + D(fprintf(stderr, "%*c> _gather_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_210")); void *elem; asdl_seq * seq; if ( - (elem = _tmp_266_rule(p)) // expressions ['as' star_target] + (elem = _tmp_268_rule(p)) // expressions ['as' star_target] && - (seq = _loop0_208_rule(p)) // _loop0_208 + (seq = _loop0_210_rule(p)) // _loop0_210 ) { - D(fprintf(stderr, "%*c+ _gather_207[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_208")); + D(fprintf(stderr, "%*c+ _gather_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_210")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_207[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_208")); + D(fprintf(stderr, "%*c%s _gather_209[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_210")); } _res = NULL; done: @@ -37864,9 +38463,9 @@ _gather_207_rule(Parser *p) return _res; } -// _tmp_209: 'except' | 'finally' +// _tmp_211: 'except' | 'finally' static void * -_tmp_209_rule(Parser *p) +_tmp_211_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37883,18 +38482,18 @@ _tmp_209_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 637)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_209[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_211[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } { // 'finally' @@ -37902,18 +38501,18 @@ _tmp_209_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 633)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_209[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_211[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_209[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_211[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; @@ -37922,9 +38521,9 @@ _tmp_209_rule(Parser *p) return _res; } -// _loop0_210: block +// _loop0_212: block static asdl_seq * -_loop0_210_rule(Parser *p) +_loop0_212_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -37950,7 +38549,7 @@ _loop0_210_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + D(fprintf(stderr, "%*c> _loop0_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); asdl_stmt_seq* block_var; while ( (block_var = block_rule(p)) // block @@ -37973,7 +38572,7 @@ _loop0_210_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_210[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_212[%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); @@ -37990,9 +38589,9 @@ _loop0_210_rule(Parser *p) return _seq; } -// _loop1_211: except_block +// _loop1_213: except_block static asdl_seq * -_loop1_211_rule(Parser *p) +_loop1_213_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38018,7 +38617,7 @@ _loop1_211_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); + D(fprintf(stderr, "%*c> _loop1_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); excepthandler_ty except_block_var; while ( (except_block_var = except_block_rule(p)) // except_block @@ -38041,7 +38640,7 @@ _loop1_211_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_211[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_213[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); } if (_n == 0 || p->error_indicator) { @@ -38063,9 +38662,9 @@ _loop1_211_rule(Parser *p) return _seq; } -// _tmp_212: 'as' NAME +// _tmp_214: 'as' NAME static void * -_tmp_212_rule(Parser *p) +_tmp_214_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38082,7 +38681,7 @@ _tmp_212_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -38091,12 +38690,12 @@ _tmp_212_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_212[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_212[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -38105,9 +38704,9 @@ _tmp_212_rule(Parser *p) return _res; } -// _loop0_213: block +// _loop0_215: block static asdl_seq * -_loop0_213_rule(Parser *p) +_loop0_215_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38133,7 +38732,7 @@ _loop0_213_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + D(fprintf(stderr, "%*c> _loop0_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); asdl_stmt_seq* block_var; while ( (block_var = block_rule(p)) // block @@ -38156,7 +38755,7 @@ _loop0_213_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_213[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_215[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38173,9 +38772,9 @@ _loop0_213_rule(Parser *p) return _seq; } -// _loop1_214: except_star_block +// _loop1_216: except_star_block static asdl_seq * -_loop1_214_rule(Parser *p) +_loop1_216_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38201,7 +38800,7 @@ _loop1_214_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); + D(fprintf(stderr, "%*c> _loop1_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); excepthandler_ty except_star_block_var; while ( (except_star_block_var = except_star_block_rule(p)) // except_star_block @@ -38224,7 +38823,7 @@ _loop1_214_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_214[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_216[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); } if (_n == 0 || p->error_indicator) { @@ -38246,9 +38845,9 @@ _loop1_214_rule(Parser *p) return _seq; } -// _tmp_215: expression ['as' NAME] +// _tmp_217: expression ['as' NAME] static void * -_tmp_215_rule(Parser *p) +_tmp_217_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38265,22 +38864,22 @@ _tmp_215_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_267_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_269_rule(p), !p->error_indicator) // ['as' NAME] ) { - D(fprintf(stderr, "%*c+ _tmp_215[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + D(fprintf(stderr, "%*c+ _tmp_217[%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_215[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_217[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' NAME]")); } _res = NULL; @@ -38289,9 +38888,9 @@ _tmp_215_rule(Parser *p) return _res; } -// _tmp_216: 'as' NAME +// _tmp_218: 'as' NAME static void * -_tmp_216_rule(Parser *p) +_tmp_218_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38308,7 +38907,7 @@ _tmp_216_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -38317,12 +38916,12 @@ _tmp_216_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_216[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_218[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_216[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_218[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -38331,9 +38930,9 @@ _tmp_216_rule(Parser *p) return _res; } -// _tmp_217: 'as' NAME +// _tmp_219: 'as' NAME static void * -_tmp_217_rule(Parser *p) +_tmp_219_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38350,7 +38949,7 @@ _tmp_217_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -38359,12 +38958,12 @@ _tmp_217_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_217[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_219[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_217[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_219[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -38373,9 +38972,9 @@ _tmp_217_rule(Parser *p) return _res; } -// _tmp_218: NEWLINE | ':' +// _tmp_220: NEWLINE | ':' static void * -_tmp_218_rule(Parser *p) +_tmp_220_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38392,18 +38991,18 @@ _tmp_218_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_220[%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_218[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_220[%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_218[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); } { // ':' @@ -38411,18 +39010,18 @@ _tmp_218_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_218[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_218[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; @@ -38431,9 +39030,9 @@ _tmp_218_rule(Parser *p) return _res; } -// _tmp_219: 'as' NAME +// _tmp_221: 'as' NAME static void * -_tmp_219_rule(Parser *p) +_tmp_221_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38450,7 +39049,7 @@ _tmp_219_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -38459,12 +39058,12 @@ _tmp_219_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_219[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_219[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_221[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -38473,9 +39072,9 @@ _tmp_219_rule(Parser *p) return _res; } -// _tmp_220: 'as' NAME +// _tmp_222: 'as' NAME static void * -_tmp_220_rule(Parser *p) +_tmp_222_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38492,7 +39091,7 @@ _tmp_220_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -38501,12 +39100,12 @@ _tmp_220_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -38515,9 +39114,9 @@ _tmp_220_rule(Parser *p) return _res; } -// _tmp_221: positional_patterns ',' +// _tmp_223: positional_patterns ',' static void * -_tmp_221_rule(Parser *p) +_tmp_223_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38534,7 +39133,7 @@ _tmp_221_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; asdl_pattern_seq* positional_patterns_var; if ( @@ -38543,12 +39142,12 @@ _tmp_221_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c+ _tmp_223[%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_221[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; @@ -38557,9 +39156,9 @@ _tmp_221_rule(Parser *p) return _res; } -// _tmp_222: '->' expression +// _tmp_224: '->' expression static void * -_tmp_222_rule(Parser *p) +_tmp_224_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38576,7 +39175,7 @@ _tmp_222_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty expression_var; if ( @@ -38585,12 +39184,12 @@ _tmp_222_rule(Parser *p) (expression_var = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = _PyPegen_dummy_name(p, _literal, expression_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -38599,9 +39198,9 @@ _tmp_222_rule(Parser *p) return _res; } -// _tmp_223: '(' arguments? ')' +// _tmp_225: '(' arguments? ')' static void * -_tmp_223_rule(Parser *p) +_tmp_225_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38618,7 +39217,7 @@ _tmp_223_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -38631,12 +39230,12 @@ _tmp_223_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -38645,9 +39244,9 @@ _tmp_223_rule(Parser *p) return _res; } -// _tmp_224: '(' arguments? ')' +// _tmp_226: '(' arguments? ')' static void * -_tmp_224_rule(Parser *p) +_tmp_226_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38664,7 +39263,7 @@ _tmp_224_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *_opt_var; @@ -38677,12 +39276,12 @@ _tmp_224_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -38691,9 +39290,9 @@ _tmp_224_rule(Parser *p) return _res; } -// _loop0_226: ',' double_starred_kvpair +// _loop0_228: ',' double_starred_kvpair static asdl_seq * -_loop0_226_rule(Parser *p) +_loop0_228_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38719,7 +39318,7 @@ _loop0_226_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; KeyValuePair* elem; while ( @@ -38751,7 +39350,7 @@ _loop0_226_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_226[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_228[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -38768,9 +39367,9 @@ _loop0_226_rule(Parser *p) return _seq; } -// _gather_225: double_starred_kvpair _loop0_226 +// _gather_227: double_starred_kvpair _loop0_228 static asdl_seq * -_gather_225_rule(Parser *p) +_gather_227_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38782,27 +39381,27 @@ _gather_225_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_226 + { // double_starred_kvpair _loop0_228 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_226")); + D(fprintf(stderr, "%*c> _gather_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_228")); KeyValuePair* elem; asdl_seq * seq; if ( (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_226_rule(p)) // _loop0_226 + (seq = _loop0_228_rule(p)) // _loop0_228 ) { - D(fprintf(stderr, "%*c+ _gather_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_226")); + D(fprintf(stderr, "%*c+ _gather_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_228")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_225[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_226")); + D(fprintf(stderr, "%*c%s _gather_227[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_228")); } _res = NULL; done: @@ -38810,9 +39409,9 @@ _gather_225_rule(Parser *p) return _res; } -// _tmp_227: '}' | ',' +// _tmp_229: '}' | ',' static void * -_tmp_227_rule(Parser *p) +_tmp_229_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38829,18 +39428,18 @@ _tmp_227_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -38848,18 +39447,18 @@ _tmp_227_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -38868,9 +39467,9 @@ _tmp_227_rule(Parser *p) return _res; } -// _tmp_228: '}' | ',' +// _tmp_230: '}' | ',' static void * -_tmp_228_rule(Parser *p) +_tmp_230_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38887,18 +39486,18 @@ _tmp_228_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } { // ',' @@ -38906,18 +39505,18 @@ _tmp_228_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; @@ -38926,9 +39525,9 @@ _tmp_228_rule(Parser *p) return _res; } -// _tmp_229: yield_expr | star_expressions +// _tmp_231: yield_expr | star_expressions static void * -_tmp_229_rule(Parser *p) +_tmp_231_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -38945,18 +39544,18 @@ _tmp_229_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -38964,18 +39563,18 @@ _tmp_229_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -38984,9 +39583,9 @@ _tmp_229_rule(Parser *p) return _res; } -// _tmp_230: yield_expr | star_expressions +// _tmp_232: yield_expr | star_expressions static void * -_tmp_230_rule(Parser *p) +_tmp_232_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39003,18 +39602,18 @@ _tmp_230_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39022,18 +39621,18 @@ _tmp_230_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39042,9 +39641,9 @@ _tmp_230_rule(Parser *p) return _res; } -// _tmp_231: '=' | '!' | ':' | '}' +// _tmp_233: '=' | '!' | ':' | '}' static void * -_tmp_231_rule(Parser *p) +_tmp_233_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39061,18 +39660,18 @@ _tmp_231_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } { // '!' @@ -39080,18 +39679,18 @@ _tmp_231_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -39099,18 +39698,18 @@ _tmp_231_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -39118,18 +39717,18 @@ _tmp_231_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -39138,9 +39737,9 @@ _tmp_231_rule(Parser *p) return _res; } -// _tmp_232: yield_expr | star_expressions +// _tmp_234: yield_expr | star_expressions static void * -_tmp_232_rule(Parser *p) +_tmp_234_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39157,18 +39756,18 @@ _tmp_232_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39176,18 +39775,18 @@ _tmp_232_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39196,9 +39795,9 @@ _tmp_232_rule(Parser *p) return _res; } -// _tmp_233: '!' | ':' | '}' +// _tmp_235: '!' | ':' | '}' static void * -_tmp_233_rule(Parser *p) +_tmp_235_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39215,18 +39814,18 @@ _tmp_233_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } { // ':' @@ -39234,18 +39833,18 @@ _tmp_233_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -39253,18 +39852,18 @@ _tmp_233_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_233[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -39273,9 +39872,9 @@ _tmp_233_rule(Parser *p) return _res; } -// _tmp_234: yield_expr | star_expressions +// _tmp_236: yield_expr | star_expressions static void * -_tmp_234_rule(Parser *p) +_tmp_236_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39292,18 +39891,18 @@ _tmp_234_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39311,18 +39910,18 @@ _tmp_234_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_234[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_234[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39331,9 +39930,9 @@ _tmp_234_rule(Parser *p) return _res; } -// _tmp_235: yield_expr | star_expressions +// _tmp_237: yield_expr | star_expressions static void * -_tmp_235_rule(Parser *p) +_tmp_237_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39350,18 +39949,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39369,18 +39968,18 @@ _tmp_235_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39389,9 +39988,9 @@ _tmp_235_rule(Parser *p) return _res; } -// _tmp_236: '!' NAME +// _tmp_238: '!' NAME static void * -_tmp_236_rule(Parser *p) +_tmp_238_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39408,7 +40007,7 @@ _tmp_236_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -39417,12 +40016,12 @@ _tmp_236_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -39431,9 +40030,9 @@ _tmp_236_rule(Parser *p) return _res; } -// _tmp_237: ':' | '}' +// _tmp_239: ':' | '}' static void * -_tmp_237_rule(Parser *p) +_tmp_239_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39450,18 +40049,18 @@ _tmp_237_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -39469,18 +40068,18 @@ _tmp_237_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -39489,9 +40088,9 @@ _tmp_237_rule(Parser *p) return _res; } -// _tmp_238: yield_expr | star_expressions +// _tmp_240: yield_expr | star_expressions static void * -_tmp_238_rule(Parser *p) +_tmp_240_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39508,18 +40107,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39527,18 +40126,18 @@ _tmp_238_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39547,9 +40146,9 @@ _tmp_238_rule(Parser *p) return _res; } -// _tmp_239: '!' NAME +// _tmp_241: '!' NAME static void * -_tmp_239_rule(Parser *p) +_tmp_241_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39566,7 +40165,7 @@ _tmp_239_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -39575,12 +40174,12 @@ _tmp_239_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_241[%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_239[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -39589,9 +40188,9 @@ _tmp_239_rule(Parser *p) return _res; } -// _loop0_240: fstring_format_spec +// _loop0_242: fstring_format_spec static asdl_seq * -_loop0_240_rule(Parser *p) +_loop0_242_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39617,7 +40216,7 @@ _loop0_240_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); + D(fprintf(stderr, "%*c> _loop0_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); expr_ty fstring_format_spec_var; while ( (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec @@ -39640,7 +40239,7 @@ _loop0_240_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_240[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_242[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -39657,9 +40256,9 @@ _loop0_240_rule(Parser *p) return _seq; } -// _tmp_241: yield_expr | star_expressions +// _tmp_243: yield_expr | star_expressions static void * -_tmp_241_rule(Parser *p) +_tmp_243_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39676,18 +40275,18 @@ _tmp_241_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -39695,18 +40294,18 @@ _tmp_241_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -39715,9 +40314,9 @@ _tmp_241_rule(Parser *p) return _res; } -// _tmp_242: '!' NAME +// _tmp_244: '!' NAME static void * -_tmp_242_rule(Parser *p) +_tmp_244_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39734,7 +40333,7 @@ _tmp_242_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); Token * _literal; expr_ty name_var; if ( @@ -39743,12 +40342,12 @@ _tmp_242_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_242[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c+ _tmp_244[%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_242[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; @@ -39757,9 +40356,9 @@ _tmp_242_rule(Parser *p) return _res; } -// _tmp_243: ':' | '}' +// _tmp_245: ':' | '}' static void * -_tmp_243_rule(Parser *p) +_tmp_245_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39776,18 +40375,18 @@ _tmp_243_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '}' @@ -39795,18 +40394,18 @@ _tmp_243_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; @@ -39815,9 +40414,9 @@ _tmp_243_rule(Parser *p) return _res; } -// _tmp_244: star_targets '=' +// _tmp_246: star_targets '=' static void * -_tmp_244_rule(Parser *p) +_tmp_246_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39834,7 +40433,7 @@ _tmp_244_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -39843,7 +40442,7 @@ _tmp_244_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -39853,7 +40452,7 @@ _tmp_244_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -39862,9 +40461,9 @@ _tmp_244_rule(Parser *p) return _res; } -// _tmp_245: '.' | '...' +// _tmp_247: '.' | '...' static void * -_tmp_245_rule(Parser *p) +_tmp_247_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39881,18 +40480,18 @@ _tmp_245_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -39900,18 +40499,18 @@ _tmp_245_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -39920,9 +40519,9 @@ _tmp_245_rule(Parser *p) return _res; } -// _tmp_246: '.' | '...' +// _tmp_248: '.' | '...' static void * -_tmp_246_rule(Parser *p) +_tmp_248_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39939,18 +40538,18 @@ _tmp_246_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -39958,18 +40557,18 @@ _tmp_246_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -39978,9 +40577,9 @@ _tmp_246_rule(Parser *p) return _res; } -// _tmp_247: '@' named_expression NEWLINE +// _tmp_249: '@' named_expression NEWLINE static void * -_tmp_247_rule(Parser *p) +_tmp_249_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -39997,7 +40596,7 @@ _tmp_247_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -40009,7 +40608,7 @@ _tmp_247_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40019,7 +40618,7 @@ _tmp_247_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -40028,9 +40627,9 @@ _tmp_247_rule(Parser *p) return _res; } -// _tmp_248: ',' expression +// _tmp_250: ',' expression static void * -_tmp_248_rule(Parser *p) +_tmp_250_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40047,7 +40646,7 @@ _tmp_248_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -40056,7 +40655,7 @@ _tmp_248_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40066,7 +40665,7 @@ _tmp_248_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -40075,9 +40674,9 @@ _tmp_248_rule(Parser *p) return _res; } -// _tmp_249: ',' star_expression +// _tmp_251: ',' star_expression static void * -_tmp_249_rule(Parser *p) +_tmp_251_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40094,7 +40693,7 @@ _tmp_249_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -40103,7 +40702,7 @@ _tmp_249_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40113,7 +40712,7 @@ _tmp_249_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -40122,9 +40721,9 @@ _tmp_249_rule(Parser *p) return _res; } -// _tmp_250: 'or' conjunction +// _tmp_252: 'or' conjunction static void * -_tmp_250_rule(Parser *p) +_tmp_252_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40141,7 +40740,7 @@ _tmp_250_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -40150,7 +40749,7 @@ _tmp_250_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40160,7 +40759,7 @@ _tmp_250_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -40169,9 +40768,9 @@ _tmp_250_rule(Parser *p) return _res; } -// _tmp_251: 'and' inversion +// _tmp_253: 'and' inversion static void * -_tmp_251_rule(Parser *p) +_tmp_253_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40188,7 +40787,7 @@ _tmp_251_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -40197,7 +40796,7 @@ _tmp_251_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40207,7 +40806,7 @@ _tmp_251_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -40216,9 +40815,9 @@ _tmp_251_rule(Parser *p) return _res; } -// _tmp_252: slice | starred_expression +// _tmp_254: slice | starred_expression static void * -_tmp_252_rule(Parser *p) +_tmp_254_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40235,18 +40834,18 @@ _tmp_252_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c> _tmp_254[%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_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c+ _tmp_254[%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_252[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice")); } { // starred_expression @@ -40254,18 +40853,18 @@ _tmp_252_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_254[%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_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_254[%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_252[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } _res = NULL; @@ -40274,9 +40873,9 @@ _tmp_252_rule(Parser *p) return _res; } -// _tmp_253: fstring | string +// _tmp_255: fstring | string static void * -_tmp_253_rule(Parser *p) +_tmp_255_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40293,18 +40892,18 @@ _tmp_253_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c> _tmp_255[%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_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c+ _tmp_255[%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_253[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring")); } { // string @@ -40312,18 +40911,18 @@ _tmp_253_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string")); + D(fprintf(stderr, "%*c> _tmp_255[%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_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); + D(fprintf(stderr, "%*c+ _tmp_255[%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_253[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "string")); } _res = NULL; @@ -40332,9 +40931,9 @@ _tmp_253_rule(Parser *p) return _res; } -// _tmp_254: 'if' disjunction +// _tmp_256: 'if' disjunction static void * -_tmp_254_rule(Parser *p) +_tmp_256_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40351,7 +40950,7 @@ _tmp_254_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -40360,7 +40959,7 @@ _tmp_254_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40370,7 +40969,7 @@ _tmp_254_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -40379,9 +40978,9 @@ _tmp_254_rule(Parser *p) return _res; } -// _tmp_255: 'if' disjunction +// _tmp_257: 'if' disjunction static void * -_tmp_255_rule(Parser *p) +_tmp_257_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40398,7 +40997,7 @@ _tmp_255_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -40407,7 +41006,7 @@ _tmp_255_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40417,7 +41016,7 @@ _tmp_255_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -40426,9 +41025,9 @@ _tmp_255_rule(Parser *p) return _res; } -// _tmp_256: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_258: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_256_rule(Parser *p) +_tmp_258_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40445,18 +41044,18 @@ _tmp_256_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c> _tmp_258[%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_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c+ _tmp_258[%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_256[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } { // (assignment_expression | expression !':=') !'=' @@ -40464,20 +41063,20 @@ _tmp_256_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_268_var; + D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_270_var; if ( - (_tmp_268_var = _tmp_268_rule(p)) // assignment_expression | expression !':=' + (_tmp_270_var = _tmp_270_rule(p)) // assignment_expression | expression !':=' && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_268_var; + D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_270_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; @@ -40486,9 +41085,9 @@ _tmp_256_rule(Parser *p) return _res; } -// _tmp_257: ',' star_target +// _tmp_259: ',' star_target static void * -_tmp_257_rule(Parser *p) +_tmp_259_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40505,7 +41104,7 @@ _tmp_257_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -40514,7 +41113,7 @@ _tmp_257_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40524,7 +41123,7 @@ _tmp_257_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -40533,9 +41132,9 @@ _tmp_257_rule(Parser *p) return _res; } -// _tmp_258: ',' star_target +// _tmp_260: ',' star_target static void * -_tmp_258_rule(Parser *p) +_tmp_260_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40552,7 +41151,7 @@ _tmp_258_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -40561,7 +41160,7 @@ _tmp_258_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -40571,7 +41170,7 @@ _tmp_258_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -40580,9 +41179,9 @@ _tmp_258_rule(Parser *p) return _res; } -// _tmp_259: star_targets '=' +// _tmp_261: star_targets '=' static void * -_tmp_259_rule(Parser *p) +_tmp_261_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40599,7 +41198,7 @@ _tmp_259_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -40608,12 +41207,12 @@ _tmp_259_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -40622,9 +41221,9 @@ _tmp_259_rule(Parser *p) return _res; } -// _tmp_260: star_targets '=' +// _tmp_262: star_targets '=' static void * -_tmp_260_rule(Parser *p) +_tmp_262_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40641,7 +41240,7 @@ _tmp_260_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -40650,12 +41249,12 @@ _tmp_260_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -40664,9 +41263,9 @@ _tmp_260_rule(Parser *p) return _res; } -// _tmp_261: ')' | '**' +// _tmp_263: ')' | '**' static void * -_tmp_261_rule(Parser *p) +_tmp_263_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40683,18 +41282,18 @@ _tmp_261_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -40702,18 +41301,18 @@ _tmp_261_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -40722,9 +41321,9 @@ _tmp_261_rule(Parser *p) return _res; } -// _tmp_262: ':' | '**' +// _tmp_264: ':' | '**' static void * -_tmp_262_rule(Parser *p) +_tmp_264_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40741,18 +41340,18 @@ _tmp_262_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -40760,18 +41359,18 @@ _tmp_262_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -40780,9 +41379,9 @@ _tmp_262_rule(Parser *p) return _res; } -// _tmp_263: expression ['as' star_target] +// _tmp_265: expression ['as' star_target] static void * -_tmp_263_rule(Parser *p) +_tmp_265_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40799,22 +41398,22 @@ _tmp_263_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_265[%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_269_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_271_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_265[%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_263[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -40823,9 +41422,9 @@ _tmp_263_rule(Parser *p) return _res; } -// _tmp_264: expressions ['as' star_target] +// _tmp_266: expressions ['as' star_target] static void * -_tmp_264_rule(Parser *p) +_tmp_266_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40842,22 +41441,22 @@ _tmp_264_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_266[%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_270_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_272_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_266[%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_264[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -40866,9 +41465,9 @@ _tmp_264_rule(Parser *p) return _res; } -// _tmp_265: expression ['as' star_target] +// _tmp_267: expression ['as' star_target] static void * -_tmp_265_rule(Parser *p) +_tmp_267_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40885,22 +41484,22 @@ _tmp_265_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_267[%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_271_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_273_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_267[%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_265[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; @@ -40909,9 +41508,9 @@ _tmp_265_rule(Parser *p) return _res; } -// _tmp_266: expressions ['as' star_target] +// _tmp_268: expressions ['as' star_target] static void * -_tmp_266_rule(Parser *p) +_tmp_268_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40928,22 +41527,22 @@ _tmp_266_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c> _tmp_268[%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_272_rule(p), !p->error_indicator) // ['as' star_target] + (_opt_var = _tmp_274_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c+ _tmp_268[%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_266[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; @@ -40952,9 +41551,9 @@ _tmp_266_rule(Parser *p) return _res; } -// _tmp_267: 'as' NAME +// _tmp_269: 'as' NAME static void * -_tmp_267_rule(Parser *p) +_tmp_269_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -40971,7 +41570,7 @@ _tmp_267_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty name_var; if ( @@ -40980,12 +41579,12 @@ _tmp_267_rule(Parser *p) (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = _PyPegen_dummy_name(p, _keyword, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -40994,9 +41593,9 @@ _tmp_267_rule(Parser *p) return _res; } -// _tmp_268: assignment_expression | expression !':=' +// _tmp_270: assignment_expression | expression !':=' static void * -_tmp_268_rule(Parser *p) +_tmp_270_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -41013,18 +41612,18 @@ _tmp_268_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); expr_ty assignment_expression_var; if ( (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } { // expression !':=' @@ -41032,7 +41631,7 @@ _tmp_268_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); expr_ty expression_var; if ( (expression_var = expression_rule(p)) // expression @@ -41040,12 +41639,12 @@ _tmp_268_rule(Parser *p) _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_268[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_268[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; @@ -41054,9 +41653,9 @@ _tmp_268_rule(Parser *p) return _res; } -// _tmp_269: 'as' star_target +// _tmp_271: 'as' star_target static void * -_tmp_269_rule(Parser *p) +_tmp_271_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -41073,7 +41672,7 @@ _tmp_269_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -41082,12 +41681,12 @@ _tmp_269_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_271[%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_269[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -41096,9 +41695,9 @@ _tmp_269_rule(Parser *p) return _res; } -// _tmp_270: 'as' star_target +// _tmp_272: 'as' star_target static void * -_tmp_270_rule(Parser *p) +_tmp_272_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -41115,7 +41714,7 @@ _tmp_270_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -41124,12 +41723,12 @@ _tmp_270_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_272[%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_270[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -41138,9 +41737,9 @@ _tmp_270_rule(Parser *p) return _res; } -// _tmp_271: 'as' star_target +// _tmp_273: 'as' star_target static void * -_tmp_271_rule(Parser *p) +_tmp_273_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -41157,7 +41756,7 @@ _tmp_271_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -41166,12 +41765,12 @@ _tmp_271_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_273[%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_271[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -41180,9 +41779,9 @@ _tmp_271_rule(Parser *p) return _res; } -// _tmp_272: 'as' star_target +// _tmp_274: 'as' star_target static void * -_tmp_272_rule(Parser *p) +_tmp_274_rule(Parser *p) { if (p->level++ == MAXSTACK) { p->error_indicator = 1; @@ -41199,7 +41798,7 @@ _tmp_272_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -41208,12 +41807,12 @@ _tmp_272_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_274[%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_272[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; diff --git a/Parser/pegen.c b/Parser/pegen.c index da410ea84ecb8e..b031a6f5d440e8 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -208,7 +208,7 @@ int _PyPegen_fill_token(Parser *p) { struct token new_token; - new_token.metadata = NULL; + _PyToken_Init(&new_token); int type = _PyTokenizer_Get(p->tok, &new_token); // Record and skip '# type: ignore' comments @@ -251,7 +251,7 @@ _PyPegen_fill_token(Parser *p) Token *t = p->tokens[p->fill]; return initialize_token(p, t, &new_token, type); error: - Py_XDECREF(new_token.metadata); + _PyToken_Free(&new_token); return -1; } diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 1f227da0194e3c..af529057f50e70 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -165,7 +165,7 @@ _PyPegen_tokenize_full_source_to_check_for_errors(Parser *p) { int ret = 0; struct token new_token; - new_token.metadata = NULL; + _PyToken_Init(&new_token); for (;;) { switch (_PyTokenizer_Get(p->tok, &new_token)) { @@ -193,7 +193,7 @@ _PyPegen_tokenize_full_source_to_check_for_errors(Parser *p) { exit: - Py_XDECREF(new_token.metadata); + _PyToken_Free(&new_token); // If we're in an f-string, we want the syntax error in the expression part // to propagate, so that tokenizer errors (like expecting '}') that happen afterwards // do not swallow it. diff --git a/Parser/token.c b/Parser/token.c index 82267fbfcd0c54..2bc963a91c7701 100644 --- a/Parser/token.c +++ b/Parser/token.c @@ -70,9 +70,9 @@ const char * const _PyParser_TokenNames[] = { "FSTRING_START", "FSTRING_MIDDLE", "FSTRING_END", + "COMMENT", + "NL", "", - "", - "", "", "", }; diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 91ffabac56c7b3..472d4174726354 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -111,6 +111,8 @@ tok_new(void) tok->interactive_underflow = IUNDERFLOW_NORMAL; tok->str = NULL; tok->report_warnings = 1; + tok->tok_extra_tokens = 0; + tok->comment_newline = 0; tok->tok_mode_stack[0] = (tokenizer_mode){.kind =TOK_REGULAR_MODE, .f_string_quote='\0', .f_string_quote_size = 0, .f_string_debug=0}; tok->tok_mode_stack_index = 0; tok->tok_report_warnings = 1; @@ -980,6 +982,16 @@ _PyTokenizer_Free(struct tok_state *tok) PyMem_Free(tok); } +void +_PyToken_Free(struct token *token) { + Py_XDECREF(token->metadata); +} + +void +_PyToken_Init(struct token *token) { + token->metadata = NULL; +} + static int tok_readline_raw(struct tok_state *tok) { @@ -1124,7 +1136,7 @@ tok_underflow_interactive(struct tok_state *tok) { static int tok_underflow_file(struct tok_state *tok) { - if (tok->start == NULL) { + if (tok->start == NULL && !INSIDE_FSTRING(tok)) { tok->cur = tok->inp = tok->buf; } if (tok->decoding_state == STATE_INIT) { @@ -1544,14 +1556,11 @@ verify_identifier(struct tok_state *tok) tok->cur = (char *)tok->start + PyBytes_GET_SIZE(s); } Py_DECREF(s); - // PyUnicode_FromFormatV() does not support %X - char hex[9]; - (void)PyOS_snprintf(hex, sizeof(hex), "%04X", ch); if (Py_UNICODE_ISPRINTABLE(ch)) { - syntaxerror(tok, "invalid character '%c' (U+%s)", ch, hex); + syntaxerror(tok, "invalid character '%c' (U+%04X)", ch, ch); } else { - syntaxerror(tok, "invalid non-printable character U+%s", hex); + syntaxerror(tok, "invalid non-printable character U+%04X", ch); } return 0; } @@ -1636,6 +1645,7 @@ token_setup(struct tok_state *tok, struct token *token, int type, const char *st return type; } + static int tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct token *token) { @@ -1649,6 +1659,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t tok->starting_col_offset = -1; blankline = 0; + /* Get indentation level */ if (tok->atbol) { int col = 0; @@ -1749,12 +1760,20 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t tok->starting_col_offset = tok->col_offset; /* Return pending indents/dedents */ - if (tok->pendin != 0) { + if (tok->pendin != 0) { if (tok->pendin < 0) { + if (tok->tok_extra_tokens) { + p_start = tok->cur; + p_end = tok->cur; + } tok->pendin++; return MAKE_TOKEN(DEDENT); } else { + if (tok->tok_extra_tokens) { + p_start = tok->buf; + p_end = tok->cur; + } tok->pendin--; return MAKE_TOKEN(INDENT); } @@ -1799,17 +1818,18 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t /* Skip comment, unless it's a type comment */ if (c == '#') { - if (INSIDE_FSTRING(tok)) { - return MAKE_TOKEN(syntaxerror(tok, "f-string expression part cannot include '#'")); - } - - const char *prefix, *p, *type_start; + const char* p = NULL; + const char *prefix, *type_start; int current_starting_col_offset; while (c != EOF && c != '\n') { c = tok_nextc(tok); } + if (tok->tok_extra_tokens) { + p = tok->start; + } + if (tok->type_comments) { p = tok->start; current_starting_col_offset = tok->starting_col_offset; @@ -1864,6 +1884,13 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t } } } + if (tok->tok_extra_tokens) { + tok_backup(tok, c); /* don't eat the newline or EOF */ + p_start = p; + p_end = tok->cur; + tok->comment_newline = blankline; + return MAKE_TOKEN(COMMENT); + } } if (tok->done == E_INTERACT_STOP) { @@ -1949,6 +1976,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t struct tok_state ahead_tok; struct token ahead_token; + _PyToken_Init(&ahead_token); int ahead_tok_kind; memcpy(&ahead_tok, tok, sizeof(ahead_tok)); @@ -1964,8 +1992,10 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t returning a plain NAME token, return ASYNC. */ tok->async_def_indent = tok->indent; tok->async_def = 1; + _PyToken_Free(&ahead_token); return MAKE_TOKEN(ASYNC); } + _PyToken_Free(&ahead_token); } } @@ -1976,8 +2006,19 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t if (c == '\n') { tok->atbol = 1; if (blankline || tok->level > 0) { + if (tok->tok_extra_tokens) { + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(NL); + } goto nextline; } + if (tok->comment_newline && tok->tok_extra_tokens) { + tok->comment_newline = 0; + p_start = tok->start; + p_end = tok->cur; + return MAKE_TOKEN(NL); + } p_start = tok->start; p_end = tok->cur - 1; /* Leave '\n' out of the string */ tok->cont_line = 0; @@ -2250,6 +2291,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t the_current_tok->f_string_quote_size = quote_size; the_current_tok->f_string_start = tok->start; the_current_tok->f_string_multi_line_start = tok->line_start; + the_current_tok->f_string_line_start = tok->lineno; the_current_tok->f_string_start_offset = -1; the_current_tok->f_string_multi_line_start_offset = -1; the_current_tok->last_expr_buffer = NULL; @@ -2492,9 +2534,7 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t } if (!Py_UNICODE_ISPRINTABLE(c)) { - char hex[9]; - (void)PyOS_snprintf(hex, sizeof(hex), "%04X", c); - return MAKE_TOKEN(syntaxerror(tok, "invalid non-printable character U+%s", hex)); + return MAKE_TOKEN(syntaxerror(tok, "invalid non-printable character U+%04X", c)); } if( c == '=' && INSIDE_FSTRING_EXPR(current_tok)) { @@ -2562,6 +2602,9 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct f_string_middle: + // TODO: This is a bit of a hack, but it works for now. We need to find a better way to handle + // this. + tok->multi_line_start = tok->line_start; while (end_quote_size != current_tok->f_string_quote_size) { int c = tok_nextc(tok); if (tok->done == E_ERROR) { @@ -2580,7 +2623,9 @@ tok_get_fstring_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct tok->cur++; tok->line_start = current_tok->f_string_multi_line_start; int start = tok->lineno; - tok->lineno = tok->first_lineno; + + tokenizer_mode *the_current_tok = TOK_GET_MODE(tok); + tok->lineno = the_current_tok->f_string_line_start; if (current_tok->f_string_quote_size == 3) { return MAKE_TOKEN(syntaxerror(tok, @@ -2785,7 +2830,9 @@ _PyTokenizer_FindEncodingFilename(int fd, PyObject *filename) // if fetching the encoding shows a warning. tok->report_warnings = 0; while (tok->lineno < 2 && tok->done == E_OK) { + _PyToken_Init(&token); _PyTokenizer_Get(tok, &token); + _PyToken_Free(&token); } fclose(fp); if (tok->encoding) { diff --git a/Parser/tokenizer.h b/Parser/tokenizer.h index 5e2171885ac75b..3f34763239acda 100644 --- a/Parser/tokenizer.h +++ b/Parser/tokenizer.h @@ -53,6 +53,7 @@ typedef struct _tokenizer_mode { int f_string_raw; const char* f_string_start; const char* f_string_multi_line_start; + int f_string_line_start; Py_ssize_t f_string_start_offset; Py_ssize_t f_string_multi_line_start_offset; @@ -127,6 +128,8 @@ struct tok_state { tokenizer_mode tok_mode_stack[MAXFSTRINGLEVEL]; int tok_mode_stack_index; int tok_report_warnings; + int tok_extra_tokens; + int comment_newline; #ifdef Py_DEBUG int debug; #endif @@ -137,6 +140,8 @@ extern struct tok_state *_PyTokenizer_FromUTF8(const char *, int); extern struct tok_state *_PyTokenizer_FromFile(FILE *, const char*, const char *, const char *); extern void _PyTokenizer_Free(struct tok_state *); +extern void _PyToken_Free(struct token *); +extern void _PyToken_Init(struct token *); extern int _PyTokenizer_Get(struct tok_state *, struct token *); #define tok_dump _Py_tok_dump diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 81ab71c0fc3b29..87906d975d7414 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -131,6 +131,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->Not_type); Py_CLEAR(state->Or_singleton); Py_CLEAR(state->Or_type); + Py_CLEAR(state->ParamSpec_type); Py_CLEAR(state->Pass_type); Py_CLEAR(state->Pow_singleton); Py_CLEAR(state->Pow_type); @@ -150,7 +151,10 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->TryStar_type); Py_CLEAR(state->Try_type); Py_CLEAR(state->Tuple_type); + Py_CLEAR(state->TypeAlias_type); Py_CLEAR(state->TypeIgnore_type); + Py_CLEAR(state->TypeVarTuple_type); + Py_CLEAR(state->TypeVar_type); Py_CLEAR(state->UAdd_singleton); Py_CLEAR(state->UAdd_type); Py_CLEAR(state->USub_singleton); @@ -179,6 +183,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->bases); Py_CLEAR(state->body); Py_CLEAR(state->boolop_type); + Py_CLEAR(state->bound); Py_CLEAR(state->cases); Py_CLEAR(state->cause); Py_CLEAR(state->cls); @@ -256,6 +261,8 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->type_comment); Py_CLEAR(state->type_ignore_type); Py_CLEAR(state->type_ignores); + Py_CLEAR(state->type_param_type); + Py_CLEAR(state->type_params); Py_CLEAR(state->unaryop_type); Py_CLEAR(state->upper); Py_CLEAR(state->value); @@ -289,6 +296,7 @@ static int init_identifiers(struct ast_state *state) if ((state->attr = PyUnicode_InternFromString("attr")) == NULL) return 0; if ((state->bases = PyUnicode_InternFromString("bases")) == NULL) return 0; if ((state->body = PyUnicode_InternFromString("body")) == NULL) return 0; + if ((state->bound = PyUnicode_InternFromString("bound")) == NULL) return 0; if ((state->cases = PyUnicode_InternFromString("cases")) == NULL) return 0; if ((state->cause = PyUnicode_InternFromString("cause")) == NULL) return 0; if ((state->cls = PyUnicode_InternFromString("cls")) == NULL) return 0; @@ -354,6 +362,7 @@ static int init_identifiers(struct ast_state *state) if ((state->type = PyUnicode_InternFromString("type")) == NULL) return 0; if ((state->type_comment = PyUnicode_InternFromString("type_comment")) == NULL) return 0; if ((state->type_ignores = PyUnicode_InternFromString("type_ignores")) == NULL) return 0; + if ((state->type_params = PyUnicode_InternFromString("type_params")) == NULL) return 0; if ((state->upper = PyUnicode_InternFromString("upper")) == NULL) return 0; if ((state->value = PyUnicode_InternFromString("value")) == NULL) return 0; if ((state->values = PyUnicode_InternFromString("values")) == NULL) return 0; @@ -374,6 +383,7 @@ GENERATE_ASDL_SEQ_CONSTRUCTOR(withitem, withitem_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(match_case, match_case_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(pattern, pattern_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(type_ignore, type_ignore_ty) +GENERATE_ASDL_SEQ_CONSTRUCTOR(type_param, type_param_ty) static PyObject* ast2obj_mod(struct ast_state *state, void*); static const char * const Module_fields[]={ @@ -399,6 +409,7 @@ static const char * const stmt_attributes[] = { static PyObject* ast2obj_stmt(struct ast_state *state, void*); static const char * const FunctionDef_fields[]={ "name", + "type_params", "args", "body", "decorator_list", @@ -407,6 +418,7 @@ static const char * const FunctionDef_fields[]={ }; static const char * const AsyncFunctionDef_fields[]={ "name", + "type_params", "args", "body", "decorator_list", @@ -415,6 +427,7 @@ static const char * const AsyncFunctionDef_fields[]={ }; static const char * const ClassDef_fields[]={ "name", + "type_params", "bases", "keywords", "body", @@ -431,6 +444,11 @@ static const char * const Assign_fields[]={ "value", "type_comment", }; +static const char * const TypeAlias_fields[]={ + "name", + "type_params", + "value", +}; static const char * const AugAssign_fields[]={ "target", "op", @@ -757,6 +775,23 @@ static const char * const TypeIgnore_fields[]={ "lineno", "tag", }; +static const char * const type_param_attributes[] = { + "lineno", + "col_offset", + "end_lineno", + "end_col_offset", +}; +static PyObject* ast2obj_type_param(struct ast_state *state, void*); +static const char * const TypeVar_fields[]={ + "name", + "bound", +}; +static const char * const ParamSpec_fields[]={ + "name", +}; +static const char * const TypeVarTuple_fields[]={ + "name", +}; @@ -1134,12 +1169,13 @@ init_types(struct ast_state *state) "FunctionType(expr* argtypes, expr returns)"); if (!state->FunctionType_type) return 0; state->stmt_type = make_type(state, "stmt", state->AST_type, NULL, 0, - "stmt = FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)\n" - " | AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)\n" - " | ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, expr* decorator_list)\n" + "stmt = FunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)\n" + " | AsyncFunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)\n" + " | ClassDef(identifier name, type_param* type_params, expr* bases, keyword* keywords, stmt* body, expr* decorator_list)\n" " | Return(expr? value)\n" " | Delete(expr* targets)\n" " | Assign(expr* targets, expr value, string? type_comment)\n" + " | TypeAlias(expr name, type_param* type_params, expr value)\n" " | AugAssign(expr target, operator op, expr value)\n" " | AnnAssign(expr target, expr annotation, expr? value, int simple)\n" " | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)\n" @@ -1169,8 +1205,8 @@ init_types(struct ast_state *state) -1) return 0; state->FunctionDef_type = make_type(state, "FunctionDef", state->stmt_type, - FunctionDef_fields, 6, - "FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)"); + FunctionDef_fields, 7, + "FunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)"); if (!state->FunctionDef_type) return 0; if (PyObject_SetAttr(state->FunctionDef_type, state->returns, Py_None) == -1) @@ -1180,8 +1216,8 @@ init_types(struct ast_state *state) return 0; state->AsyncFunctionDef_type = make_type(state, "AsyncFunctionDef", state->stmt_type, - AsyncFunctionDef_fields, 6, - "AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)"); + AsyncFunctionDef_fields, 7, + "AsyncFunctionDef(identifier name, type_param* type_params, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment)"); if (!state->AsyncFunctionDef_type) return 0; if (PyObject_SetAttr(state->AsyncFunctionDef_type, state->returns, Py_None) == -1) @@ -1190,8 +1226,8 @@ init_types(struct ast_state *state) Py_None) == -1) return 0; state->ClassDef_type = make_type(state, "ClassDef", state->stmt_type, - ClassDef_fields, 5, - "ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, expr* decorator_list)"); + ClassDef_fields, 6, + "ClassDef(identifier name, type_param* type_params, expr* bases, keyword* keywords, stmt* body, expr* decorator_list)"); if (!state->ClassDef_type) return 0; state->Return_type = make_type(state, "Return", state->stmt_type, Return_fields, 1, @@ -1210,6 +1246,10 @@ init_types(struct ast_state *state) if (PyObject_SetAttr(state->Assign_type, state->type_comment, Py_None) == -1) return 0; + state->TypeAlias_type = make_type(state, "TypeAlias", state->stmt_type, + TypeAlias_fields, 3, + "TypeAlias(expr name, type_param* type_params, expr value)"); + if (!state->TypeAlias_type) return 0; state->AugAssign_type = make_type(state, "AugAssign", state->stmt_type, AugAssign_fields, 3, "AugAssign(expr target, operator op, expr value)"); @@ -1854,6 +1894,36 @@ init_types(struct ast_state *state) TypeIgnore_fields, 2, "TypeIgnore(int lineno, string tag)"); if (!state->TypeIgnore_type) return 0; + state->type_param_type = make_type(state, "type_param", state->AST_type, + NULL, 0, + "type_param = TypeVar(identifier name, expr? bound)\n" + " | ParamSpec(identifier name)\n" + " | TypeVarTuple(identifier name)"); + if (!state->type_param_type) return 0; + if (!add_attributes(state, state->type_param_type, type_param_attributes, + 4)) return 0; + if (PyObject_SetAttr(state->type_param_type, state->end_lineno, Py_None) == + -1) + return 0; + if (PyObject_SetAttr(state->type_param_type, state->end_col_offset, + Py_None) == -1) + return 0; + state->TypeVar_type = make_type(state, "TypeVar", state->type_param_type, + TypeVar_fields, 2, + "TypeVar(identifier name, expr? bound)"); + if (!state->TypeVar_type) return 0; + if (PyObject_SetAttr(state->TypeVar_type, state->bound, Py_None) == -1) + return 0; + state->ParamSpec_type = make_type(state, "ParamSpec", + state->type_param_type, ParamSpec_fields, + 1, + "ParamSpec(identifier name)"); + if (!state->ParamSpec_type) return 0; + state->TypeVarTuple_type = make_type(state, "TypeVarTuple", + state->type_param_type, + TypeVarTuple_fields, 1, + "TypeVarTuple(identifier name)"); + if (!state->TypeVarTuple_type) return 0; state->recursion_depth = 0; state->recursion_limit = 0; @@ -1897,6 +1967,8 @@ static int obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, PyArena* arena); static int obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* out, PyArena* arena); +static int obj2ast_type_param(struct ast_state *state, PyObject* obj, + type_param_ty* out, PyArena* arena); mod_ty _PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores, @@ -1960,10 +2032,11 @@ _PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena *arena) } stmt_ty -_PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * body, - asdl_expr_seq * decorator_list, expr_ty returns, string - type_comment, int lineno, int col_offset, int end_lineno, - int end_col_offset, PyArena *arena) +_PyAST_FunctionDef(identifier name, asdl_type_param_seq * type_params, + arguments_ty args, asdl_stmt_seq * body, asdl_expr_seq * + decorator_list, expr_ty returns, string type_comment, int + lineno, int col_offset, int end_lineno, int end_col_offset, + PyArena *arena) { stmt_ty p; if (!name) { @@ -1981,6 +2054,7 @@ _PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * body, return NULL; p->kind = FunctionDef_kind; p->v.FunctionDef.name = name; + p->v.FunctionDef.type_params = type_params; p->v.FunctionDef.args = args; p->v.FunctionDef.body = body; p->v.FunctionDef.decorator_list = decorator_list; @@ -1994,10 +2068,11 @@ _PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * body, } stmt_ty -_PyAST_AsyncFunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * - body, asdl_expr_seq * decorator_list, expr_ty returns, - string type_comment, int lineno, int col_offset, int - end_lineno, int end_col_offset, PyArena *arena) +_PyAST_AsyncFunctionDef(identifier name, asdl_type_param_seq * type_params, + arguments_ty args, asdl_stmt_seq * body, asdl_expr_seq + * decorator_list, expr_ty returns, string type_comment, + int lineno, int col_offset, int end_lineno, int + end_col_offset, PyArena *arena) { stmt_ty p; if (!name) { @@ -2015,6 +2090,7 @@ _PyAST_AsyncFunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * return NULL; p->kind = AsyncFunctionDef_kind; p->v.AsyncFunctionDef.name = name; + p->v.AsyncFunctionDef.type_params = type_params; p->v.AsyncFunctionDef.args = args; p->v.AsyncFunctionDef.body = body; p->v.AsyncFunctionDef.decorator_list = decorator_list; @@ -2028,9 +2104,10 @@ _PyAST_AsyncFunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * } stmt_ty -_PyAST_ClassDef(identifier name, asdl_expr_seq * bases, asdl_keyword_seq * - keywords, asdl_stmt_seq * body, asdl_expr_seq * decorator_list, - int lineno, int col_offset, int end_lineno, int end_col_offset, +_PyAST_ClassDef(identifier name, asdl_type_param_seq * type_params, + asdl_expr_seq * bases, asdl_keyword_seq * keywords, + asdl_stmt_seq * body, asdl_expr_seq * decorator_list, int + lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena) { stmt_ty p; @@ -2044,6 +2121,7 @@ _PyAST_ClassDef(identifier name, asdl_expr_seq * bases, asdl_keyword_seq * return NULL; p->kind = ClassDef_kind; p->v.ClassDef.name = name; + p->v.ClassDef.type_params = type_params; p->v.ClassDef.bases = bases; p->v.ClassDef.keywords = keywords; p->v.ClassDef.body = body; @@ -2114,6 +2192,36 @@ _PyAST_Assign(asdl_expr_seq * targets, expr_ty value, string type_comment, int return p; } +stmt_ty +_PyAST_TypeAlias(expr_ty name, asdl_type_param_seq * type_params, expr_ty + value, int lineno, int col_offset, int end_lineno, int + end_col_offset, PyArena *arena) +{ + stmt_ty p; + if (!name) { + PyErr_SetString(PyExc_ValueError, + "field 'name' is required for TypeAlias"); + return NULL; + } + if (!value) { + PyErr_SetString(PyExc_ValueError, + "field 'value' is required for TypeAlias"); + return NULL; + } + p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = TypeAlias_kind; + p->v.TypeAlias.name = name; + p->v.TypeAlias.type_params = type_params; + p->v.TypeAlias.value = value; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + stmt_ty _PyAST_AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena) @@ -3606,6 +3714,73 @@ _PyAST_TypeIgnore(int lineno, string tag, PyArena *arena) return p; } +type_param_ty +_PyAST_TypeVar(identifier name, expr_ty bound, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena) +{ + type_param_ty p; + if (!name) { + PyErr_SetString(PyExc_ValueError, + "field 'name' is required for TypeVar"); + return NULL; + } + p = (type_param_ty)_PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = TypeVar_kind; + p->v.TypeVar.name = name; + p->v.TypeVar.bound = bound; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + +type_param_ty +_PyAST_ParamSpec(identifier name, int lineno, int col_offset, int end_lineno, + int end_col_offset, PyArena *arena) +{ + type_param_ty p; + if (!name) { + PyErr_SetString(PyExc_ValueError, + "field 'name' is required for ParamSpec"); + return NULL; + } + p = (type_param_ty)_PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = ParamSpec_kind; + p->v.ParamSpec.name = name; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + +type_param_ty +_PyAST_TypeVarTuple(identifier name, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena) +{ + type_param_ty p; + if (!name) { + PyErr_SetString(PyExc_ValueError, + "field 'name' is required for TypeVarTuple"); + return NULL; + } + p = (type_param_ty)_PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = TypeVarTuple_kind; + p->v.TypeVarTuple.name = name; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + PyObject* ast2obj_mod(struct ast_state *state, void* _o) @@ -3708,6 +3883,12 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.type_params, + ast2obj_type_param); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->type_params, value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_arguments(state, o->v.FunctionDef.args); if (!value) goto failed; if (PyObject_SetAttr(result, state->args, value) == -1) @@ -3745,6 +3926,13 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_list(state, + (asdl_seq*)o->v.AsyncFunctionDef.type_params, + ast2obj_type_param); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->type_params, value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_arguments(state, o->v.AsyncFunctionDef.args); if (!value) goto failed; if (PyObject_SetAttr(result, state->args, value) == -1) @@ -3783,6 +3971,12 @@ ast2obj_stmt(struct ast_state *state, void* _o) if (PyObject_SetAttr(result, state->name, value) == -1) goto failed; Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.type_params, + ast2obj_type_param); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->type_params, value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.bases, ast2obj_expr); if (!value) goto failed; @@ -3850,6 +4044,27 @@ ast2obj_stmt(struct ast_state *state, void* _o) goto failed; Py_DECREF(value); break; + case TypeAlias_kind: + tp = (PyTypeObject *)state->TypeAlias_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(state, o->v.TypeAlias.name); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->name, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->v.TypeAlias.type_params, + ast2obj_type_param); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->type_params, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(state, o->v.TypeAlias.value); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->value, value) == -1) + goto failed; + Py_DECREF(value); + break; case AugAssign_kind: tp = (PyTypeObject *)state->AugAssign_type; result = PyType_GenericNew(tp, NULL, NULL); @@ -5441,6 +5656,85 @@ ast2obj_type_ignore(struct ast_state *state, void* _o) return NULL; } +PyObject* +ast2obj_type_param(struct ast_state *state, void* _o) +{ + type_param_ty o = (type_param_ty)_o; + PyObject *result = NULL, *value = NULL; + PyTypeObject *tp; + if (!o) { + Py_RETURN_NONE; + } + if (++state->recursion_depth > state->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during ast construction"); + return 0; + } + switch (o->kind) { + case TypeVar_kind: + tp = (PyTypeObject *)state->TypeVar_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_identifier(state, o->v.TypeVar.name); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->name, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(state, o->v.TypeVar.bound); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->bound, value) == -1) + goto failed; + Py_DECREF(value); + break; + case ParamSpec_kind: + tp = (PyTypeObject *)state->ParamSpec_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_identifier(state, o->v.ParamSpec.name); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->name, value) == -1) + goto failed; + Py_DECREF(value); + break; + case TypeVarTuple_kind: + tp = (PyTypeObject *)state->TypeVarTuple_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_identifier(state, o->v.TypeVarTuple.name); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->name, value) == -1) + goto failed; + Py_DECREF(value); + break; + } + value = ast2obj_int(state, o->lineno); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->lineno, value) < 0) + goto failed; + Py_DECREF(value); + value = ast2obj_int(state, o->col_offset); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->col_offset, value) < 0) + goto failed; + Py_DECREF(value); + value = ast2obj_int(state, o->end_lineno); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->end_lineno, value) < 0) + goto failed; + Py_DECREF(value); + value = ast2obj_int(state, o->end_col_offset); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->end_col_offset, value) < 0) + goto failed; + Py_DECREF(value); + state->recursion_depth--; + return result; +failed: + Py_XDECREF(value); + Py_XDECREF(result); + return NULL; +} + int obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) @@ -5781,6 +6075,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } if (isinstance) { identifier name; + asdl_type_param_seq* type_params; arguments_ty args; asdl_stmt_seq* body; asdl_expr_seq* decorator_list; @@ -5804,6 +6099,42 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (res != 0) goto failed; Py_CLEAR(tmp); } + if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from FunctionDef"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "FunctionDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + type_params = _Py_asdl_type_param_seq_new(len, arena); + if (type_params == NULL) goto failed; + for (i = 0; i < len; i++) { + type_param_ty val; + PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i)); + if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { + goto failed; + } + res = obj2ast_type_param(state, tmp2, &val, arena); + _Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "FunctionDef field \"type_params\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(type_params, i, val); + } + Py_CLEAR(tmp); + } if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) { return 1; } @@ -5927,8 +6258,9 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (res != 0) goto failed; Py_CLEAR(tmp); } - *out = _PyAST_FunctionDef(name, args, body, decorator_list, returns, - type_comment, lineno, col_offset, end_lineno, + *out = _PyAST_FunctionDef(name, type_params, args, body, + decorator_list, returns, type_comment, + lineno, col_offset, end_lineno, end_col_offset, arena); if (*out == NULL) goto failed; return 0; @@ -5940,6 +6272,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } if (isinstance) { identifier name; + asdl_type_param_seq* type_params; arguments_ty args; asdl_stmt_seq* body; asdl_expr_seq* decorator_list; @@ -5963,6 +6296,42 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (res != 0) goto failed; Py_CLEAR(tmp); } + if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from AsyncFunctionDef"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + type_params = _Py_asdl_type_param_seq_new(len, arena); + if (type_params == NULL) goto failed; + for (i = 0; i < len; i++) { + type_param_ty val; + PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i)); + if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { + goto failed; + } + res = obj2ast_type_param(state, tmp2, &val, arena); + _Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "AsyncFunctionDef field \"type_params\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(type_params, i, val); + } + Py_CLEAR(tmp); + } if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) { return 1; } @@ -6086,10 +6455,10 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (res != 0) goto failed; Py_CLEAR(tmp); } - *out = _PyAST_AsyncFunctionDef(name, args, body, decorator_list, - returns, type_comment, lineno, - col_offset, end_lineno, end_col_offset, - arena); + *out = _PyAST_AsyncFunctionDef(name, type_params, args, body, + decorator_list, returns, type_comment, + lineno, col_offset, end_lineno, + end_col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -6100,6 +6469,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } if (isinstance) { identifier name; + asdl_type_param_seq* type_params; asdl_expr_seq* bases; asdl_keyword_seq* keywords; asdl_stmt_seq* body; @@ -6122,6 +6492,42 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (res != 0) goto failed; Py_CLEAR(tmp); } + if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from ClassDef"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "ClassDef field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + type_params = _Py_asdl_type_param_seq_new(len, arena); + if (type_params == NULL) goto failed; + for (i = 0; i < len; i++) { + type_param_ty val; + PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i)); + if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { + goto failed; + } + res = obj2ast_type_param(state, tmp2, &val, arena); + _Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "ClassDef field \"type_params\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(type_params, i, val); + } + Py_CLEAR(tmp); + } if (_PyObject_LookupAttr(obj, state->bases, &tmp) < 0) { return 1; } @@ -6266,9 +6672,9 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } Py_CLEAR(tmp); } - *out = _PyAST_ClassDef(name, bases, keywords, body, decorator_list, - lineno, col_offset, end_lineno, end_col_offset, - arena); + *out = _PyAST_ClassDef(name, type_params, bases, keywords, body, + decorator_list, lineno, col_offset, end_lineno, + end_col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -6436,6 +6842,91 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (*out == NULL) goto failed; return 0; } + tp = state->TypeAlias_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + expr_ty name; + asdl_type_param_seq* type_params; + expr_ty value; + + if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from TypeAlias"); + return 1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp, &name, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"type_params\" missing from TypeAlias"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "TypeAlias field \"type_params\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + type_params = _Py_asdl_type_param_seq_new(len, arena); + if (type_params == NULL) goto failed; + for (i = 0; i < len; i++) { + type_param_ty val; + PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i)); + if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { + goto failed; + } + res = obj2ast_type_param(state, tmp2, &val, arena); + _Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "TypeAlias field \"type_params\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(type_params, i, val); + } + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from TypeAlias"); + return 1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp, &value, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = _PyAST_TypeAlias(name, type_params, value, lineno, col_offset, + end_lineno, end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } tp = state->AugAssign_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -11803,6 +12294,206 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* return 1; } +int +obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, + PyArena* arena) +{ + int isinstance; + + PyObject *tmp = NULL; + PyObject *tp; + int lineno; + int col_offset; + int end_lineno; + int end_col_offset; + + if (obj == Py_None) { + *out = NULL; + return 0; + } + if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from type_param"); + return 1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { + goto failed; + } + res = obj2ast_int(state, tmp, &lineno, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"col_offset\" missing from type_param"); + return 1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { + goto failed; + } + res = obj2ast_int(state, tmp, &col_offset, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) { + return 1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + end_lineno = lineno; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { + goto failed; + } + res = obj2ast_int(state, tmp, &end_lineno, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) { + return 1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + end_col_offset = col_offset; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { + goto failed; + } + res = obj2ast_int(state, tmp, &end_col_offset, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + tp = state->TypeVar_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + identifier name; + expr_ty bound; + + if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from TypeVar"); + return 1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { + goto failed; + } + res = obj2ast_identifier(state, tmp, &name, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->bound, &tmp) < 0) { + return 1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + bound = NULL; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp, &bound, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = _PyAST_TypeVar(name, bound, lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } + tp = state->ParamSpec_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + identifier name; + + if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from ParamSpec"); + return 1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'ParamSpec' node")) { + goto failed; + } + res = obj2ast_identifier(state, tmp, &name, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = _PyAST_ParamSpec(name, lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } + tp = state->TypeVarTuple_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + identifier name; + + if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from TypeVarTuple"); + return 1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'TypeVarTuple' node")) { + goto failed; + } + res = obj2ast_identifier(state, tmp, &name, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = _PyAST_TypeVarTuple(name, lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } + + PyErr_Format(PyExc_TypeError, "expected some sort of type_param, but got %R", obj); + failed: + Py_XDECREF(tmp); + return 1; +} + static int astmodule_exec(PyObject *m) @@ -11861,6 +12552,9 @@ astmodule_exec(PyObject *m) if (PyModule_AddObjectRef(m, "Assign", state->Assign_type) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "TypeAlias", state->TypeAlias_type) < 0) { + return -1; + } if (PyModule_AddObjectRef(m, "AugAssign", state->AugAssign_type) < 0) { return -1; } @@ -12188,6 +12882,19 @@ astmodule_exec(PyObject *m) if (PyModule_AddObjectRef(m, "TypeIgnore", state->TypeIgnore_type) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "type_param", state->type_param_type) < 0) { + return -1; + } + if (PyModule_AddObjectRef(m, "TypeVar", state->TypeVar_type) < 0) { + return -1; + } + if (PyModule_AddObjectRef(m, "ParamSpec", state->ParamSpec_type) < 0) { + return -1; + } + if (PyModule_AddObjectRef(m, "TypeVarTuple", state->TypeVarTuple_type) < 0) + { + return -1; + } return 0; } diff --git a/Python/Python-tokenize.c b/Python/Python-tokenize.c index 3394a5108cb535..f7e32d3af9a9f7 100644 --- a/Python/Python-tokenize.c +++ b/Python/Python-tokenize.c @@ -1,5 +1,8 @@ #include "Python.h" +#include "errcode.h" #include "../Parser/tokenizer.h" +#include "../Parser/pegen.h" // _PyPegen_byte_offset_to_character_offset() +#include "../Parser/pegen.h" // _PyPegen_byte_offset_to_character_offset() static struct PyModuleDef _tokenizemodule; @@ -34,11 +37,14 @@ typedef struct _tokenizer.tokenizeriter.__new__ as tokenizeriter_new source: str + * + extra_tokens: bool [clinic start generated code]*/ static PyObject * -tokenizeriter_new_impl(PyTypeObject *type, const char *source) -/*[clinic end generated code: output=7fd9f46cf9263cbb input=4384b368407375c6]*/ +tokenizeriter_new_impl(PyTypeObject *type, const char *source, + int extra_tokens) +/*[clinic end generated code: output=f6f9d8b4beec8106 input=90dc5b6a5df180c2]*/ { tokenizeriterobject *self = (tokenizeriterobject *)type->tp_alloc(type, 0); if (self == NULL) { @@ -54,20 +60,126 @@ tokenizeriter_new_impl(PyTypeObject *type, const char *source) return NULL; } self->tok->filename = filename; + if (extra_tokens) { + self->tok->tok_extra_tokens = 1; + } return (PyObject *)self; } +static int +_tokenizer_error(struct tok_state *tok) +{ + if (PyErr_Occurred()) { + return -1; + } + + const char *msg = NULL; + PyObject* errtype = PyExc_SyntaxError; + switch (tok->done) { + case E_TOKEN: + msg = "invalid token"; + break; + case E_EOF: + if (tok->level) { + PyErr_Format(PyExc_SyntaxError, + "parenthesis '%c' was never closed", + tok->parenstack[tok->level-1]); + } else { + PyErr_SetString(PyExc_SyntaxError, "unexpected EOF while parsing"); + } + return -1; + case E_DEDENT: + msg = "unindent does not match any outer indentation level"; + errtype = PyExc_IndentationError; + break; + case E_INTR: + if (!PyErr_Occurred()) { + PyErr_SetNone(PyExc_KeyboardInterrupt); + } + return -1; + case E_NOMEM: + PyErr_NoMemory(); + return -1; + case E_TABSPACE: + errtype = PyExc_TabError; + msg = "inconsistent use of tabs and spaces in indentation"; + break; + case E_TOODEEP: + errtype = PyExc_IndentationError; + msg = "too many levels of indentation"; + break; + case E_LINECONT: { + msg = "unexpected character after line continuation character"; + break; + } + default: + msg = "unknown tokenization error"; + } + + PyObject* errstr = NULL; + PyObject* error_line = NULL; + PyObject* tmp = NULL; + PyObject* value = NULL; + int result = 0; + + Py_ssize_t size = tok->inp - tok->buf; + error_line = PyUnicode_DecodeUTF8(tok->buf, size, "replace"); + if (!error_line) { + result = -1; + goto exit; + } + + Py_ssize_t offset = _PyPegen_byte_offset_to_character_offset(error_line, tok->inp - tok->buf); + if (offset == -1) { + result = -1; + goto exit; + } + tmp = Py_BuildValue("(OnnOOO)", tok->filename, tok->lineno, offset, error_line, Py_None, Py_None); + if (!tmp) { + result = -1; + goto exit; + } + + errstr = PyUnicode_FromString(msg); + if (!errstr) { + result = -1; + goto exit; + } + + value = PyTuple_Pack(2, errstr, tmp); + if (!value) { + result = -1; + goto exit; + } + + PyErr_SetObject(errtype, value); + +exit: + Py_XDECREF(errstr); + Py_XDECREF(error_line); + Py_XDECREF(tmp); + Py_XDECREF(value); + return result; +} + static PyObject * tokenizeriter_next(tokenizeriterobject *it) { + PyObject* result = NULL; struct token token; + _PyToken_Init(&token); + int type = _PyTokenizer_Get(it->tok, &token); - if (type == ERRORTOKEN && PyErr_Occurred()) { - return NULL; + if (type == ERRORTOKEN) { + if(!PyErr_Occurred()) { + _tokenizer_error(it->tok); + assert(PyErr_Occurred()); + } + goto exit; } if (type == ERRORTOKEN || type == ENDMARKER) { PyErr_SetString(PyExc_StopIteration, "EOF"); - return NULL; + goto exit; } PyObject *str = NULL; if (token.start == NULL || token.end == NULL) { @@ -77,28 +189,46 @@ tokenizeriter_next(tokenizeriterobject *it) str = PyUnicode_FromStringAndSize(token.start, token.end - token.start); } if (str == NULL) { - return NULL; + goto exit; } Py_ssize_t size = it->tok->inp - it->tok->buf; PyObject *line = PyUnicode_DecodeUTF8(it->tok->buf, size, "replace"); if (line == NULL) { Py_DECREF(str); - return NULL; + goto exit; } const char *line_start = ISSTRINGLIT(type) ? it->tok->multi_line_start : it->tok->line_start; - int lineno = ISSTRINGLIT(type) ? it->tok->first_lineno : it->tok->lineno; - int end_lineno = it->tok->lineno; - int col_offset = -1; - int end_col_offset = -1; + Py_ssize_t lineno = ISSTRINGLIT(type) ? it->tok->first_lineno : it->tok->lineno; + Py_ssize_t end_lineno = it->tok->lineno; + Py_ssize_t col_offset = -1; + Py_ssize_t end_col_offset = -1; if (token.start != NULL && token.start >= line_start) { - col_offset = (int)(token.start - line_start); + col_offset = _PyPegen_byte_offset_to_character_offset(line, token.start - line_start); } if (token.end != NULL && token.end >= it->tok->line_start) { - end_col_offset = (int)(token.end - it->tok->line_start); + end_col_offset = _PyPegen_byte_offset_to_character_offset(line, token.end - it->tok->line_start); + } + + if (it->tok->tok_extra_tokens) { + // Necessary adjustments to match the original Python tokenize + // implementation + if (type > DEDENT && type < OP) { + type = OP; + } + else if (type == ASYNC || type == AWAIT) { + type = NAME; + } + else if (type == NEWLINE) { + str = PyUnicode_FromString("\n"); + end_col_offset++; + } } - return Py_BuildValue("(NiiiiiN)", str, type, lineno, end_lineno, col_offset, end_col_offset, line); + result = Py_BuildValue("(iN(nn)(nn)N)", type, str, lineno, col_offset, end_lineno, end_col_offset, line); +exit: + _PyToken_Free(&token); + return result; } static void diff --git a/Python/_warnings.c b/Python/_warnings.c index 5644db9a3770cb..dec658680241ed 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -198,7 +198,7 @@ get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import) PyObject *warnings_module, *obj; /* don't try to import after the start of the Python finallization */ - if (try_import && !_Py_IsFinalizing()) { + if (try_import && !_Py_IsInterpreterFinalizing(interp)) { warnings_module = PyImport_Import(&_Py_ID(warnings)); if (warnings_module == NULL) { /* Fallback to the C implementation if we cannot get diff --git a/Python/ast.c b/Python/ast.c index 50fc8e01fb3f69..68600ce683b974 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -17,10 +17,12 @@ struct validator { static int validate_stmts(struct validator *, asdl_stmt_seq *); static int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int); static int validate_patterns(struct validator *, asdl_pattern_seq *, int); +static int validate_type_params(struct validator *, asdl_type_param_seq *); static int _validate_nonempty_seq(asdl_seq *, const char *, const char *); static int validate_stmt(struct validator *, stmt_ty); static int validate_expr(struct validator *, expr_ty, expr_context_ty); static int validate_pattern(struct validator *, pattern_ty, int); +static int validate_typeparam(struct validator *, type_param_ty); #define VALIDATE_POSITIONS(node) \ if (node->lineno > node->end_lineno) { \ @@ -46,6 +48,7 @@ static int validate_pattern(struct validator *, pattern_ty, int); static int validate_name(PyObject *name) { + assert(!PyErr_Occurred()); assert(PyUnicode_Check(name)); static const char * const forbidden[] = { "None", @@ -65,12 +68,12 @@ validate_name(PyObject *name) static int validate_comprehension(struct validator *state, asdl_comprehension_seq *gens) { - Py_ssize_t i; + assert(!PyErr_Occurred()); if (!asdl_seq_LEN(gens)) { PyErr_SetString(PyExc_ValueError, "comprehension with no generators"); return 0; } - for (i = 0; i < asdl_seq_LEN(gens); i++) { + for (Py_ssize_t i = 0; i < asdl_seq_LEN(gens); i++) { comprehension_ty comp = asdl_seq_GET(gens, i); if (!validate_expr(state, comp->target, Store) || !validate_expr(state, comp->iter, Load) || @@ -83,8 +86,8 @@ validate_comprehension(struct validator *state, asdl_comprehension_seq *gens) static int validate_keywords(struct validator *state, asdl_keyword_seq *keywords) { - Py_ssize_t i; - for (i = 0; i < asdl_seq_LEN(keywords); i++) + assert(!PyErr_Occurred()); + for (Py_ssize_t i = 0; i < asdl_seq_LEN(keywords); i++) if (!validate_expr(state, (asdl_seq_GET(keywords, i))->value, Load)) return 0; return 1; @@ -93,8 +96,8 @@ validate_keywords(struct validator *state, asdl_keyword_seq *keywords) static int validate_args(struct validator *state, asdl_arg_seq *args) { - Py_ssize_t i; - for (i = 0; i < asdl_seq_LEN(args); i++) { + assert(!PyErr_Occurred()); + for (Py_ssize_t i = 0; i < asdl_seq_LEN(args); i++) { arg_ty arg = asdl_seq_GET(args, i); VALIDATE_POSITIONS(arg); if (arg->annotation && !validate_expr(state, arg->annotation, Load)) @@ -121,6 +124,7 @@ expr_context_name(expr_context_ty ctx) static int validate_arguments(struct validator *state, arguments_ty args) { + assert(!PyErr_Occurred()); if (!validate_args(state, args->posonlyargs) || !validate_args(state, args->args)) { return 0; } @@ -149,6 +153,7 @@ validate_arguments(struct validator *state, arguments_ty args) static int validate_constant(struct validator *state, PyObject *value) { + assert(!PyErr_Occurred()); if (value == Py_None || value == Py_Ellipsis) return 1; @@ -205,6 +210,7 @@ validate_constant(struct validator *state, PyObject *value) static int validate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx) { + assert(!PyErr_Occurred()); VALIDATE_POSITIONS(exp); int ret = -1; if (++state->recursion_depth > state->recursion_limit) { @@ -465,6 +471,7 @@ ensure_literal_complex(expr_ty exp) static int validate_pattern_match_value(struct validator *state, expr_ty exp) { + assert(!PyErr_Occurred()); if (!validate_expr(state, exp, Load)) { return 0; } @@ -518,6 +525,7 @@ validate_pattern_match_value(struct validator *state, expr_ty exp) static int validate_capture(PyObject *name) { + assert(!PyErr_Occurred()); if (_PyUnicode_EqualToASCIIString(name, "_")) { PyErr_Format(PyExc_ValueError, "can't capture name '_' in patterns"); return 0; @@ -528,6 +536,7 @@ validate_capture(PyObject *name) static int validate_pattern(struct validator *state, pattern_ty p, int star_ok) { + assert(!PyErr_Occurred()); VALIDATE_POSITIONS(p); int ret = -1; if (++state->recursion_depth > state->recursion_limit) { @@ -580,7 +589,9 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok) break; } } - + if (ret == 0) { + break; + } ret = validate_patterns(state, p->v.MatchMapping.patterns, /*star_ok=*/0); break; case MatchClass_kind: @@ -611,6 +622,9 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok) break; } } + if (ret == 0) { + break; + } for (Py_ssize_t i = 0; i < asdl_seq_LEN(p->v.MatchClass.kwd_attrs); i++) { PyObject *identifier = asdl_seq_GET(p->v.MatchClass.kwd_attrs, i); @@ -619,6 +633,9 @@ validate_pattern(struct validator *state, pattern_ty p, int star_ok) break; } } + if (ret == 0) { + break; + } if (!validate_patterns(state, p->v.MatchClass.patterns, /*star_ok=*/0)) { ret = 0; @@ -685,6 +702,7 @@ _validate_nonempty_seq(asdl_seq *seq, const char *what, const char *owner) static int validate_assignlist(struct validator *state, asdl_expr_seq *targets, expr_context_ty ctx) { + assert(!PyErr_Occurred()); return validate_nonempty_seq(targets, "targets", ctx == Del ? "Delete" : "Assign") && validate_exprs(state, targets, ctx, 0); } @@ -692,15 +710,16 @@ validate_assignlist(struct validator *state, asdl_expr_seq *targets, expr_contex static int validate_body(struct validator *state, asdl_stmt_seq *body, const char *owner) { + assert(!PyErr_Occurred()); return validate_nonempty_seq(body, "body", owner) && validate_stmts(state, body); } static int validate_stmt(struct validator *state, stmt_ty stmt) { + assert(!PyErr_Occurred()); VALIDATE_POSITIONS(stmt); int ret = -1; - Py_ssize_t i; if (++state->recursion_depth > state->recursion_limit) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth exceeded during compilation"); @@ -709,6 +728,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) switch (stmt->kind) { case FunctionDef_kind: ret = validate_body(state, stmt->v.FunctionDef.body, "FunctionDef") && + validate_type_params(state, stmt->v.FunctionDef.type_params) && validate_arguments(state, stmt->v.FunctionDef.args) && validate_exprs(state, stmt->v.FunctionDef.decorator_list, Load, 0) && (!stmt->v.FunctionDef.returns || @@ -716,6 +736,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) break; case ClassDef_kind: ret = validate_body(state, stmt->v.ClassDef.body, "ClassDef") && + validate_type_params(state, stmt->v.ClassDef.type_params) && validate_exprs(state, stmt->v.ClassDef.bases, Load, 0) && validate_keywords(state, stmt->v.ClassDef.keywords) && validate_exprs(state, stmt->v.ClassDef.decorator_list, Load, 0); @@ -746,6 +767,11 @@ validate_stmt(struct validator *state, stmt_ty stmt) validate_expr(state, stmt->v.AnnAssign.value, Load)) && validate_expr(state, stmt->v.AnnAssign.annotation, Load); break; + case TypeAlias_kind: + ret = validate_expr(state, stmt->v.TypeAlias.name, Store) && + validate_type_params(state, stmt->v.TypeAlias.type_params) && + validate_expr(state, stmt->v.TypeAlias.value, Load); + break; case For_kind: ret = validate_expr(state, stmt->v.For.target, Store) && validate_expr(state, stmt->v.For.iter, Load) && @@ -771,7 +797,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) case With_kind: if (!validate_nonempty_seq(stmt->v.With.items, "items", "With")) return 0; - for (i = 0; i < asdl_seq_LEN(stmt->v.With.items); i++) { + for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.With.items); i++) { withitem_ty item = asdl_seq_GET(stmt->v.With.items, i); if (!validate_expr(state, item->context_expr, Load) || (item->optional_vars && !validate_expr(state, item->optional_vars, Store))) @@ -782,7 +808,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) case AsyncWith_kind: if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith")) return 0; - for (i = 0; i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++) { + for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++) { withitem_ty item = asdl_seq_GET(stmt->v.AsyncWith.items, i); if (!validate_expr(state, item->context_expr, Load) || (item->optional_vars && !validate_expr(state, item->optional_vars, Store))) @@ -795,7 +821,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) || !validate_nonempty_seq(stmt->v.Match.cases, "cases", "Match")) { return 0; } - for (i = 0; i < asdl_seq_LEN(stmt->v.Match.cases); i++) { + for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.Match.cases); i++) { match_case_ty m = asdl_seq_GET(stmt->v.Match.cases, i); if (!validate_pattern(state, m->pattern, /*star_ok=*/0) || (m->guard && !validate_expr(state, m->guard, Load)) @@ -830,7 +856,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) PyErr_SetString(PyExc_ValueError, "Try has orelse but no except handlers"); return 0; } - for (i = 0; i < asdl_seq_LEN(stmt->v.Try.handlers); i++) { + for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.Try.handlers); i++) { excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i); VALIDATE_POSITIONS(handler); if ((handler->v.ExceptHandler.type && @@ -856,7 +882,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) PyErr_SetString(PyExc_ValueError, "TryStar has orelse but no except handlers"); return 0; } - for (i = 0; i < asdl_seq_LEN(stmt->v.TryStar.handlers); i++) { + for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.TryStar.handlers); i++) { excepthandler_ty handler = asdl_seq_GET(stmt->v.TryStar.handlers, i); if ((handler->v.ExceptHandler.type && !validate_expr(state, handler->v.ExceptHandler.type, Load)) || @@ -893,6 +919,7 @@ validate_stmt(struct validator *state, stmt_ty stmt) break; case AsyncFunctionDef_kind: ret = validate_body(state, stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") && + validate_type_params(state, stmt->v.AsyncFunctionDef.type_params) && validate_arguments(state, stmt->v.AsyncFunctionDef.args) && validate_exprs(state, stmt->v.AsyncFunctionDef.decorator_list, Load, 0) && (!stmt->v.AsyncFunctionDef.returns || @@ -916,8 +943,8 @@ validate_stmt(struct validator *state, stmt_ty stmt) static int validate_stmts(struct validator *state, asdl_stmt_seq *seq) { - Py_ssize_t i; - for (i = 0; i < asdl_seq_LEN(seq); i++) { + assert(!PyErr_Occurred()); + for (Py_ssize_t i = 0; i < asdl_seq_LEN(seq); i++) { stmt_ty stmt = asdl_seq_GET(seq, i); if (stmt) { if (!validate_stmt(state, stmt)) @@ -935,8 +962,8 @@ validate_stmts(struct validator *state, asdl_stmt_seq *seq) static int validate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ctx, int null_ok) { - Py_ssize_t i; - for (i = 0; i < asdl_seq_LEN(exprs); i++) { + assert(!PyErr_Occurred()); + for (Py_ssize_t i = 0; i < asdl_seq_LEN(exprs); i++) { expr_ty expr = asdl_seq_GET(exprs, i); if (expr) { if (!validate_expr(state, expr, ctx)) @@ -955,8 +982,8 @@ validate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ct static int validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_ok) { - Py_ssize_t i; - for (i = 0; i < asdl_seq_LEN(patterns); i++) { + assert(!PyErr_Occurred()); + for (Py_ssize_t i = 0; i < asdl_seq_LEN(patterns); i++) { pattern_ty pattern = asdl_seq_GET(patterns, i); if (!validate_pattern(state, pattern, star_ok)) { return 0; @@ -965,6 +992,41 @@ validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_ return 1; } +static int +validate_typeparam(struct validator *state, type_param_ty tp) +{ + VALIDATE_POSITIONS(tp); + int ret = -1; + switch (tp->kind) { + case TypeVar_kind: + ret = validate_name(tp->v.TypeVar.name) && + (!tp->v.TypeVar.bound || + validate_expr(state, tp->v.TypeVar.bound, Load)); + break; + case ParamSpec_kind: + ret = validate_name(tp->v.ParamSpec.name); + break; + case TypeVarTuple_kind: + ret = validate_name(tp->v.TypeVarTuple.name); + break; + } + return ret; +} + +static int +validate_type_params(struct validator *state, asdl_type_param_seq *tps) +{ + Py_ssize_t i; + for (i = 0; i < asdl_seq_LEN(tps); i++) { + type_param_ty tp = asdl_seq_GET(tps, i); + if (tp) { + if (!validate_typeparam(state, tp)) + return 0; + } + } + return 1; +} + /* See comments in symtable.c. */ #define COMPILER_STACK_FRAME_SCALE 3 @@ -972,6 +1034,7 @@ validate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_ int _PyAST_Validate(mod_ty mod) { + assert(!PyErr_Occurred()); int res = -1; struct validator state; PyThreadState *tstate; diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 3883ec9e21c765..274bd134e1435b 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -642,6 +642,7 @@ static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeStat static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); +static int astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); #define CALL(FUNC, TYPE, ARG) \ if (!FUNC((ARG), ctx_, state)) \ @@ -880,6 +881,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) } switch (node_->kind) { case FunctionDef_kind: + CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params); CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body); CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list); @@ -888,6 +890,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) } break; case AsyncFunctionDef_kind: + CALL_SEQ(astfold_type_param, type_param, node_->v.AsyncFunctionDef.type_params); CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body); CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list); @@ -896,6 +899,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) } break; case ClassDef_kind: + CALL_SEQ(astfold_type_param, type_param, node_->v.ClassDef.type_params); CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases); CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords); CALL(astfold_body, asdl_seq, node_->v.ClassDef.body); @@ -922,6 +926,11 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) } CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value); break; + case TypeAlias_kind: + CALL(astfold_expr, expr_ty, node_->v.TypeAlias.name); + CALL_SEQ(astfold_type_param, type_param, node_->v.TypeAlias.type_params); + CALL(astfold_expr, expr_ty, node_->v.TypeAlias.value); + break; case For_kind: CALL(astfold_expr, expr_ty, node_->v.For.target); CALL(astfold_expr, expr_ty, node_->v.For.iter); @@ -1074,6 +1083,21 @@ astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *stat return 1; } +static int +astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) +{ + switch (node_->kind) { + case TypeVar_kind: + CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.bound); + break; + case ParamSpec_kind: + break; + case TypeVarTuple_kind: + break; + } + return 1; +} + #undef CALL #undef CALL_OPT #undef CALL_SEQ diff --git a/Python/bytecodes.c b/Python/bytecodes.c index d84a078f110085..f71a62e051a34f 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -56,7 +56,7 @@ static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2; static PyObject *list, *tuple, *dict, *owner, *set, *str, *tup, *map, *keys; static PyObject *exit_func, *lasti, *val, *retval, *obj, *iter; -static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc; +static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc, *locals; static PyObject *orig, *excs, *update, *b, *fromlist, *level, *from; static PyObject **pieces, **values; static size_t jump; @@ -70,7 +70,6 @@ dummy_func( _PyInterpreterFrame *frame, unsigned char opcode, unsigned int oparg, - _Py_atomic_int * const eval_breaker, _PyCFrame cframe, _Py_CODEUNIT *next_instr, PyObject **stack_pointer, @@ -125,6 +124,7 @@ dummy_func( PyObject *subject; PyObject *top; PyObject *type; + PyObject *typevars; int values_or_none; switch (opcode) { @@ -142,7 +142,7 @@ dummy_func( ERROR_IF(err, error); next_instr--; } - else if (_Py_atomic_load_relaxed_int32(eval_breaker) && oparg < 2) { + else if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) { goto handle_eval_breaker; } } @@ -169,7 +169,7 @@ dummy_func( next_instr = frame->prev_instr; DISPATCH(); } - if (_Py_atomic_load_relaxed_int32(eval_breaker) && oparg < 2) { + if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) { goto handle_eval_breaker; } } @@ -269,7 +269,6 @@ dummy_func( else { res = Py_False; } - Py_INCREF(res); } inst(UNARY_INVERT, (value -- res)) { @@ -966,7 +965,7 @@ dummy_func( if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { value = Py_NewRef(((PyStopIterationObject *)exc_value)->value); DECREF_INPUTS(); - none = Py_NewRef(Py_None); + none = Py_None; } else { _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); @@ -1002,6 +1001,7 @@ dummy_func( } } + inst(STORE_NAME, (v -- )) { PyObject *name = GETITEM(frame->f_code->co_names, oparg); PyObject *ns = LOCALS(); @@ -1158,31 +1158,41 @@ dummy_func( } } - inst(LOAD_NAME, ( -- v)) { - PyObject *name = GETITEM(frame->f_code->co_names, oparg); - PyObject *locals = LOCALS(); + op(_LOAD_LOCALS, ( -- locals)) { + locals = LOCALS(); if (locals == NULL) { - _PyErr_Format(tstate, PyExc_SystemError, - "no locals when loading %R", name); - goto error; + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + ERROR_IF(true, error); } - if (PyDict_CheckExact(locals)) { - v = PyDict_GetItemWithError(locals, name); + Py_INCREF(locals); + } + + macro(LOAD_LOCALS) = _LOAD_LOCALS; + + op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) { + PyObject *name = GETITEM(frame->f_code->co_names, oparg); + if (PyDict_CheckExact(mod_or_class_dict)) { + v = PyDict_GetItemWithError(mod_or_class_dict, name); if (v != NULL) { Py_INCREF(v); } else if (_PyErr_Occurred(tstate)) { + Py_DECREF(mod_or_class_dict); goto error; } } else { - v = PyObject_GetItem(locals, name); + v = PyObject_GetItem(mod_or_class_dict, name); if (v == NULL) { - if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) + if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + Py_DECREF(mod_or_class_dict); goto error; + } _PyErr_Clear(tstate); } } + Py_DECREF(mod_or_class_dict); if (v == NULL) { v = PyDict_GetItemWithError(GLOBALS(), name); if (v != NULL) { @@ -1219,6 +1229,10 @@ dummy_func( } } + macro(LOAD_NAME) = _LOAD_LOCALS + _LOAD_FROM_DICT_OR_GLOBALS; + + macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS; + family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = { LOAD_GLOBAL, LOAD_GLOBAL_MODULE, @@ -1339,29 +1353,32 @@ dummy_func( Py_DECREF(oldobj); } - inst(LOAD_CLASSDEREF, ( -- value)) { - PyObject *name, *locals = LOCALS(); - assert(locals); + inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) { + PyObject *name; + assert(class_dict); assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus); name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg); - if (PyDict_CheckExact(locals)) { - value = PyDict_GetItemWithError(locals, name); + if (PyDict_CheckExact(class_dict)) { + value = PyDict_GetItemWithError(class_dict, name); if (value != NULL) { Py_INCREF(value); } else if (_PyErr_Occurred(tstate)) { + Py_DECREF(class_dict); goto error; } } else { - value = PyObject_GetItem(locals, name); + value = PyObject_GetItem(class_dict, name); if (value == NULL) { if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + Py_DECREF(class_dict); goto error; } _PyErr_Clear(tstate); } } + Py_DECREF(class_dict); if (!value) { PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); @@ -1433,7 +1450,7 @@ dummy_func( DECREF_INPUTS(); ERROR_IF(true, error); } - Py_DECREF(none_val); + assert(Py_IsNone(none_val)); DECREF_INPUTS(); } @@ -1563,6 +1580,14 @@ dummy_func( PREDICT(JUMP_BACKWARD); } + inst(INSTRUMENTED_LOAD_SUPER_ATTR, (unused/9, unused, unused, unused -- unused if (oparg & 1), unused)) { + _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; + // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we + // don't want to specialize instrumented instructions + INCREMENT_ADAPTIVE_COUNTER(cache->counter); + GO_TO_INSTRUCTION(LOAD_SUPER_ATTR); + } + family(load_super_attr, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = { LOAD_SUPER_ATTR, LOAD_SUPER_ATTR_ATTR, @@ -1583,10 +1608,34 @@ dummy_func( DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ + if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { + PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_CALL, + frame, next_instr-1, global_super, arg); + ERROR_IF(err, error); + } + // we make no attempt to optimize here; specializations should // handle any case whose performance we care about PyObject *stack[] = {class, self}; PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL); + if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { + PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; + if (super == NULL) { + _Py_call_instrumentation_exc2( + tstate, PY_MONITORING_EVENT_C_RAISE, + frame, next_instr-1, global_super, arg); + } + else { + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_C_RETURN, + frame, next_instr-1, global_super, arg); + if (err < 0) { + Py_CLEAR(super); + } + } + } DECREF_INPUTS(); ERROR_IF(super == NULL, error); res = PyObject_GetAttr(super, name); @@ -1942,7 +1991,6 @@ dummy_func( _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); res = (sign_ish & oparg) ? Py_True : Py_False; - Py_INCREF(res); } // Similar to COMPARE_OP_FLOAT @@ -1961,7 +2009,6 @@ dummy_func( _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); res = (sign_ish & oparg) ? Py_True : Py_False; - Py_INCREF(res); } // Similar to COMPARE_OP_FLOAT, but for ==, != only @@ -1977,20 +2024,19 @@ dummy_func( assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; - Py_INCREF(res); } inst(IS_OP, (left, right -- b)) { int res = Py_Is(left, right) ^ oparg; DECREF_INPUTS(); - b = Py_NewRef(res ? Py_True : Py_False); + b = res ? Py_True : Py_False; } inst(CONTAINS_OP, (left, right -- b)) { int res = PySequence_Contains(right, left); DECREF_INPUTS(); ERROR_IF(res < 0, error); - b = Py_NewRef((res^oparg) ? Py_True : Py_False); + b = (res ^ oparg) ? Py_True : Py_False; } inst(CHECK_EG_MATCH, (exc_value, match_type -- rest, match)) { @@ -2023,7 +2069,7 @@ dummy_func( int res = PyErr_GivenExceptionMatches(left, right); DECREF_INPUTS(); - b = Py_NewRef(res ? Py_True : Py_False); + b = res ? Py_True : Py_False; } inst(IMPORT_NAME, (level, fromlist -- res)) { @@ -2050,14 +2096,10 @@ dummy_func( } inst(POP_JUMP_IF_FALSE, (cond -- )) { - if (Py_IsTrue(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - } - else if (Py_IsFalse(cond)) { - _Py_DECREF_NO_DEALLOC(cond); + if (Py_IsFalse(cond)) { JUMPBY(oparg); } - else { + else if (!Py_IsTrue(cond)) { int err = PyObject_IsTrue(cond); DECREF_INPUTS(); if (err == 0) { @@ -2070,14 +2112,10 @@ dummy_func( } inst(POP_JUMP_IF_TRUE, (cond -- )) { - if (Py_IsFalse(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - } - else if (Py_IsTrue(cond)) { - _Py_DECREF_NO_DEALLOC(cond); + if (Py_IsTrue(cond)) { JUMPBY(oparg); } - else { + else if (!Py_IsFalse(cond)) { int err = PyObject_IsTrue(cond); DECREF_INPUTS(); if (err > 0) { @@ -2094,14 +2132,10 @@ dummy_func( DECREF_INPUTS(); JUMPBY(oparg); } - else { - _Py_DECREF_NO_DEALLOC(value); - } } inst(POP_JUMP_IF_NONE, (value -- )) { if (Py_IsNone(value)) { - _Py_DECREF_NO_DEALLOC(value); JUMPBY(oparg); } else { @@ -2137,19 +2171,19 @@ dummy_func( } else { ERROR_IF(_PyErr_Occurred(tstate), error); // Error! - attrs = Py_NewRef(Py_None); // Failure! + attrs = Py_None; // Failure! } } inst(MATCH_MAPPING, (subject -- subject, res)) { int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; - res = Py_NewRef(match ? Py_True : Py_False); + res = match ? Py_True : Py_False; PREDICT(POP_JUMP_IF_FALSE); } inst(MATCH_SEQUENCE, (subject -- subject, res)) { int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE; - res = Py_NewRef(match ? Py_True : Py_False); + res = match ? Py_True : Py_False; PREDICT(POP_JUMP_IF_FALSE); } @@ -2341,7 +2375,7 @@ dummy_func( STAT_INC(FOR_ITER, hit); _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; frame->return_offset = oparg; - _PyFrame_StackPush(gen_frame, Py_NewRef(Py_None)); + _PyFrame_StackPush(gen_frame, Py_None); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; @@ -2448,7 +2482,7 @@ dummy_func( prev_exc = exc_info->exc_value; } else { - prev_exc = Py_NewRef(Py_None); + prev_exc = Py_None; } assert(PyExceptionInstance_Check(new_exc)); exc_info->exc_value = Py_NewRef(new_exc); @@ -3342,7 +3376,6 @@ dummy_func( _Py_CODEUNIT *here = next_instr-1; int offset; if (Py_IsNone(value)) { - _Py_DECREF_NO_DEALLOC(value); offset = oparg; } else { @@ -3357,7 +3390,6 @@ dummy_func( _Py_CODEUNIT *here = next_instr-1; int offset; if (Py_IsNone(value)) { - _Py_DECREF_NO_DEALLOC(value); offset = 0; } else { diff --git a/Python/ceval.c b/Python/ceval.c index e8534ec6598e2b..df997e1ed283d7 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -652,7 +652,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int // for the big switch below (in combination with the EXTRA_CASES macro). uint8_t opcode; /* Current opcode */ int oparg; /* Current opcode argument, if any */ - _Py_atomic_int * const eval_breaker = &tstate->interp->ceval.eval_breaker; #ifdef LLTRACE int lltrace = 0; #endif diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 42e1436bc9130d..b9bdb74fcedf32 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -332,6 +332,9 @@ tstate_must_exit(PyThreadState *tstate) After Py_Finalize() has been called, tstate can be a dangling pointer: point to PyThreadState freed memory. */ PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime); + if (finalizing == NULL) { + finalizing = _PyInterpreterState_GetFinalizing(tstate->interp); + } return (finalizing != NULL && finalizing != tstate); } diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index e92ff0bd6fba6f..fccf9088cbd131 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -116,7 +116,7 @@ #define CHECK_EVAL_BREAKER() \ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \ - if (_Py_atomic_load_relaxed_int32(eval_breaker)) { \ + if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker)) { \ goto handle_eval_breaker; \ } diff --git a/Python/clinic/Python-tokenize.c.h b/Python/clinic/Python-tokenize.c.h index 6af93743f40dab..7e779388a92dbf 100644 --- a/Python/clinic/Python-tokenize.c.h +++ b/Python/clinic/Python-tokenize.c.h @@ -9,7 +9,8 @@ preserve static PyObject * -tokenizeriter_new_impl(PyTypeObject *type, const char *source); +tokenizeriter_new_impl(PyTypeObject *type, const char *source, + int extra_tokens); static PyObject * tokenizeriter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) @@ -17,14 +18,14 @@ tokenizeriter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyObject *return_value = NULL; #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE) - #define NUM_KEYWORDS 1 + #define NUM_KEYWORDS 2 static struct { PyGC_Head _this_is_not_used; PyObject_VAR_HEAD PyObject *ob_item[NUM_KEYWORDS]; } _kwtuple = { .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS) - .ob_item = { &_Py_ID(source), }, + .ob_item = { &_Py_ID(source), &_Py_ID(extra_tokens), }, }; #undef NUM_KEYWORDS #define KWTUPLE (&_kwtuple.ob_base.ob_base) @@ -33,19 +34,20 @@ tokenizeriter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) # define KWTUPLE NULL #endif // !Py_BUILD_CORE - static const char * const _keywords[] = {"source", NULL}; + static const char * const _keywords[] = {"source", "extra_tokens", NULL}; static _PyArg_Parser _parser = { .keywords = _keywords, .fname = "tokenizeriter", .kwtuple = KWTUPLE, }; #undef KWTUPLE - PyObject *argsbuf[1]; + PyObject *argsbuf[2]; PyObject * const *fastargs; Py_ssize_t nargs = PyTuple_GET_SIZE(args); const char *source; + int extra_tokens; - fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 0, argsbuf); + fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 1, argsbuf); if (!fastargs) { goto exit; } @@ -62,9 +64,13 @@ tokenizeriter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) PyErr_SetString(PyExc_ValueError, "embedded null character"); goto exit; } - return_value = tokenizeriter_new_impl(type, source); + extra_tokens = PyObject_IsTrue(fastargs[1]); + if (extra_tokens < 0) { + goto exit; + } + return_value = tokenizeriter_new_impl(type, source, extra_tokens); exit: return return_value; } -/*[clinic end generated code: output=8c2c09f651961986 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=940b564c67f6e0e2 input=a9049054013a1b77]*/ diff --git a/Python/compile.c b/Python/compile.c index f8d0197e9f0682..f2314ae11c417b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -147,6 +147,7 @@ enum { COMPILER_SCOPE_ASYNC_FUNCTION, COMPILER_SCOPE_LAMBDA, COMPILER_SCOPE_COMPREHENSION, + COMPILER_SCOPE_TYPEPARAMS, }; @@ -231,6 +232,7 @@ instr_sequence_next_inst(instr_sequence *seq) { &seq->s_allocated, INITIAL_INSTR_SEQUENCE_SIZE, sizeof(instruction))); + assert(seq->s_allocated >= 0); assert(seq->s_used < seq->s_allocated); return seq->s_used++; } @@ -386,6 +388,8 @@ struct compiler_unit { instr_sequence u_instr_sequence; /* codegen output */ int u_nfblocks; + int u_in_inlined_comp; + struct fblockinfo u_fblock[CO_MAXBLOCKS]; _PyCompile_CodeUnitMetadata u_metadata; @@ -567,6 +571,7 @@ PyCodeObject * _PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags, int optimize, PyArena *arena) { + assert(!PyErr_Occurred()); struct compiler *c = new_compiler(mod, filename, pflags, optimize, arena); if (c == NULL) { return NULL; @@ -713,6 +718,19 @@ compiler_set_qualname(struct compiler *c) capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); assert(parent); + if (parent->u_scope_type == COMPILER_SCOPE_TYPEPARAMS) { + /* The parent is a type parameter scope, so we need to + look at the grandparent. */ + if (stack_size == 2) { + // If we're immediately within the module, we can skip + // the rest and just set the qualname to be the same as name. + u->u_metadata.u_qualname = Py_NewRef(u->u_metadata.u_name); + return SUCCESS; + } + capsule = PyList_GET_ITEM(c->c_stack, stack_size - 2); + parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); + assert(parent); + } if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION @@ -1113,16 +1131,18 @@ codegen_addop_j(instr_sequence *seq, location loc, return instr_sequence_addop(seq, opcode, target.id, loc); } -#define ADDOP(C, LOC, OP) \ - RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC))) - -#define ADDOP_IN_SCOPE(C, LOC, OP) { \ - if (codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)) < 0) { \ - compiler_exit_scope(C); \ +#define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \ + if ((CALL) < 0) { \ + compiler_exit_scope((C)); \ return ERROR; \ } \ } +#define ADDOP(C, LOC, OP) \ + RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC))) + +#define ADDOP_IN_SCOPE(C, LOC, OP) RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC))) + #define ADDOP_LOAD_CONST(C, LOC, O) \ RETURN_IF_ERROR(compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), (O))) @@ -1182,12 +1202,8 @@ codegen_addop_j(instr_sequence *seq, location loc, #define VISIT(C, TYPE, V) \ RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), (V))); -#define VISIT_IN_SCOPE(C, TYPE, V) {\ - if (compiler_visit_ ## TYPE((C), (V)) < 0) { \ - compiler_exit_scope(C); \ - return ERROR; \ - } \ -} +#define VISIT_IN_SCOPE(C, TYPE, V) \ + RETURN_IF_ERROR_IN_SCOPE((C), compiler_visit_ ## TYPE((C), (V))) #define VISIT_SEQ(C, TYPE, SEQ) { \ int _i; \ @@ -1236,7 +1252,7 @@ compiler_enter_scope(struct compiler *c, identifier name, } u->u_metadata.u_name = Py_NewRef(name); u->u_metadata.u_varnames = list2dict(u->u_ste->ste_varnames); - u->u_metadata.u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, 0, 0); + u->u_metadata.u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, DEF_COMP_CELL, 0); if (!u->u_metadata.u_varnames || !u->u_metadata.u_cellvars) { compiler_unit_free(u); return ERROR; @@ -1251,6 +1267,16 @@ compiler_enter_scope(struct compiler *c, identifier name, return ERROR; } } + if (u->u_ste->ste_needs_classdict) { + /* Cook up an implicit __classdict__ cell. */ + Py_ssize_t res; + assert(u->u_scope_type == COMPILER_SCOPE_CLASS); + res = dict_add_o(u->u_metadata.u_cellvars, &_Py_ID(__classdict__)); + if (res < 0) { + compiler_unit_free(u); + return ERROR; + } + } u->u_metadata.u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, PyDict_GET_SIZE(u->u_metadata.u_cellvars)); @@ -1266,6 +1292,7 @@ compiler_enter_scope(struct compiler *c, identifier name, } u->u_nfblocks = 0; + u->u_in_inlined_comp = 0; u->u_metadata.u_firstlineno = lineno; u->u_metadata.u_consts = PyDict_New(); if (!u->u_metadata.u_consts) { @@ -1717,8 +1744,10 @@ get_ref_type(struct compiler *c, PyObject *name) { int scope; if (c->u->u_scope_type == COMPILER_SCOPE_CLASS && - _PyUnicode_EqualToASCIIString(name, "__class__")) + (_PyUnicode_EqualToASCIIString(name, "__class__") || + _PyUnicode_EqualToASCIIString(name, "__classdict__"))) { return CELL; + } scope = _PyST_GetScope(c->u->u_ste, name); if (scope == 0) { PyErr_Format(PyExc_SystemError, @@ -2084,26 +2113,81 @@ wrap_in_stopiteration_handler(struct compiler *c) } static int -compiler_function(struct compiler *c, stmt_ty s, int is_async) +compiler_type_params(struct compiler *c, asdl_type_param_seq *type_params) +{ + if (!type_params) { + return SUCCESS; + } + Py_ssize_t n = asdl_seq_LEN(type_params); + + for (Py_ssize_t i = 0; i < n; i++) { + type_param_ty typeparam = asdl_seq_GET(type_params, i); + location loc = LOC(typeparam); + switch(typeparam->kind) { + case TypeVar_kind: + ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVar.name); + if (typeparam->v.TypeVar.bound) { + expr_ty bound = typeparam->v.TypeVar.bound; + if (compiler_enter_scope(c, typeparam->v.TypeVar.name, COMPILER_SCOPE_TYPEPARAMS, + (void *)typeparam, bound->lineno) == -1) { + return ERROR; + } + VISIT_IN_SCOPE(c, expr, bound); + ADDOP_IN_SCOPE(c, loc, RETURN_VALUE); + PyCodeObject *co = optimize_and_assemble(c, 1); + compiler_exit_scope(c); + if (co == NULL) { + return ERROR; + } + if (compiler_make_closure(c, loc, co, 0) < 0) { + Py_DECREF(co); + return ERROR; + } + Py_DECREF(co); + + int intrinsic = bound->kind == Tuple_kind + ? INTRINSIC_TYPEVAR_WITH_CONSTRAINTS + : INTRINSIC_TYPEVAR_WITH_BOUND; + ADDOP_I(c, loc, CALL_INTRINSIC_2, intrinsic); + } + else { + ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVAR); + } + ADDOP_I(c, loc, COPY, 1); + RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVar.name, Store)); + break; + case TypeVarTuple_kind: + ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVarTuple.name); + ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVARTUPLE); + ADDOP_I(c, loc, COPY, 1); + RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVarTuple.name, Store)); + break; + case ParamSpec_kind: + ADDOP_LOAD_CONST(c, loc, typeparam->v.ParamSpec.name); + ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PARAMSPEC); + ADDOP_I(c, loc, COPY, 1); + RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.ParamSpec.name, Store)); + break; + } + } + ADDOP_I(c, LOC(asdl_seq_GET(type_params, 0)), BUILD_TUPLE, n); + return SUCCESS; +} + +static int +compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags, + int firstlineno) { - PyCodeObject *co; PyObject *docstring = NULL; arguments_ty args; - expr_ty returns; identifier name; - asdl_expr_seq* decos; asdl_stmt_seq *body; - Py_ssize_t i, funcflags; - int annotations; int scope_type; - int firstlineno; if (is_async) { assert(s->kind == AsyncFunctionDef_kind); args = s->v.AsyncFunctionDef.args; - returns = s->v.AsyncFunctionDef.returns; - decos = s->v.AsyncFunctionDef.decorator_list; name = s->v.AsyncFunctionDef.name; body = s->v.AsyncFunctionDef.body; @@ -2112,33 +2196,12 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) assert(s->kind == FunctionDef_kind); args = s->v.FunctionDef.args; - returns = s->v.FunctionDef.returns; - decos = s->v.FunctionDef.decorator_list; name = s->v.FunctionDef.name; body = s->v.FunctionDef.body; scope_type = COMPILER_SCOPE_FUNCTION; } - RETURN_IF_ERROR(compiler_check_debug_args(c, args)); - RETURN_IF_ERROR(compiler_decorators(c, decos)); - - firstlineno = s->lineno; - if (asdl_seq_LEN(decos)) { - firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno; - } - - location loc = LOC(s); - funcflags = compiler_default_arguments(c, loc, args); - if (funcflags == -1) { - return ERROR; - } - annotations = compiler_visit_annotations(c, loc, args, returns); - RETURN_IF_ERROR(annotations); - if (annotations > 0) { - funcflags |= 0x04; - } - RETURN_IF_ERROR( compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno)); @@ -2154,7 +2217,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args); c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs); c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - for (i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) { + for (Py_ssize_t i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) { VISIT_IN_SCOPE(c, stmt, (stmt_ty)asdl_seq_GET(body, i)); } if (c->u->u_ste->ste_coroutine || c->u->u_ste->ste_generator) { @@ -2163,29 +2226,52 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) return ERROR; } } - co = optimize_and_assemble(c, 1); + PyCodeObject *co = optimize_and_assemble(c, 1); compiler_exit_scope(c); if (co == NULL) { Py_XDECREF(co); return ERROR; } + location loc = LOC(s); if (compiler_make_closure(c, loc, co, funcflags) < 0) { Py_DECREF(co); return ERROR; } Py_DECREF(co); - - RETURN_IF_ERROR(compiler_apply_decorators(c, decos)); - return compiler_nameop(c, loc, name, Store); + return SUCCESS; } static int -compiler_class(struct compiler *c, stmt_ty s) +compiler_function(struct compiler *c, stmt_ty s, int is_async) { - PyCodeObject *co; - int i, firstlineno; - asdl_expr_seq *decos = s->v.ClassDef.decorator_list; + arguments_ty args; + expr_ty returns; + identifier name; + asdl_expr_seq *decos; + asdl_type_param_seq *type_params; + Py_ssize_t funcflags; + int annotations; + int firstlineno; + if (is_async) { + assert(s->kind == AsyncFunctionDef_kind); + + args = s->v.AsyncFunctionDef.args; + returns = s->v.AsyncFunctionDef.returns; + decos = s->v.AsyncFunctionDef.decorator_list; + name = s->v.AsyncFunctionDef.name; + type_params = s->v.AsyncFunctionDef.type_params; + } else { + assert(s->kind == FunctionDef_kind); + + args = s->v.FunctionDef.args; + returns = s->v.FunctionDef.returns; + decos = s->v.FunctionDef.decorator_list; + name = s->v.FunctionDef.name; + type_params = s->v.FunctionDef.type_params; + } + + RETURN_IF_ERROR(compiler_check_debug_args(c, args)); RETURN_IF_ERROR(compiler_decorators(c, decos)); firstlineno = s->lineno; @@ -2193,6 +2279,108 @@ compiler_class(struct compiler *c, stmt_ty s) firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno; } + location loc = LOC(s); + + int is_generic = asdl_seq_LEN(type_params) > 0; + + if (is_generic) { + // Used by the CALL to the type parameters function. + ADDOP(c, loc, PUSH_NULL); + } + + funcflags = compiler_default_arguments(c, loc, args); + if (funcflags == -1) { + return ERROR; + } + + int num_typeparam_args = 0; + + if (is_generic) { + if (funcflags & 0x01) { + num_typeparam_args += 1; + } + if (funcflags & 0x02) { + num_typeparam_args += 1; + } + if (num_typeparam_args == 2) { + ADDOP_I(c, loc, SWAP, 2); + } + PyObject *type_params_name = PyUnicode_FromFormat("", name); + if (!type_params_name) { + return ERROR; + } + if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_TYPEPARAMS, + (void *)type_params, firstlineno) == -1) { + Py_DECREF(type_params_name); + return ERROR; + } + Py_DECREF(type_params_name); + RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params)); + if ((funcflags & 0x01) || (funcflags & 0x02)) { + RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, 0, loc)); + } + if ((funcflags & 0x01) && (funcflags & 0x02)) { + RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, 1, loc)); + } + } + + annotations = compiler_visit_annotations(c, loc, args, returns); + if (annotations < 0) { + if (is_generic) { + compiler_exit_scope(c); + } + return ERROR; + } + if (annotations > 0) { + funcflags |= 0x04; + } + + if (compiler_function_body(c, s, is_async, funcflags, firstlineno) < 0) { + if (is_generic) { + compiler_exit_scope(c); + } + return ERROR; + } + + if (is_generic) { + RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i( + INSTR_SEQUENCE(c), SWAP, 2, loc)); + RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i( + INSTR_SEQUENCE(c), CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS, loc)); + + c->u->u_metadata.u_argcount = num_typeparam_args; + PyCodeObject *co = optimize_and_assemble(c, 0); + compiler_exit_scope(c); + if (co == NULL) { + return ERROR; + } + if (compiler_make_closure(c, loc, co, 0) < 0) { + Py_DECREF(co); + return ERROR; + } + Py_DECREF(co); + if (num_typeparam_args > 0) { + ADDOP_I(c, loc, SWAP, num_typeparam_args + 1); + } + ADDOP_I(c, loc, CALL, num_typeparam_args); + } + + RETURN_IF_ERROR(compiler_apply_decorators(c, decos)); + return compiler_nameop(c, loc, name, Store); +} + +static int +compiler_set_type_params_in_class(struct compiler *c, location loc) +{ + _Py_DECLARE_STR(type_params, ".type_params"); + RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_STR(type_params), Load)); + RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_ID(__type_params__), Store)); + return 1; +} + +static int +compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno) +{ /* ultimately generate code for: = __build_class__(, , *, **) where: @@ -2203,69 +2391,105 @@ compiler_class(struct compiler *c, stmt_ty s) is the keyword arguments and **kwds argument This borrows from compiler_call. */ + /* 1. compile the class body into a code object */ RETURN_IF_ERROR( compiler_enter_scope(c, s->v.ClassDef.name, COMPILER_SCOPE_CLASS, (void *)s, firstlineno)); - /* this block represents what we do in the new scope */ - { - location loc = LOCATION(firstlineno, firstlineno, 0, 0); - /* use the class name for name mangling */ - Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name)); - /* load (global) __name__ ... */ - if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) { + location loc = LOCATION(firstlineno, firstlineno, 0, 0); + /* use the class name for name mangling */ + Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name)); + /* load (global) __name__ ... */ + if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) { + compiler_exit_scope(c); + return ERROR; + } + /* ... and store it as __module__ */ + if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) { + compiler_exit_scope(c); + return ERROR; + } + assert(c->u->u_metadata.u_qualname); + ADDOP_LOAD_CONST(c, loc, c->u->u_metadata.u_qualname); + if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) { + compiler_exit_scope(c); + return ERROR; + } + asdl_type_param_seq *type_params = s->v.ClassDef.type_params; + if (asdl_seq_LEN(type_params) > 0) { + if (!compiler_set_type_params_in_class(c, loc)) { compiler_exit_scope(c); return ERROR; } - /* ... and store it as __module__ */ - if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) { + } + if (c->u->u_ste->ste_needs_classdict) { + ADDOP(c, loc, LOAD_LOCALS); + + // We can't use compiler_nameop here because we need to generate a + // STORE_DEREF in a class namespace, and compiler_nameop() won't do + // that by default. + PyObject *cellvars = c->u->u_metadata.u_cellvars; + if (compiler_addop_o(c->u, loc, STORE_DEREF, cellvars, + &_Py_ID(__classdict__)) < 0) { compiler_exit_scope(c); return ERROR; } - assert(c->u->u_metadata.u_qualname); - ADDOP_LOAD_CONST(c, loc, c->u->u_metadata.u_qualname); - if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) { + } + /* compile the body proper */ + if (compiler_body(c, loc, s->v.ClassDef.body) < 0) { + compiler_exit_scope(c); + return ERROR; + } + /* The following code is artificial */ + /* Set __classdictcell__ if necessary */ + if (c->u->u_ste->ste_needs_classdict) { + /* Store __classdictcell__ into class namespace */ + int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__)); + if (i < 0) { compiler_exit_scope(c); return ERROR; } - /* compile the body proper */ - if (compiler_body(c, loc, s->v.ClassDef.body) < 0) { + ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i); + if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classdictcell__), Store) < 0) { compiler_exit_scope(c); return ERROR; } - /* The following code is artificial */ - /* Return __classcell__ if it is referenced, otherwise return None */ - if (c->u->u_ste->ste_needs_class_closure) { - /* Store __classcell__ into class namespace & return it */ - i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__)); - if (i < 0) { - compiler_exit_scope(c); - return ERROR; - } - ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i); - ADDOP_I(c, NO_LOCATION, COPY, 1); - if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) { - compiler_exit_scope(c); - return ERROR; - } + } + /* Return __classcell__ if it is referenced, otherwise return None */ + if (c->u->u_ste->ste_needs_class_closure) { + /* Store __classcell__ into class namespace & return it */ + int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__)); + if (i < 0) { + compiler_exit_scope(c); + return ERROR; } - else { - /* No methods referenced __class__, so just return None */ - ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); + ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i); + ADDOP_I(c, NO_LOCATION, COPY, 1); + if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) { + compiler_exit_scope(c); + return ERROR; } - ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE); - /* create the code object */ - co = optimize_and_assemble(c, 1); } + else { + /* No methods referenced __class__, so just return None */ + ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); + } + ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE); + /* create the code object */ + PyCodeObject *co = optimize_and_assemble(c, 1); + /* leave the new scope */ compiler_exit_scope(c); if (co == NULL) { return ERROR; } - location loc = LOC(s); /* 2. load the 'build_class' function */ + + // these instructions should be attributed to the class line, + // not a decorator line + loc = LOC(s); ADDOP(c, loc, PUSH_NULL); ADDOP(c, loc, LOAD_BUILD_CLASS); @@ -2279,10 +2503,100 @@ compiler_class(struct compiler *c, stmt_ty s) /* 4. load class name */ ADDOP_LOAD_CONST(c, loc, s->v.ClassDef.name); - /* 5. generate the rest of the code for the call */ - RETURN_IF_ERROR(compiler_call_helper(c, loc, 2, - s->v.ClassDef.bases, - s->v.ClassDef.keywords)); + return SUCCESS; +} + +static int +compiler_class(struct compiler *c, stmt_ty s) +{ + asdl_expr_seq *decos = s->v.ClassDef.decorator_list; + + RETURN_IF_ERROR(compiler_decorators(c, decos)); + + int firstlineno = s->lineno; + if (asdl_seq_LEN(decos)) { + firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno; + } + location loc = LOC(s); + + asdl_type_param_seq *type_params = s->v.ClassDef.type_params; + int is_generic = asdl_seq_LEN(type_params) > 0; + if (is_generic) { + Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name)); + ADDOP(c, loc, PUSH_NULL); + PyObject *type_params_name = PyUnicode_FromFormat("", + s->v.ClassDef.name); + if (!type_params_name) { + return ERROR; + } + if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_TYPEPARAMS, + (void *)type_params, firstlineno) == -1) { + Py_DECREF(type_params_name); + return ERROR; + } + Py_DECREF(type_params_name); + RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params)); + _Py_DECLARE_STR(type_params, ".type_params"); + RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Store)); + } + + if (compiler_class_body(c, s, firstlineno) < 0) { + if (is_generic) { + compiler_exit_scope(c); + } + return ERROR; + } + + /* generate the rest of the code for the call */ + + if (is_generic) { + _Py_DECLARE_STR(type_params, ".type_params"); + _Py_DECLARE_STR(generic_base, ".generic_base"); + RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Load)); + RETURN_IF_ERROR_IN_SCOPE( + c, codegen_addop_i(INSTR_SEQUENCE(c), CALL_INTRINSIC_1, INTRINSIC_SUBSCRIPT_GENERIC, loc) + ) + RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(generic_base), Store)); + + Py_ssize_t original_len = asdl_seq_LEN(s->v.ClassDef.bases); + asdl_expr_seq *bases = _Py_asdl_expr_seq_new( + original_len + 1, c->c_arena); + if (bases == NULL) { + compiler_exit_scope(c); + return ERROR; + } + for (Py_ssize_t i = 0; i < original_len; i++) { + asdl_seq_SET(bases, i, asdl_seq_GET(s->v.ClassDef.bases, i)); + } + expr_ty name_node = _PyAST_Name( + &_Py_STR(generic_base), Load, + loc.lineno, loc.col_offset, loc.end_lineno, loc.end_col_offset, c->c_arena + ); + if (name_node == NULL) { + compiler_exit_scope(c); + return ERROR; + } + asdl_seq_SET(bases, original_len, name_node); + RETURN_IF_ERROR_IN_SCOPE(c, compiler_call_helper(c, loc, 2, + bases, + s->v.ClassDef.keywords)); + + PyCodeObject *co = optimize_and_assemble(c, 0); + compiler_exit_scope(c); + if (co == NULL) { + return ERROR; + } + if (compiler_make_closure(c, loc, co, 0) < 0) { + Py_DECREF(co); + return ERROR; + } + Py_DECREF(co); + ADDOP_I(c, loc, CALL, 0); + } else { + RETURN_IF_ERROR(compiler_call_helper(c, loc, 2, + s->v.ClassDef.bases, + s->v.ClassDef.keywords)); + } /* 6. apply decorators */ RETURN_IF_ERROR(compiler_apply_decorators(c, decos)); @@ -2292,6 +2606,87 @@ compiler_class(struct compiler *c, stmt_ty s) return SUCCESS; } +static int +compiler_typealias_body(struct compiler *c, stmt_ty s) +{ + location loc = LOC(s); + PyObject *name = s->v.TypeAlias.name->v.Name.id; + RETURN_IF_ERROR( + compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno)); + /* Make None the first constant, so the evaluate function can't have a + docstring. */ + RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None)); + VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value); + ADDOP_IN_SCOPE(c, loc, RETURN_VALUE); + PyCodeObject *co = optimize_and_assemble(c, 0); + compiler_exit_scope(c); + if (co == NULL) { + return ERROR; + } + if (compiler_make_closure(c, loc, co, 0) < 0) { + Py_DECREF(co); + return ERROR; + } + Py_DECREF(co); + ADDOP_I(c, loc, BUILD_TUPLE, 3); + ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEALIAS); + return SUCCESS; +} + +static int +compiler_typealias(struct compiler *c, stmt_ty s) +{ + location loc = LOC(s); + asdl_type_param_seq *type_params = s->v.TypeAlias.type_params; + int is_generic = asdl_seq_LEN(type_params) > 0; + PyObject *name = s->v.TypeAlias.name->v.Name.id; + if (is_generic) { + ADDOP(c, loc, PUSH_NULL); + PyObject *type_params_name = PyUnicode_FromFormat("", + name); + if (!type_params_name) { + return ERROR; + } + if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_TYPEPARAMS, + (void *)type_params, loc.lineno) == -1) { + Py_DECREF(type_params_name); + return ERROR; + } + Py_DECREF(type_params_name); + RETURN_IF_ERROR_IN_SCOPE( + c, compiler_addop_load_const(c->c_const_cache, c->u, loc, name) + ); + RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params)); + } + else { + ADDOP_LOAD_CONST(c, loc, name); + ADDOP_LOAD_CONST(c, loc, Py_None); + } + + if (compiler_typealias_body(c, s) < 0) { + if (is_generic) { + compiler_exit_scope(c); + } + return ERROR; + } + + if (is_generic) { + PyCodeObject *co = optimize_and_assemble(c, 0); + compiler_exit_scope(c); + if (co == NULL) { + return ERROR; + } + if (compiler_make_closure(c, loc, co, 0) < 0) { + Py_DECREF(co); + return ERROR; + } + Py_DECREF(co); + ADDOP_I(c, loc, CALL, 0); + } + RETURN_IF_ERROR(compiler_nameop(c, loc, name, Store)); + return SUCCESS; +} + /* Return false if the expression is a constant value except named singletons. Return true otherwise. */ static bool @@ -2704,7 +3099,7 @@ compiler_return(struct compiler *c, stmt_ty s) location loc = LOC(s); int preserve_tos = ((s->v.Return.value != NULL) && (s->v.Return.value->kind != Constant_kind)); - if (c->u->u_ste->ste_type != FunctionBlock) { + if (!_PyST_IsFunctionLike(c->u->u_ste)) { return compiler_error(c, loc, "'return' outside function"); } if (s->v.Return.value != NULL && @@ -3518,6 +3913,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) return compiler_function(c, s, 0); case ClassDef_kind: return compiler_class(c, s); + case TypeAlias_kind: + return compiler_typealias(c, s); case Return_kind: return compiler_return(c, s); case Delete_kind: @@ -3724,12 +4121,12 @@ compiler_nameop(struct compiler *c, location loc, optype = OP_DEREF; break; case LOCAL: - if (c->u->u_ste->ste_type == FunctionBlock || + if (_PyST_IsFunctionLike(c->u->u_ste) || (PyDict_GetItem(c->u->u_metadata.u_fasthidden, mangled) == Py_True)) optype = OP_FAST; break; case GLOBAL_IMPLICIT: - if (c->u->u_ste->ste_type == FunctionBlock) + if (_PyST_IsFunctionLike(c->u->u_ste)) optype = OP_GLOBAL; break; case GLOBAL_EXPLICIT: @@ -3747,7 +4144,24 @@ compiler_nameop(struct compiler *c, location loc, case OP_DEREF: switch (ctx) { case Load: - op = (c->u->u_ste->ste_type == ClassBlock) ? LOAD_CLASSDEREF : LOAD_DEREF; + if (c->u->u_ste->ste_type == ClassBlock && !c->u->u_in_inlined_comp) { + op = LOAD_FROM_DICT_OR_DEREF; + // First load the locals + if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) { + return ERROR; + } + } + else if (c->u->u_ste->ste_can_see_class_scope) { + op = LOAD_FROM_DICT_OR_DEREF; + // First load the classdict + if (compiler_addop_o(c->u, loc, LOAD_DEREF, + c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { + return ERROR; + } + } + else { + op = LOAD_DEREF; + } break; case Store: op = STORE_DEREF; break; case Del: op = DELETE_DEREF; break; @@ -3763,14 +4177,30 @@ compiler_nameop(struct compiler *c, location loc, return SUCCESS; case OP_GLOBAL: switch (ctx) { - case Load: op = LOAD_GLOBAL; break; + case Load: + if (c->u->u_ste->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) { + op = LOAD_FROM_DICT_OR_GLOBALS; + // First load the classdict + if (compiler_addop_o(c->u, loc, LOAD_DEREF, + c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) { + return ERROR; + } + } else { + op = LOAD_GLOBAL; + } + break; case Store: op = STORE_GLOBAL; break; case Del: op = DELETE_GLOBAL; break; } break; case OP_NAME: switch (ctx) { - case Load: op = LOAD_NAME; break; + case Load: + op = (c->u->u_ste->ste_type == ClassBlock + && c->u->u_in_inlined_comp) + ? LOAD_GLOBAL + : LOAD_NAME; + break; case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; } @@ -4428,6 +4858,8 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e) int opcode = asdl_seq_LEN(meth->v.Attribute.value->v.Call.args) ? LOAD_SUPER_METHOD : LOAD_ZERO_SUPER_METHOD; ADDOP_NAME(c, loc, opcode, meth->v.Attribute.attr, names); + loc = update_start_location_to_match_attr(c, loc, meth); + ADDOP(c, loc, NOP); } else { VISIT(c, expr, meth->v.Attribute.value); loc = update_start_location_to_match_attr(c, loc, meth); @@ -4995,6 +5427,8 @@ push_inlined_comprehension_state(struct compiler *c, location loc, PySTEntryObject *entry, inlined_comprehension_state *state) { + int in_class_block = (c->u->u_ste->ste_type == ClassBlock) && !c->u->u_in_inlined_comp; + c->u->u_in_inlined_comp++; // iterate over names bound in the comprehension and ensure we isolate // them from the outer scope as needed PyObject *k, *v; @@ -5006,8 +5440,8 @@ push_inlined_comprehension_state(struct compiler *c, location loc, // at all; DEF_LOCAL | DEF_NONLOCAL can occur in the case of an // assignment expression to a nonlocal in the comprehension, these don't // need handling here since they shouldn't be isolated - if (symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) { - if (c->u->u_ste->ste_type != FunctionBlock) { + if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) { + if (!_PyST_IsFunctionLike(c->u->u_ste)) { // non-function scope: override this name to use fast locals PyObject *orig = PyDict_GetItem(c->u->u_metadata.u_fasthidden, k); if (orig != Py_True) { @@ -5028,8 +5462,7 @@ push_inlined_comprehension_state(struct compiler *c, location loc, long scope = (symbol >> SCOPE_OFFSET) & SCOPE_MASK; PyObject *outv = PyDict_GetItemWithError(c->u->u_ste->ste_symbols, k); if (outv == NULL) { - assert(PyErr_Occurred()); - return ERROR; + outv = _PyLong_GetZero(); } assert(PyLong_Check(outv)); long outsc = (PyLong_AS_LONG(outv) >> SCOPE_OFFSET) & SCOPE_MASK; @@ -5061,31 +5494,29 @@ push_inlined_comprehension_state(struct compiler *c, location loc, } Py_DECREF(outv); } - if (outsc == LOCAL || outsc == CELL || outsc == FREE) { - // local names bound in comprehension must be isolated from - // outer scope; push existing value (which may be NULL if - // not defined) on stack + // local names bound in comprehension must be isolated from + // outer scope; push existing value (which may be NULL if + // not defined) on stack + if (state->pushed_locals == NULL) { + state->pushed_locals = PyList_New(0); if (state->pushed_locals == NULL) { - state->pushed_locals = PyList_New(0); - if (state->pushed_locals == NULL) { - return ERROR; - } - } - // in the case of a cell, this will actually push the cell - // itself to the stack, then we'll create a new one for the - // comprehension and restore the original one after - ADDOP_NAME(c, loc, LOAD_FAST_AND_CLEAR, k, varnames); - if (scope == CELL) { - if (outsc == FREE) { - ADDOP_NAME(c, loc, MAKE_CELL, k, freevars); - } else { - ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars); - } - } - if (PyList_Append(state->pushed_locals, k) < 0) { return ERROR; } } + // in the case of a cell, this will actually push the cell + // itself to the stack, then we'll create a new one for the + // comprehension and restore the original one after + ADDOP_NAME(c, loc, LOAD_FAST_AND_CLEAR, k, varnames); + if (scope == CELL) { + if (outsc == FREE) { + ADDOP_NAME(c, loc, MAKE_CELL, k, freevars); + } else { + ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars); + } + } + if (PyList_Append(state->pushed_locals, k) < 0) { + return ERROR; + } } } if (state->pushed_locals) { @@ -5103,6 +5534,7 @@ static int pop_inlined_comprehension_state(struct compiler *c, location loc, inlined_comprehension_state state) { + c->u->u_in_inlined_comp--; PyObject *k, *v; Py_ssize_t pos = 0; if (state.temp_symbols) { @@ -5603,7 +6035,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) case DictComp_kind: return compiler_dictcomp(c, e); case Yield_kind: - if (c->u->u_ste->ste_type != FunctionBlock) { + if (!_PyST_IsFunctionLike(c->u->u_ste)) { return compiler_error(c, loc, "'yield' outside function"); } if (e->v.Yield.value) { @@ -5615,7 +6047,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) ADDOP_YIELD(c, loc); break; case YieldFrom_kind: - if (c->u->u_ste->ste_type != FunctionBlock) { + if (!_PyST_IsFunctionLike(c->u->u_ste)) { return compiler_error(c, loc, "'yield' outside function"); } if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) { @@ -5628,7 +6060,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) break; case Await_kind: if (!IS_TOP_LEVEL_AWAIT(c)){ - if (c->u->u_ste->ste_type != FunctionBlock){ + if (!_PyST_IsFunctionLike(c->u->u_ste)) { return compiler_error(c, loc, "'await' outside function"); } @@ -5661,6 +6093,8 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) int opcode = asdl_seq_LEN(e->v.Attribute.value->v.Call.args) ? LOAD_SUPER_ATTR : LOAD_ZERO_SUPER_ATTR; ADDOP_NAME(c, loc, opcode, e->v.Attribute.attr, names); + loc = update_start_location_to_match_attr(c, loc, e); + ADDOP(c, loc, NOP); return SUCCESS; } VISIT(c, expr, e->v.Attribute.value); @@ -6915,7 +7349,7 @@ compute_code_flags(struct compiler *c) { PySTEntryObject *ste = c->u->u_ste; int flags = 0; - if (ste->ste_type == FunctionBlock) { + if (_PyST_IsFunctionLike(c->u->u_ste)) { flags |= CO_NEWLOCALS | CO_OPTIMIZED; if (ste->ste_nested) flags |= CO_NESTED; @@ -7113,7 +7547,7 @@ fix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int * case LOAD_DEREF: case STORE_DEREF: case DELETE_DEREF: - case LOAD_CLASSDEREF: + case LOAD_FROM_DICT_OR_DEREF: assert(oldoffset >= 0); assert(oldoffset < noffsets); assert(fixedmap[oldoffset] >= 0); @@ -7564,7 +7998,7 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, } PyObject * -_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts) +_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts, int nlocals) { PyObject *res = NULL; PyObject *const_cache = PyDict_New(); @@ -7576,7 +8010,7 @@ _PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts) if (instructions_to_cfg(instructions, &g) < 0) { goto error; } - int code_flags = 0, nlocals = 0, nparams = 0, firstlineno = 1; + int code_flags = 0, nparams = 0, firstlineno = 1; if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, code_flags, nlocals, nparams, firstlineno) < 0) { goto error; diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 7f790b79d2844f..f8039a4985d948 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -1293,6 +1293,11 @@ swaptimize(basicblock *block, int *ix) (opcode) == STORE_FAST_MAYBE_NULL || \ (opcode) == POP_TOP) +#define STORES_TO(instr) \ + (((instr).i_opcode == STORE_FAST || \ + (instr).i_opcode == STORE_FAST_MAYBE_NULL) \ + ? (instr).i_oparg : -1) + static int next_swappable_instruction(basicblock *block, int i, int lineno) { @@ -1344,6 +1349,23 @@ apply_static_swaps(basicblock *block, int i) return; } } + // The reordering is not safe if the two instructions to be swapped + // store to the same location, or if any intervening instruction stores + // to the same location as either of them. + int store_j = STORES_TO(block->b_instr[j]); + int store_k = STORES_TO(block->b_instr[k]); + if (store_j >= 0 || store_k >= 0) { + if (store_j == store_k) { + return; + } + for (int idx = j + 1; idx < k; idx++) { + int store_idx = STORES_TO(block->b_instr[idx]); + if (store_idx >= 0 && (store_idx == store_j || store_idx == store_k)) { + return; + } + } + } + // Success! INSTR_SET_OP0(swap, NOP); cfg_instr temp = block->b_instr[j]; diff --git a/Python/frame.c b/Python/frame.c index d792b92fa57560..b84fd9b6a9380a 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -146,10 +146,10 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame) /* Unstable API functions */ -PyCodeObject * +PyObject * PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame) { - PyCodeObject *code = frame->f_code; + PyObject *code = (PyObject *)frame->f_code; Py_INCREF(code); return code; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 014a69ff7e9615..055fb5a0611b96 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -17,7 +17,7 @@ if (err) goto error; next_instr--; } - else if (_Py_atomic_load_relaxed_int32(eval_breaker) && oparg < 2) { + else if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) { goto handle_eval_breaker; } #line 24 "Python/generated_cases.c.h" @@ -47,7 +47,7 @@ next_instr = frame->prev_instr; DISPATCH(); } - if (_Py_atomic_load_relaxed_int32(eval_breaker) && oparg < 2) { + if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) { goto handle_eval_breaker; } } @@ -365,8 +365,7 @@ else { res = Py_False; } - Py_INCREF(res); - #line 370 "Python/generated_cases.c.h" + #line 369 "Python/generated_cases.c.h" stack_pointer[-1] = res; DISPATCH(); } @@ -374,13 +373,13 @@ TARGET(UNARY_INVERT) { PyObject *value = stack_pointer[-1]; PyObject *res; - #line 276 "Python/bytecodes.c" + #line 275 "Python/bytecodes.c" res = PyNumber_Invert(value); - #line 380 "Python/generated_cases.c.h" + #line 379 "Python/generated_cases.c.h" Py_DECREF(value); - #line 278 "Python/bytecodes.c" + #line 277 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; - #line 384 "Python/generated_cases.c.h" + #line 383 "Python/generated_cases.c.h" stack_pointer[-1] = res; DISPATCH(); } @@ -389,7 +388,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *prod; - #line 295 "Python/bytecodes.c" + #line 294 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); STAT_INC(BINARY_OP, hit); @@ -397,7 +396,7 @@ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); if (prod == NULL) goto pop_2_error; - #line 401 "Python/generated_cases.c.h" + #line 400 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = prod; next_instr += 1; @@ -408,14 +407,14 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *prod; - #line 305 "Python/bytecodes.c" + #line 304 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); STAT_INC(BINARY_OP, hit); double dprod = ((PyFloatObject *)left)->ob_fval * ((PyFloatObject *)right)->ob_fval; DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dprod, prod); - #line 419 "Python/generated_cases.c.h" + #line 418 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = prod; next_instr += 1; @@ -426,7 +425,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *sub; - #line 314 "Python/bytecodes.c" + #line 313 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); STAT_INC(BINARY_OP, hit); @@ -434,7 +433,7 @@ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); if (sub == NULL) goto pop_2_error; - #line 438 "Python/generated_cases.c.h" + #line 437 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = sub; next_instr += 1; @@ -445,13 +444,13 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *sub; - #line 324 "Python/bytecodes.c" + #line 323 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); STAT_INC(BINARY_OP, hit); double dsub = ((PyFloatObject *)left)->ob_fval - ((PyFloatObject *)right)->ob_fval; DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dsub, sub); - #line 455 "Python/generated_cases.c.h" + #line 454 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = sub; next_instr += 1; @@ -462,7 +461,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 332 "Python/bytecodes.c" + #line 331 "Python/bytecodes.c" DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); STAT_INC(BINARY_OP, hit); @@ -470,7 +469,7 @@ _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); if (res == NULL) goto pop_2_error; - #line 474 "Python/generated_cases.c.h" + #line 473 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -480,7 +479,7 @@ TARGET(BINARY_OP_INPLACE_ADD_UNICODE) { PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; - #line 348 "Python/bytecodes.c" + #line 347 "Python/bytecodes.c" DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); _Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP]; @@ -507,7 +506,7 @@ if (*target_local == NULL) goto pop_2_error; // The STORE_FAST is already done. JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1); - #line 511 "Python/generated_cases.c.h" + #line 510 "Python/generated_cases.c.h" STACK_SHRINK(2); DISPATCH(); } @@ -516,14 +515,14 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *sum; - #line 377 "Python/bytecodes.c" + #line 376 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); STAT_INC(BINARY_OP, hit); double dsum = ((PyFloatObject *)left)->ob_fval + ((PyFloatObject *)right)->ob_fval; DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dsum, sum); - #line 527 "Python/generated_cases.c.h" + #line 526 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = sum; next_instr += 1; @@ -534,7 +533,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *sum; - #line 386 "Python/bytecodes.c" + #line 385 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); STAT_INC(BINARY_OP, hit); @@ -542,7 +541,7 @@ _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); if (sum == NULL) goto pop_2_error; - #line 546 "Python/generated_cases.c.h" + #line 545 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = sum; next_instr += 1; @@ -555,7 +554,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *container = stack_pointer[-2]; PyObject *res; - #line 404 "Python/bytecodes.c" + #line 403 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -567,12 +566,12 @@ DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ res = PyObject_GetItem(container, sub); - #line 571 "Python/generated_cases.c.h" + #line 570 "Python/generated_cases.c.h" Py_DECREF(container); Py_DECREF(sub); - #line 416 "Python/bytecodes.c" + #line 415 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; - #line 576 "Python/generated_cases.c.h" + #line 575 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -584,7 +583,7 @@ PyObject *start = stack_pointer[-2]; PyObject *container = stack_pointer[-3]; PyObject *res; - #line 420 "Python/bytecodes.c" + #line 419 "Python/bytecodes.c" PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); // Can't use ERROR_IF() here, because we haven't // DECREF'ed container yet, and we still own slice. @@ -597,7 +596,7 @@ } Py_DECREF(container); if (res == NULL) goto pop_3_error; - #line 601 "Python/generated_cases.c.h" + #line 600 "Python/generated_cases.c.h" STACK_SHRINK(2); stack_pointer[-1] = res; DISPATCH(); @@ -608,7 +607,7 @@ PyObject *start = stack_pointer[-2]; PyObject *container = stack_pointer[-3]; PyObject *v = stack_pointer[-4]; - #line 435 "Python/bytecodes.c" + #line 434 "Python/bytecodes.c" PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop); int err; if (slice == NULL) { @@ -621,7 +620,7 @@ Py_DECREF(v); Py_DECREF(container); if (err) goto pop_4_error; - #line 625 "Python/generated_cases.c.h" + #line 624 "Python/generated_cases.c.h" STACK_SHRINK(4); DISPATCH(); } @@ -630,7 +629,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *list = stack_pointer[-2]; PyObject *res; - #line 450 "Python/bytecodes.c" + #line 449 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR); @@ -644,7 +643,7 @@ Py_INCREF(res); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); Py_DECREF(list); - #line 648 "Python/generated_cases.c.h" + #line 647 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -655,7 +654,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *tuple = stack_pointer[-2]; PyObject *res; - #line 466 "Python/bytecodes.c" + #line 465 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR); DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR); @@ -669,7 +668,7 @@ Py_INCREF(res); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); Py_DECREF(tuple); - #line 673 "Python/generated_cases.c.h" + #line 672 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -680,7 +679,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *dict = stack_pointer[-2]; PyObject *res; - #line 482 "Python/bytecodes.c" + #line 481 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); res = PyDict_GetItemWithError(dict, sub); @@ -688,14 +687,14 @@ if (!_PyErr_Occurred(tstate)) { _PyErr_SetKeyError(sub); } - #line 692 "Python/generated_cases.c.h" + #line 691 "Python/generated_cases.c.h" Py_DECREF(dict); Py_DECREF(sub); - #line 490 "Python/bytecodes.c" + #line 489 "Python/bytecodes.c" if (true) goto pop_2_error; } Py_INCREF(res); // Do this before DECREF'ing dict, sub - #line 699 "Python/generated_cases.c.h" + #line 698 "Python/generated_cases.c.h" Py_DECREF(dict); Py_DECREF(sub); STACK_SHRINK(1); @@ -707,7 +706,7 @@ TARGET(BINARY_SUBSCR_GETITEM) { PyObject *sub = stack_pointer[-1]; PyObject *container = stack_pointer[-2]; - #line 497 "Python/bytecodes.c" + #line 496 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR); PyTypeObject *tp = Py_TYPE(container); DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR); @@ -730,15 +729,15 @@ JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR); frame->return_offset = 0; DISPATCH_INLINED(new_frame); - #line 734 "Python/generated_cases.c.h" + #line 733 "Python/generated_cases.c.h" } TARGET(LIST_APPEND) { PyObject *v = stack_pointer[-1]; PyObject *list = stack_pointer[-(2 + (oparg-1))]; - #line 522 "Python/bytecodes.c" + #line 521 "Python/bytecodes.c" if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error; - #line 742 "Python/generated_cases.c.h" + #line 741 "Python/generated_cases.c.h" STACK_SHRINK(1); PREDICT(JUMP_BACKWARD); DISPATCH(); @@ -747,13 +746,13 @@ TARGET(SET_ADD) { PyObject *v = stack_pointer[-1]; PyObject *set = stack_pointer[-(2 + (oparg-1))]; - #line 527 "Python/bytecodes.c" + #line 526 "Python/bytecodes.c" int err = PySet_Add(set, v); - #line 753 "Python/generated_cases.c.h" + #line 752 "Python/generated_cases.c.h" Py_DECREF(v); - #line 529 "Python/bytecodes.c" + #line 528 "Python/bytecodes.c" if (err) goto pop_1_error; - #line 757 "Python/generated_cases.c.h" + #line 756 "Python/generated_cases.c.h" STACK_SHRINK(1); PREDICT(JUMP_BACKWARD); DISPATCH(); @@ -766,7 +765,7 @@ PyObject *container = stack_pointer[-2]; PyObject *v = stack_pointer[-3]; uint16_t counter = read_u16(&next_instr[0].cache); - #line 540 "Python/bytecodes.c" + #line 539 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_IS_ZERO(counter)) { next_instr--; @@ -781,13 +780,13 @@ #endif /* ENABLE_SPECIALIZATION */ /* container[sub] = v */ int err = PyObject_SetItem(container, sub, v); - #line 785 "Python/generated_cases.c.h" + #line 784 "Python/generated_cases.c.h" Py_DECREF(v); Py_DECREF(container); Py_DECREF(sub); - #line 555 "Python/bytecodes.c" + #line 554 "Python/bytecodes.c" if (err) goto pop_3_error; - #line 791 "Python/generated_cases.c.h" + #line 790 "Python/generated_cases.c.h" STACK_SHRINK(3); next_instr += 1; DISPATCH(); @@ -797,7 +796,7 @@ PyObject *sub = stack_pointer[-1]; PyObject *list = stack_pointer[-2]; PyObject *value = stack_pointer[-3]; - #line 559 "Python/bytecodes.c" + #line 558 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR); DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR); @@ -814,7 +813,7 @@ Py_DECREF(old_value); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); Py_DECREF(list); - #line 818 "Python/generated_cases.c.h" + #line 817 "Python/generated_cases.c.h" STACK_SHRINK(3); next_instr += 1; DISPATCH(); @@ -824,13 +823,13 @@ PyObject *sub = stack_pointer[-1]; PyObject *dict = stack_pointer[-2]; PyObject *value = stack_pointer[-3]; - #line 578 "Python/bytecodes.c" + #line 577 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); STAT_INC(STORE_SUBSCR, hit); int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value); Py_DECREF(dict); if (err) goto pop_3_error; - #line 834 "Python/generated_cases.c.h" + #line 833 "Python/generated_cases.c.h" STACK_SHRINK(3); next_instr += 1; DISPATCH(); @@ -839,15 +838,15 @@ TARGET(DELETE_SUBSCR) { PyObject *sub = stack_pointer[-1]; PyObject *container = stack_pointer[-2]; - #line 586 "Python/bytecodes.c" + #line 585 "Python/bytecodes.c" /* del container[sub] */ int err = PyObject_DelItem(container, sub); - #line 846 "Python/generated_cases.c.h" + #line 845 "Python/generated_cases.c.h" Py_DECREF(container); Py_DECREF(sub); - #line 589 "Python/bytecodes.c" + #line 588 "Python/bytecodes.c" if (err) goto pop_2_error; - #line 851 "Python/generated_cases.c.h" + #line 850 "Python/generated_cases.c.h" STACK_SHRINK(2); DISPATCH(); } @@ -855,14 +854,14 @@ TARGET(CALL_INTRINSIC_1) { PyObject *value = stack_pointer[-1]; PyObject *res; - #line 593 "Python/bytecodes.c" + #line 592 "Python/bytecodes.c" assert(oparg <= MAX_INTRINSIC_1); res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value); - #line 862 "Python/generated_cases.c.h" + #line 861 "Python/generated_cases.c.h" Py_DECREF(value); - #line 596 "Python/bytecodes.c" + #line 595 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; - #line 866 "Python/generated_cases.c.h" + #line 865 "Python/generated_cases.c.h" stack_pointer[-1] = res; DISPATCH(); } @@ -871,15 +870,15 @@ PyObject *value1 = stack_pointer[-1]; PyObject *value2 = stack_pointer[-2]; PyObject *res; - #line 600 "Python/bytecodes.c" + #line 599 "Python/bytecodes.c" assert(oparg <= MAX_INTRINSIC_2); res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1); - #line 878 "Python/generated_cases.c.h" + #line 877 "Python/generated_cases.c.h" Py_DECREF(value2); Py_DECREF(value1); - #line 603 "Python/bytecodes.c" + #line 602 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; - #line 883 "Python/generated_cases.c.h" + #line 882 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; DISPATCH(); @@ -887,7 +886,7 @@ TARGET(RAISE_VARARGS) { PyObject **args = (stack_pointer - oparg); - #line 607 "Python/bytecodes.c" + #line 606 "Python/bytecodes.c" PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: @@ -905,12 +904,12 @@ break; } if (true) { STACK_SHRINK(oparg); goto error; } - #line 909 "Python/generated_cases.c.h" + #line 908 "Python/generated_cases.c.h" } TARGET(INTERPRETER_EXIT) { PyObject *retval = stack_pointer[-1]; - #line 627 "Python/bytecodes.c" + #line 626 "Python/bytecodes.c" assert(frame == &entry_frame); assert(_PyFrame_IsIncomplete(frame)); STACK_SHRINK(1); // Since we're not going to DISPATCH() @@ -921,12 +920,12 @@ assert(!_PyErr_Occurred(tstate)); _Py_LeaveRecursiveCallTstate(tstate); return retval; - #line 925 "Python/generated_cases.c.h" + #line 924 "Python/generated_cases.c.h" } TARGET(RETURN_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 640 "Python/bytecodes.c" + #line 639 "Python/bytecodes.c" STACK_SHRINK(1); assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -939,12 +938,12 @@ frame->prev_instr += frame->return_offset; _PyFrame_StackPush(frame, retval); goto resume_frame; - #line 943 "Python/generated_cases.c.h" + #line 942 "Python/generated_cases.c.h" } TARGET(INSTRUMENTED_RETURN_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 655 "Python/bytecodes.c" + #line 654 "Python/bytecodes.c" int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, next_instr-1, retval); @@ -961,11 +960,11 @@ frame->prev_instr += frame->return_offset; _PyFrame_StackPush(frame, retval); goto resume_frame; - #line 965 "Python/generated_cases.c.h" + #line 964 "Python/generated_cases.c.h" } TARGET(RETURN_CONST) { - #line 674 "Python/bytecodes.c" + #line 673 "Python/bytecodes.c" PyObject *retval = GETITEM(frame->f_code->co_consts, oparg); Py_INCREF(retval); assert(EMPTY()); @@ -979,11 +978,11 @@ frame->prev_instr += frame->return_offset; _PyFrame_StackPush(frame, retval); goto resume_frame; - #line 983 "Python/generated_cases.c.h" + #line 982 "Python/generated_cases.c.h" } TARGET(INSTRUMENTED_RETURN_CONST) { - #line 690 "Python/bytecodes.c" + #line 689 "Python/bytecodes.c" PyObject *retval = GETITEM(frame->f_code->co_consts, oparg); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, @@ -1001,13 +1000,13 @@ frame->prev_instr += frame->return_offset; _PyFrame_StackPush(frame, retval); goto resume_frame; - #line 1005 "Python/generated_cases.c.h" + #line 1004 "Python/generated_cases.c.h" } TARGET(GET_AITER) { PyObject *obj = stack_pointer[-1]; PyObject *iter; - #line 710 "Python/bytecodes.c" + #line 709 "Python/bytecodes.c" unaryfunc getter = NULL; PyTypeObject *type = Py_TYPE(obj); @@ -1020,16 +1019,16 @@ "'async for' requires an object with " "__aiter__ method, got %.100s", type->tp_name); - #line 1024 "Python/generated_cases.c.h" + #line 1023 "Python/generated_cases.c.h" Py_DECREF(obj); - #line 723 "Python/bytecodes.c" + #line 722 "Python/bytecodes.c" if (true) goto pop_1_error; } iter = (*getter)(obj); - #line 1031 "Python/generated_cases.c.h" + #line 1030 "Python/generated_cases.c.h" Py_DECREF(obj); - #line 728 "Python/bytecodes.c" + #line 727 "Python/bytecodes.c" if (iter == NULL) goto pop_1_error; if (Py_TYPE(iter)->tp_as_async == NULL || @@ -1042,7 +1041,7 @@ Py_DECREF(iter); if (true) goto pop_1_error; } - #line 1046 "Python/generated_cases.c.h" + #line 1045 "Python/generated_cases.c.h" stack_pointer[-1] = iter; DISPATCH(); } @@ -1050,7 +1049,7 @@ TARGET(GET_ANEXT) { PyObject *aiter = stack_pointer[-1]; PyObject *awaitable; - #line 743 "Python/bytecodes.c" + #line 742 "Python/bytecodes.c" unaryfunc getter = NULL; PyObject *next_iter = NULL; PyTypeObject *type = Py_TYPE(aiter); @@ -1094,7 +1093,7 @@ } } - #line 1098 "Python/generated_cases.c.h" + #line 1097 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = awaitable; PREDICT(LOAD_CONST); @@ -1105,16 +1104,16 @@ PREDICTED(GET_AWAITABLE); PyObject *iterable = stack_pointer[-1]; PyObject *iter; - #line 790 "Python/bytecodes.c" + #line 789 "Python/bytecodes.c" iter = _PyCoro_GetAwaitableIter(iterable); if (iter == NULL) { format_awaitable_error(tstate, Py_TYPE(iterable), oparg); } - #line 1116 "Python/generated_cases.c.h" + #line 1115 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 797 "Python/bytecodes.c" + #line 796 "Python/bytecodes.c" if (iter != NULL && PyCoro_CheckExact(iter)) { PyObject *yf = _PyGen_yf((PyGenObject*)iter); @@ -1132,7 +1131,7 @@ if (iter == NULL) goto pop_1_error; - #line 1136 "Python/generated_cases.c.h" + #line 1135 "Python/generated_cases.c.h" stack_pointer[-1] = iter; PREDICT(LOAD_CONST); DISPATCH(); @@ -1144,7 +1143,7 @@ PyObject *v = stack_pointer[-1]; PyObject *receiver = stack_pointer[-2]; PyObject *retval; - #line 823 "Python/bytecodes.c" + #line 822 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PySendCache *cache = (_PySendCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1191,7 +1190,7 @@ } } Py_DECREF(v); - #line 1195 "Python/generated_cases.c.h" + #line 1194 "Python/generated_cases.c.h" stack_pointer[-1] = retval; next_instr += 1; DISPATCH(); @@ -1200,7 +1199,7 @@ TARGET(SEND_GEN) { PyObject *v = stack_pointer[-1]; PyObject *receiver = stack_pointer[-2]; - #line 872 "Python/bytecodes.c" + #line 871 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, SEND); PyGenObject *gen = (PyGenObject *)receiver; DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && @@ -1216,12 +1215,12 @@ tstate->exc_info = &gen->gi_exc_state; JUMPBY(INLINE_CACHE_ENTRIES_SEND); DISPATCH_INLINED(gen_frame); - #line 1220 "Python/generated_cases.c.h" + #line 1219 "Python/generated_cases.c.h" } TARGET(INSTRUMENTED_YIELD_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 890 "Python/bytecodes.c" + #line 889 "Python/bytecodes.c" assert(frame != &entry_frame); PyGenObject *gen = _PyFrame_GetGenerator(frame); gen->gi_frame_state = FRAME_SUSPENDED; @@ -1238,12 +1237,12 @@ gen_frame->previous = NULL; _PyFrame_StackPush(frame, retval); goto resume_frame; - #line 1242 "Python/generated_cases.c.h" + #line 1241 "Python/generated_cases.c.h" } TARGET(YIELD_VALUE) { PyObject *retval = stack_pointer[-1]; - #line 909 "Python/bytecodes.c" + #line 908 "Python/bytecodes.c" // NOTE: It's important that YIELD_VALUE never raises an exception! // The compiler treats any exception raised here as a failed close() // or throw() call. @@ -1259,15 +1258,15 @@ gen_frame->previous = NULL; _PyFrame_StackPush(frame, retval); goto resume_frame; - #line 1263 "Python/generated_cases.c.h" + #line 1262 "Python/generated_cases.c.h" } TARGET(POP_EXCEPT) { PyObject *exc_value = stack_pointer[-1]; - #line 927 "Python/bytecodes.c" + #line 926 "Python/bytecodes.c" _PyErr_StackItem *exc_info = tstate->exc_info; Py_XSETREF(exc_info->exc_value, exc_value); - #line 1271 "Python/generated_cases.c.h" + #line 1270 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } @@ -1275,7 +1274,7 @@ TARGET(RERAISE) { PyObject *exc = stack_pointer[-1]; PyObject **values = (stack_pointer - (1 + oparg)); - #line 932 "Python/bytecodes.c" + #line 931 "Python/bytecodes.c" assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = values[0]; @@ -1293,26 +1292,26 @@ Py_INCREF(exc); _PyErr_SetRaisedException(tstate, exc); goto exception_unwind; - #line 1297 "Python/generated_cases.c.h" + #line 1296 "Python/generated_cases.c.h" } TARGET(END_ASYNC_FOR) { PyObject *exc = stack_pointer[-1]; PyObject *awaitable = stack_pointer[-2]; - #line 952 "Python/bytecodes.c" + #line 951 "Python/bytecodes.c" assert(exc && PyExceptionInstance_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { - #line 1306 "Python/generated_cases.c.h" + #line 1305 "Python/generated_cases.c.h" Py_DECREF(awaitable); Py_DECREF(exc); - #line 955 "Python/bytecodes.c" + #line 954 "Python/bytecodes.c" } else { Py_INCREF(exc); _PyErr_SetRaisedException(tstate, exc); goto exception_unwind; } - #line 1316 "Python/generated_cases.c.h" + #line 1315 "Python/generated_cases.c.h" STACK_SHRINK(2); DISPATCH(); } @@ -1323,23 +1322,23 @@ PyObject *sub_iter = stack_pointer[-3]; PyObject *none; PyObject *value; - #line 964 "Python/bytecodes.c" + #line 963 "Python/bytecodes.c" assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) { value = Py_NewRef(((PyStopIterationObject *)exc_value)->value); - #line 1332 "Python/generated_cases.c.h" + #line 1331 "Python/generated_cases.c.h" Py_DECREF(sub_iter); Py_DECREF(last_sent_val); Py_DECREF(exc_value); - #line 969 "Python/bytecodes.c" - none = Py_NewRef(Py_None); + #line 968 "Python/bytecodes.c" + none = Py_None; } else { _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); goto exception_unwind; } - #line 1343 "Python/generated_cases.c.h" + #line 1342 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = value; stack_pointer[-2] = none; @@ -1348,9 +1347,9 @@ TARGET(LOAD_ASSERTION_ERROR) { PyObject *value; - #line 978 "Python/bytecodes.c" + #line 977 "Python/bytecodes.c" value = Py_NewRef(PyExc_AssertionError); - #line 1354 "Python/generated_cases.c.h" + #line 1353 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = value; DISPATCH(); @@ -1358,7 +1357,7 @@ TARGET(LOAD_BUILD_CLASS) { PyObject *bc; - #line 982 "Python/bytecodes.c" + #line 981 "Python/bytecodes.c" if (PyDict_CheckExact(BUILTINS())) { bc = _PyDict_GetItemWithError(BUILTINS(), &_Py_ID(__build_class__)); @@ -1380,7 +1379,7 @@ if (true) goto error; } } - #line 1384 "Python/generated_cases.c.h" + #line 1383 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = bc; DISPATCH(); @@ -1395,7 +1394,7 @@ if (ns == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); - #line 1399 "Python/generated_cases.c.h" + #line 1398 "Python/generated_cases.c.h" Py_DECREF(v); #line 1013 "Python/bytecodes.c" if (true) goto pop_1_error; @@ -1404,11 +1403,11 @@ err = PyDict_SetItem(ns, name, v); else err = PyObject_SetItem(ns, name, v); - #line 1408 "Python/generated_cases.c.h" + #line 1407 "Python/generated_cases.c.h" Py_DECREF(v); #line 1020 "Python/bytecodes.c" if (err) goto pop_1_error; - #line 1412 "Python/generated_cases.c.h" + #line 1411 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } @@ -1431,7 +1430,7 @@ name); goto error; } - #line 1435 "Python/generated_cases.c.h" + #line 1434 "Python/generated_cases.c.h" DISPATCH(); } @@ -1452,11 +1451,11 @@ #endif /* ENABLE_SPECIALIZATION */ PyObject **top = stack_pointer + oparg - 1; int res = unpack_iterable(tstate, seq, oparg, -1, top); - #line 1456 "Python/generated_cases.c.h" + #line 1455 "Python/generated_cases.c.h" Py_DECREF(seq); #line 1063 "Python/bytecodes.c" if (res == 0) goto pop_1_error; - #line 1460 "Python/generated_cases.c.h" + #line 1459 "Python/generated_cases.c.h" STACK_SHRINK(1); STACK_GROW(oparg); next_instr += 1; @@ -1473,7 +1472,7 @@ STAT_INC(UNPACK_SEQUENCE, hit); values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1)); values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0)); - #line 1477 "Python/generated_cases.c.h" + #line 1476 "Python/generated_cases.c.h" Py_DECREF(seq); STACK_SHRINK(1); STACK_GROW(oparg); @@ -1492,7 +1491,7 @@ for (int i = oparg; --i >= 0; ) { *values++ = Py_NewRef(items[i]); } - #line 1496 "Python/generated_cases.c.h" + #line 1495 "Python/generated_cases.c.h" Py_DECREF(seq); STACK_SHRINK(1); STACK_GROW(oparg); @@ -1511,7 +1510,7 @@ for (int i = oparg; --i >= 0; ) { *values++ = Py_NewRef(items[i]); } - #line 1515 "Python/generated_cases.c.h" + #line 1514 "Python/generated_cases.c.h" Py_DECREF(seq); STACK_SHRINK(1); STACK_GROW(oparg); @@ -1525,11 +1524,11 @@ int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); PyObject **top = stack_pointer + totalargs - 1; int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top); - #line 1529 "Python/generated_cases.c.h" + #line 1528 "Python/generated_cases.c.h" Py_DECREF(seq); #line 1103 "Python/bytecodes.c" if (res == 0) goto pop_1_error; - #line 1533 "Python/generated_cases.c.h" + #line 1532 "Python/generated_cases.c.h" STACK_GROW((oparg & 0xFF) + (oparg >> 8)); DISPATCH(); } @@ -1556,12 +1555,12 @@ #endif /* ENABLE_SPECIALIZATION */ PyObject *name = GETITEM(frame->f_code->co_names, oparg); int err = PyObject_SetAttr(owner, name, v); - #line 1560 "Python/generated_cases.c.h" + #line 1559 "Python/generated_cases.c.h" Py_DECREF(v); Py_DECREF(owner); #line 1130 "Python/bytecodes.c" if (err) goto pop_2_error; - #line 1565 "Python/generated_cases.c.h" + #line 1564 "Python/generated_cases.c.h" STACK_SHRINK(2); next_instr += 4; DISPATCH(); @@ -1572,11 +1571,11 @@ #line 1134 "Python/bytecodes.c" PyObject *name = GETITEM(frame->f_code->co_names, oparg); int err = PyObject_SetAttr(owner, name, (PyObject *)NULL); - #line 1576 "Python/generated_cases.c.h" + #line 1575 "Python/generated_cases.c.h" Py_DECREF(owner); #line 1137 "Python/bytecodes.c" if (err) goto pop_1_error; - #line 1580 "Python/generated_cases.c.h" + #line 1579 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } @@ -1586,11 +1585,11 @@ #line 1141 "Python/bytecodes.c" PyObject *name = GETITEM(frame->f_code->co_names, oparg); int err = PyDict_SetItem(GLOBALS(), name, v); - #line 1590 "Python/generated_cases.c.h" + #line 1589 "Python/generated_cases.c.h" Py_DECREF(v); #line 1144 "Python/bytecodes.c" if (err) goto pop_1_error; - #line 1594 "Python/generated_cases.c.h" + #line 1593 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } @@ -1608,74 +1607,179 @@ } goto error; } - #line 1612 "Python/generated_cases.c.h" + #line 1611 "Python/generated_cases.c.h" + DISPATCH(); + } + + TARGET(LOAD_LOCALS) { + PyObject *_tmp_1; + { + PyObject *locals; + #line 1162 "Python/bytecodes.c" + locals = LOCALS(); + if (locals == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + if (true) goto error; + } + Py_INCREF(locals); + #line 1627 "Python/generated_cases.c.h" + _tmp_1 = locals; + } + STACK_GROW(1); + stack_pointer[-1] = _tmp_1; DISPATCH(); } TARGET(LOAD_NAME) { - PyObject *v; - #line 1162 "Python/bytecodes.c" - PyObject *name = GETITEM(frame->f_code->co_names, oparg); - PyObject *locals = LOCALS(); - if (locals == NULL) { - _PyErr_Format(tstate, PyExc_SystemError, - "no locals when loading %R", name); - goto error; + PyObject *_tmp_1; + { + PyObject *locals; + #line 1162 "Python/bytecodes.c" + locals = LOCALS(); + if (locals == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, + "no locals found"); + if (true) goto error; + } + Py_INCREF(locals); + #line 1647 "Python/generated_cases.c.h" + _tmp_1 = locals; } - if (PyDict_CheckExact(locals)) { - v = PyDict_GetItemWithError(locals, name); - if (v != NULL) { - Py_INCREF(v); + { + PyObject *mod_or_class_dict = _tmp_1; + PyObject *v; + #line 1174 "Python/bytecodes.c" + PyObject *name = GETITEM(frame->f_code->co_names, oparg); + if (PyDict_CheckExact(mod_or_class_dict)) { + v = PyDict_GetItemWithError(mod_or_class_dict, name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { + Py_DECREF(mod_or_class_dict); + goto error; + } } - else if (_PyErr_Occurred(tstate)) { - goto error; + else { + v = PyObject_GetItem(mod_or_class_dict, name); + if (v == NULL) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + Py_DECREF(mod_or_class_dict); + goto error; + } + _PyErr_Clear(tstate); + } } - } - else { - v = PyObject_GetItem(locals, name); + Py_DECREF(mod_or_class_dict); if (v == NULL) { - if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { goto error; - _PyErr_Clear(tstate); + } + else { + if (PyDict_CheckExact(BUILTINS())) { + v = PyDict_GetItemWithError(BUILTINS(), name); + if (v == NULL) { + if (!_PyErr_Occurred(tstate)) { + format_exc_check_arg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + goto error; + } + Py_INCREF(v); + } + else { + v = PyObject_GetItem(BUILTINS(), name); + if (v == NULL) { + if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + format_exc_check_arg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + goto error; + } + } + } } + #line 1710 "Python/generated_cases.c.h" + _tmp_1 = v; } - if (v == NULL) { - v = PyDict_GetItemWithError(GLOBALS(), name); - if (v != NULL) { - Py_INCREF(v); - } - else if (_PyErr_Occurred(tstate)) { - goto error; + STACK_GROW(1); + stack_pointer[-1] = _tmp_1; + DISPATCH(); + } + + TARGET(LOAD_FROM_DICT_OR_GLOBALS) { + PyObject *_tmp_1 = stack_pointer[-1]; + { + PyObject *mod_or_class_dict = _tmp_1; + PyObject *v; + #line 1174 "Python/bytecodes.c" + PyObject *name = GETITEM(frame->f_code->co_names, oparg); + if (PyDict_CheckExact(mod_or_class_dict)) { + v = PyDict_GetItemWithError(mod_or_class_dict, name); + if (v != NULL) { + Py_INCREF(v); + } + else if (_PyErr_Occurred(tstate)) { + Py_DECREF(mod_or_class_dict); + goto error; + } } else { - if (PyDict_CheckExact(BUILTINS())) { - v = PyDict_GetItemWithError(BUILTINS(), name); - if (v == NULL) { - if (!_PyErr_Occurred(tstate)) { - format_exc_check_arg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - } + v = PyObject_GetItem(mod_or_class_dict, name); + if (v == NULL) { + if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + Py_DECREF(mod_or_class_dict); goto error; } + _PyErr_Clear(tstate); + } + } + Py_DECREF(mod_or_class_dict); + if (v == NULL) { + v = PyDict_GetItemWithError(GLOBALS(), name); + if (v != NULL) { Py_INCREF(v); } + else if (_PyErr_Occurred(tstate)) { + goto error; + } else { - v = PyObject_GetItem(BUILTINS(), name); - if (v == NULL) { - if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { - format_exc_check_arg( + if (PyDict_CheckExact(BUILTINS())) { + v = PyDict_GetItemWithError(BUILTINS(), name); + if (v == NULL) { + if (!_PyErr_Occurred(tstate)) { + format_exc_check_arg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); + } + goto error; + } + Py_INCREF(v); + } + else { + v = PyObject_GetItem(BUILTINS(), name); + if (v == NULL) { + if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + format_exc_check_arg( + tstate, PyExc_NameError, + NAME_ERROR_MSG, name); + } + goto error; } - goto error; } } } + #line 1780 "Python/generated_cases.c.h" + _tmp_1 = v; } - #line 1677 "Python/generated_cases.c.h" - STACK_GROW(1); - stack_pointer[-1] = v; + stack_pointer[-1] = _tmp_1; DISPATCH(); } @@ -1684,7 +1788,7 @@ static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size"); PyObject *null = NULL; PyObject *v; - #line 1229 "Python/bytecodes.c" + #line 1243 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -1736,7 +1840,7 @@ } } null = NULL; - #line 1740 "Python/generated_cases.c.h" + #line 1844 "Python/generated_cases.c.h" STACK_GROW(1); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = v; @@ -1750,7 +1854,7 @@ PyObject *res; uint16_t index = read_u16(&next_instr[1].cache); uint16_t version = read_u16(&next_instr[2].cache); - #line 1283 "Python/bytecodes.c" + #line 1297 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); PyDictObject *dict = (PyDictObject *)GLOBALS(); DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); @@ -1761,7 +1865,7 @@ Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); null = NULL; - #line 1765 "Python/generated_cases.c.h" + #line 1869 "Python/generated_cases.c.h" STACK_GROW(1); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -1776,7 +1880,7 @@ uint16_t index = read_u16(&next_instr[1].cache); uint16_t mod_version = read_u16(&next_instr[2].cache); uint16_t bltn_version = read_u16(&next_instr[3].cache); - #line 1296 "Python/bytecodes.c" + #line 1310 "Python/bytecodes.c" DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); PyDictObject *mdict = (PyDictObject *)GLOBALS(); @@ -1791,7 +1895,7 @@ Py_INCREF(res); STAT_INC(LOAD_GLOBAL, hit); null = NULL; - #line 1795 "Python/generated_cases.c.h" + #line 1899 "Python/generated_cases.c.h" STACK_GROW(1); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -1801,16 +1905,16 @@ } TARGET(DELETE_FAST) { - #line 1313 "Python/bytecodes.c" + #line 1327 "Python/bytecodes.c" PyObject *v = GETLOCAL(oparg); if (v == NULL) goto unbound_local_error; SETLOCAL(oparg, NULL); - #line 1809 "Python/generated_cases.c.h" + #line 1913 "Python/generated_cases.c.h" DISPATCH(); } TARGET(MAKE_CELL) { - #line 1319 "Python/bytecodes.c" + #line 1333 "Python/bytecodes.c" // "initial" is probably NULL but not if it's an arg (or set // via PyFrame_LocalsToFast() before MAKE_CELL has run). PyObject *initial = GETLOCAL(oparg); @@ -1819,12 +1923,12 @@ goto resume_with_error; } SETLOCAL(oparg, cell); - #line 1823 "Python/generated_cases.c.h" + #line 1927 "Python/generated_cases.c.h" DISPATCH(); } TARGET(DELETE_DEREF) { - #line 1330 "Python/bytecodes.c" + #line 1344 "Python/bytecodes.c" PyObject *cell = GETLOCAL(oparg); PyObject *oldobj = PyCell_GET(cell); // Can't use ERROR_IF here. @@ -1835,35 +1939,39 @@ } PyCell_SET(cell, NULL); Py_DECREF(oldobj); - #line 1839 "Python/generated_cases.c.h" + #line 1943 "Python/generated_cases.c.h" DISPATCH(); } - TARGET(LOAD_CLASSDEREF) { + TARGET(LOAD_FROM_DICT_OR_DEREF) { + PyObject *class_dict = stack_pointer[-1]; PyObject *value; - #line 1343 "Python/bytecodes.c" - PyObject *name, *locals = LOCALS(); - assert(locals); + #line 1357 "Python/bytecodes.c" + PyObject *name; + assert(class_dict); assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus); name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg); - if (PyDict_CheckExact(locals)) { - value = PyDict_GetItemWithError(locals, name); + if (PyDict_CheckExact(class_dict)) { + value = PyDict_GetItemWithError(class_dict, name); if (value != NULL) { Py_INCREF(value); } else if (_PyErr_Occurred(tstate)) { + Py_DECREF(class_dict); goto error; } } else { - value = PyObject_GetItem(locals, name); + value = PyObject_GetItem(class_dict, name); if (value == NULL) { if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { + Py_DECREF(class_dict); goto error; } _PyErr_Clear(tstate); } } + Py_DECREF(class_dict); if (!value) { PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); @@ -1873,15 +1981,14 @@ } Py_INCREF(value); } - #line 1877 "Python/generated_cases.c.h" - STACK_GROW(1); + #line 1985 "Python/generated_cases.c.h" stack_pointer[-1] = value; DISPATCH(); } TARGET(LOAD_DEREF) { PyObject *value; - #line 1377 "Python/bytecodes.c" + #line 1394 "Python/bytecodes.c" PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); if (value == NULL) { @@ -1889,7 +1996,7 @@ if (true) goto error; } Py_INCREF(value); - #line 1893 "Python/generated_cases.c.h" + #line 2000 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = value; DISPATCH(); @@ -1897,18 +2004,18 @@ TARGET(STORE_DEREF) { PyObject *v = stack_pointer[-1]; - #line 1387 "Python/bytecodes.c" + #line 1404 "Python/bytecodes.c" PyObject *cell = GETLOCAL(oparg); PyObject *oldobj = PyCell_GET(cell); PyCell_SET(cell, v); Py_XDECREF(oldobj); - #line 1906 "Python/generated_cases.c.h" + #line 2013 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } TARGET(COPY_FREE_VARS) { - #line 1394 "Python/bytecodes.c" + #line 1411 "Python/bytecodes.c" /* Copy closure variables to free variables */ PyCodeObject *co = frame->f_code; assert(PyFunction_Check(frame->f_funcobj)); @@ -1919,22 +2026,22 @@ PyObject *o = PyTuple_GET_ITEM(closure, i); frame->localsplus[offset + i] = Py_NewRef(o); } - #line 1923 "Python/generated_cases.c.h" + #line 2030 "Python/generated_cases.c.h" DISPATCH(); } TARGET(BUILD_STRING) { PyObject **pieces = (stack_pointer - oparg); PyObject *str; - #line 1407 "Python/bytecodes.c" + #line 1424 "Python/bytecodes.c" str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg); - #line 1932 "Python/generated_cases.c.h" + #line 2039 "Python/generated_cases.c.h" for (int _i = oparg; --_i >= 0;) { Py_DECREF(pieces[_i]); } - #line 1409 "Python/bytecodes.c" + #line 1426 "Python/bytecodes.c" if (str == NULL) { STACK_SHRINK(oparg); goto error; } - #line 1938 "Python/generated_cases.c.h" + #line 2045 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_GROW(1); stack_pointer[-1] = str; @@ -1944,10 +2051,10 @@ TARGET(BUILD_TUPLE) { PyObject **values = (stack_pointer - oparg); PyObject *tup; - #line 1413 "Python/bytecodes.c" + #line 1430 "Python/bytecodes.c" tup = _PyTuple_FromArraySteal(values, oparg); if (tup == NULL) { STACK_SHRINK(oparg); goto error; } - #line 1951 "Python/generated_cases.c.h" + #line 2058 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_GROW(1); stack_pointer[-1] = tup; @@ -1957,10 +2064,10 @@ TARGET(BUILD_LIST) { PyObject **values = (stack_pointer - oparg); PyObject *list; - #line 1418 "Python/bytecodes.c" + #line 1435 "Python/bytecodes.c" list = _PyList_FromArraySteal(values, oparg); if (list == NULL) { STACK_SHRINK(oparg); goto error; } - #line 1964 "Python/generated_cases.c.h" + #line 2071 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_GROW(1); stack_pointer[-1] = list; @@ -1970,7 +2077,7 @@ TARGET(LIST_EXTEND) { PyObject *iterable = stack_pointer[-1]; PyObject *list = stack_pointer[-(2 + (oparg-1))]; - #line 1423 "Python/bytecodes.c" + #line 1440 "Python/bytecodes.c" PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); if (none_val == NULL) { if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) && @@ -1981,13 +2088,13 @@ "Value after * must be an iterable, not %.200s", Py_TYPE(iterable)->tp_name); } - #line 1985 "Python/generated_cases.c.h" + #line 2092 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 1434 "Python/bytecodes.c" + #line 1451 "Python/bytecodes.c" if (true) goto pop_1_error; } - Py_DECREF(none_val); - #line 1991 "Python/generated_cases.c.h" + assert(Py_IsNone(none_val)); + #line 2098 "Python/generated_cases.c.h" Py_DECREF(iterable); STACK_SHRINK(1); DISPATCH(); @@ -1996,13 +2103,13 @@ TARGET(SET_UPDATE) { PyObject *iterable = stack_pointer[-1]; PyObject *set = stack_pointer[-(2 + (oparg-1))]; - #line 1441 "Python/bytecodes.c" + #line 1458 "Python/bytecodes.c" int err = _PySet_Update(set, iterable); - #line 2002 "Python/generated_cases.c.h" + #line 2109 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 1443 "Python/bytecodes.c" + #line 1460 "Python/bytecodes.c" if (err < 0) goto pop_1_error; - #line 2006 "Python/generated_cases.c.h" + #line 2113 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } @@ -2010,7 +2117,7 @@ TARGET(BUILD_SET) { PyObject **values = (stack_pointer - oparg); PyObject *set; - #line 1447 "Python/bytecodes.c" + #line 1464 "Python/bytecodes.c" set = PySet_New(NULL); if (set == NULL) goto error; @@ -2025,7 +2132,7 @@ Py_DECREF(set); if (true) { STACK_SHRINK(oparg); goto error; } } - #line 2029 "Python/generated_cases.c.h" + #line 2136 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_GROW(1); stack_pointer[-1] = set; @@ -2035,7 +2142,7 @@ TARGET(BUILD_MAP) { PyObject **values = (stack_pointer - oparg*2); PyObject *map; - #line 1464 "Python/bytecodes.c" + #line 1481 "Python/bytecodes.c" map = _PyDict_FromItems( values, 2, values+1, 2, @@ -2043,13 +2150,13 @@ if (map == NULL) goto error; - #line 2047 "Python/generated_cases.c.h" + #line 2154 "Python/generated_cases.c.h" for (int _i = oparg*2; --_i >= 0;) { Py_DECREF(values[_i]); } - #line 1472 "Python/bytecodes.c" + #line 1489 "Python/bytecodes.c" if (map == NULL) { STACK_SHRINK(oparg*2); goto error; } - #line 2053 "Python/generated_cases.c.h" + #line 2160 "Python/generated_cases.c.h" STACK_SHRINK(oparg*2); STACK_GROW(1); stack_pointer[-1] = map; @@ -2057,7 +2164,7 @@ } TARGET(SETUP_ANNOTATIONS) { - #line 1476 "Python/bytecodes.c" + #line 1493 "Python/bytecodes.c" int err; PyObject *ann_dict; if (LOCALS() == NULL) { @@ -2097,7 +2204,7 @@ Py_DECREF(ann_dict); } } - #line 2101 "Python/generated_cases.c.h" + #line 2208 "Python/generated_cases.c.h" DISPATCH(); } @@ -2105,7 +2212,7 @@ PyObject *keys = stack_pointer[-1]; PyObject **values = (stack_pointer - (1 + oparg)); PyObject *map; - #line 1518 "Python/bytecodes.c" + #line 1535 "Python/bytecodes.c" if (!PyTuple_CheckExact(keys) || PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { _PyErr_SetString(tstate, PyExc_SystemError, @@ -2115,14 +2222,14 @@ map = _PyDict_FromItems( &PyTuple_GET_ITEM(keys, 0), 1, values, 1, oparg); - #line 2119 "Python/generated_cases.c.h" + #line 2226 "Python/generated_cases.c.h" for (int _i = oparg; --_i >= 0;) { Py_DECREF(values[_i]); } Py_DECREF(keys); - #line 1528 "Python/bytecodes.c" + #line 1545 "Python/bytecodes.c" if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; } - #line 2126 "Python/generated_cases.c.h" + #line 2233 "Python/generated_cases.c.h" STACK_SHRINK(oparg); stack_pointer[-1] = map; DISPATCH(); @@ -2130,7 +2237,7 @@ TARGET(DICT_UPDATE) { PyObject *update = stack_pointer[-1]; - #line 1532 "Python/bytecodes.c" + #line 1549 "Python/bytecodes.c" PyObject *dict = PEEK(oparg + 1); // update is still on the stack if (PyDict_Update(dict, update) < 0) { if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { @@ -2138,12 +2245,12 @@ "'%.200s' object is not a mapping", Py_TYPE(update)->tp_name); } - #line 2142 "Python/generated_cases.c.h" + #line 2249 "Python/generated_cases.c.h" Py_DECREF(update); - #line 1540 "Python/bytecodes.c" + #line 1557 "Python/bytecodes.c" if (true) goto pop_1_error; } - #line 2147 "Python/generated_cases.c.h" + #line 2254 "Python/generated_cases.c.h" Py_DECREF(update); STACK_SHRINK(1); DISPATCH(); @@ -2151,17 +2258,17 @@ TARGET(DICT_MERGE) { PyObject *update = stack_pointer[-1]; - #line 1546 "Python/bytecodes.c" + #line 1563 "Python/bytecodes.c" PyObject *dict = PEEK(oparg + 1); // update is still on the stack if (_PyDict_MergeEx(dict, update, 2) < 0) { format_kwargs_error(tstate, PEEK(3 + oparg), update); - #line 2160 "Python/generated_cases.c.h" + #line 2267 "Python/generated_cases.c.h" Py_DECREF(update); - #line 1551 "Python/bytecodes.c" + #line 1568 "Python/bytecodes.c" if (true) goto pop_1_error; } - #line 2165 "Python/generated_cases.c.h" + #line 2272 "Python/generated_cases.c.h" Py_DECREF(update); STACK_SHRINK(1); PREDICT(CALL_FUNCTION_EX); @@ -2171,18 +2278,28 @@ TARGET(MAP_ADD) { PyObject *value = stack_pointer[-1]; PyObject *key = stack_pointer[-2]; - #line 1558 "Python/bytecodes.c" + #line 1575 "Python/bytecodes.c" PyObject *dict = PEEK(oparg + 2); // key, value are still on the stack assert(PyDict_CheckExact(dict)); /* dict[key] = value */ // Do not DECREF INPUTS because the function steals the references if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error; - #line 2181 "Python/generated_cases.c.h" + #line 2288 "Python/generated_cases.c.h" STACK_SHRINK(2); PREDICT(JUMP_BACKWARD); DISPATCH(); } + TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) { + #line 1584 "Python/bytecodes.c" + _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr; + // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we + // don't want to specialize instrumented instructions + INCREMENT_ADAPTIVE_COUNTER(cache->counter); + GO_TO_INSTRUCTION(LOAD_SUPER_ATTR); + #line 2301 "Python/generated_cases.c.h" + } + TARGET(LOAD_SUPER_ATTR) { PREDICTED(LOAD_SUPER_ATTR); static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size"); @@ -2191,7 +2308,7 @@ PyObject *global_super = stack_pointer[-3]; PyObject *res2 = NULL; PyObject *res; - #line 1573 "Python/bytecodes.c" + #line 1598 "Python/bytecodes.c" PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2); int load_method = oparg & 1; #if ENABLE_SPECIALIZATION @@ -2205,20 +2322,44 @@ DECREMENT_ADAPTIVE_COUNTER(cache->counter); #endif /* ENABLE_SPECIALIZATION */ + if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { + PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_CALL, + frame, next_instr-1, global_super, arg); + if (err) goto pop_3_error; + } + // we make no attempt to optimize here; specializations should // handle any case whose performance we care about PyObject *stack[] = {class, self}; PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL); - #line 2213 "Python/generated_cases.c.h" + if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { + PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; + if (super == NULL) { + _Py_call_instrumentation_exc2( + tstate, PY_MONITORING_EVENT_C_RAISE, + frame, next_instr-1, global_super, arg); + } + else { + int err = _Py_call_instrumentation_2args( + tstate, PY_MONITORING_EVENT_C_RETURN, + frame, next_instr-1, global_super, arg); + if (err < 0) { + Py_CLEAR(super); + } + } + } + #line 2354 "Python/generated_cases.c.h" Py_DECREF(global_super); Py_DECREF(class); Py_DECREF(self); - #line 1591 "Python/bytecodes.c" + #line 1640 "Python/bytecodes.c" if (super == NULL) goto pop_3_error; res = PyObject_GetAttr(super, name); Py_DECREF(super); if (res == NULL) goto pop_3_error; - #line 2222 "Python/generated_cases.c.h" + #line 2363 "Python/generated_cases.c.h" STACK_SHRINK(2); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -2233,20 +2374,20 @@ PyObject *global_super = stack_pointer[-3]; PyObject *res2 = NULL; PyObject *res; - #line 1598 "Python/bytecodes.c" + #line 1647 "Python/bytecodes.c" assert(!(oparg & 1)); DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2); res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); - #line 2244 "Python/generated_cases.c.h" + #line 2385 "Python/generated_cases.c.h" Py_DECREF(global_super); Py_DECREF(class); Py_DECREF(self); - #line 1605 "Python/bytecodes.c" + #line 1654 "Python/bytecodes.c" if (res == NULL) goto pop_3_error; - #line 2250 "Python/generated_cases.c.h" + #line 2391 "Python/generated_cases.c.h" STACK_SHRINK(2); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -2261,7 +2402,7 @@ PyObject *global_super = stack_pointer[-3]; PyObject *res2; PyObject *res; - #line 1609 "Python/bytecodes.c" + #line 1658 "Python/bytecodes.c" assert(oparg & 1); DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR); DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); @@ -2282,7 +2423,7 @@ res = res2; res2 = NULL; } - #line 2286 "Python/generated_cases.c.h" + #line 2427 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; stack_pointer[-2] = res2; @@ -2296,7 +2437,7 @@ PyObject *owner = stack_pointer[-1]; PyObject *res2 = NULL; PyObject *res; - #line 1646 "Python/bytecodes.c" + #line 1695 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyAttrCache *cache = (_PyAttrCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -2330,9 +2471,9 @@ NULL | meth | arg1 | ... | argN */ - #line 2334 "Python/generated_cases.c.h" + #line 2475 "Python/generated_cases.c.h" Py_DECREF(owner); - #line 1680 "Python/bytecodes.c" + #line 1729 "Python/bytecodes.c" if (meth == NULL) goto pop_1_error; res2 = NULL; res = meth; @@ -2341,12 +2482,12 @@ else { /* Classic, pushes one value. */ res = PyObject_GetAttr(owner, name); - #line 2345 "Python/generated_cases.c.h" + #line 2486 "Python/generated_cases.c.h" Py_DECREF(owner); - #line 1689 "Python/bytecodes.c" + #line 1738 "Python/bytecodes.c" if (res == NULL) goto pop_1_error; } - #line 2350 "Python/generated_cases.c.h" + #line 2491 "Python/generated_cases.c.h" STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } @@ -2360,7 +2501,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1694 "Python/bytecodes.c" + #line 1743 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); @@ -2373,7 +2514,7 @@ STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); res2 = NULL; - #line 2377 "Python/generated_cases.c.h" + #line 2518 "Python/generated_cases.c.h" Py_DECREF(owner); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -2388,7 +2529,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1710 "Python/bytecodes.c" + #line 1759 "Python/bytecodes.c" DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict != NULL); @@ -2401,7 +2542,7 @@ STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); res2 = NULL; - #line 2405 "Python/generated_cases.c.h" + #line 2546 "Python/generated_cases.c.h" Py_DECREF(owner); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -2416,7 +2557,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1726 "Python/bytecodes.c" + #line 1775 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); @@ -2443,7 +2584,7 @@ STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); res2 = NULL; - #line 2447 "Python/generated_cases.c.h" + #line 2588 "Python/generated_cases.c.h" Py_DECREF(owner); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -2458,7 +2599,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1756 "Python/bytecodes.c" + #line 1805 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); @@ -2468,7 +2609,7 @@ STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); res2 = NULL; - #line 2472 "Python/generated_cases.c.h" + #line 2613 "Python/generated_cases.c.h" Py_DECREF(owner); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -2483,7 +2624,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 1769 "Python/bytecodes.c" + #line 1818 "Python/bytecodes.c" DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, @@ -2495,7 +2636,7 @@ res = descr; assert(res != NULL); Py_INCREF(res); - #line 2499 "Python/generated_cases.c.h" + #line 2640 "Python/generated_cases.c.h" Py_DECREF(cls); STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; @@ -2509,7 +2650,7 @@ uint32_t type_version = read_u32(&next_instr[1].cache); uint32_t func_version = read_u32(&next_instr[3].cache); PyObject *fget = read_obj(&next_instr[5].cache); - #line 1784 "Python/bytecodes.c" + #line 1833 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); PyTypeObject *cls = Py_TYPE(owner); @@ -2533,7 +2674,7 @@ JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); frame->return_offset = 0; DISPATCH_INLINED(new_frame); - #line 2537 "Python/generated_cases.c.h" + #line 2678 "Python/generated_cases.c.h" } TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { @@ -2541,7 +2682,7 @@ uint32_t type_version = read_u32(&next_instr[1].cache); uint32_t func_version = read_u32(&next_instr[3].cache); PyObject *getattribute = read_obj(&next_instr[5].cache); - #line 1810 "Python/bytecodes.c" + #line 1859 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); PyTypeObject *cls = Py_TYPE(owner); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); @@ -2567,7 +2708,7 @@ JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); frame->return_offset = 0; DISPATCH_INLINED(new_frame); - #line 2571 "Python/generated_cases.c.h" + #line 2712 "Python/generated_cases.c.h" } TARGET(STORE_ATTR_INSTANCE_VALUE) { @@ -2575,7 +2716,7 @@ PyObject *value = stack_pointer[-2]; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1838 "Python/bytecodes.c" + #line 1887 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); @@ -2593,7 +2734,7 @@ Py_DECREF(old_value); } Py_DECREF(owner); - #line 2597 "Python/generated_cases.c.h" + #line 2738 "Python/generated_cases.c.h" STACK_SHRINK(2); next_instr += 4; DISPATCH(); @@ -2604,7 +2745,7 @@ PyObject *value = stack_pointer[-2]; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t hint = read_u16(&next_instr[3].cache); - #line 1858 "Python/bytecodes.c" + #line 1907 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); @@ -2643,7 +2784,7 @@ /* PEP 509 */ dict->ma_version_tag = new_version; Py_DECREF(owner); - #line 2647 "Python/generated_cases.c.h" + #line 2788 "Python/generated_cases.c.h" STACK_SHRINK(2); next_instr += 4; DISPATCH(); @@ -2654,7 +2795,7 @@ PyObject *value = stack_pointer[-2]; uint32_t type_version = read_u32(&next_instr[1].cache); uint16_t index = read_u16(&next_instr[3].cache); - #line 1899 "Python/bytecodes.c" + #line 1948 "Python/bytecodes.c" PyTypeObject *tp = Py_TYPE(owner); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); @@ -2664,7 +2805,7 @@ *(PyObject **)addr = value; Py_XDECREF(old_value); Py_DECREF(owner); - #line 2668 "Python/generated_cases.c.h" + #line 2809 "Python/generated_cases.c.h" STACK_SHRINK(2); next_instr += 4; DISPATCH(); @@ -2676,7 +2817,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 1918 "Python/bytecodes.c" + #line 1967 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -2689,12 +2830,12 @@ #endif /* ENABLE_SPECIALIZATION */ assert((oparg >> 4) <= Py_GE); res = PyObject_RichCompare(left, right, oparg>>4); - #line 2693 "Python/generated_cases.c.h" + #line 2834 "Python/generated_cases.c.h" Py_DECREF(left); Py_DECREF(right); - #line 1931 "Python/bytecodes.c" + #line 1980 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; - #line 2698 "Python/generated_cases.c.h" + #line 2839 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -2705,7 +2846,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 1935 "Python/bytecodes.c" + #line 1984 "Python/bytecodes.c" DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); STAT_INC(COMPARE_OP, hit); @@ -2716,8 +2857,7 @@ _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); res = (sign_ish & oparg) ? Py_True : Py_False; - Py_INCREF(res); - #line 2721 "Python/generated_cases.c.h" + #line 2861 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -2728,7 +2868,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 1950 "Python/bytecodes.c" + #line 1998 "Python/bytecodes.c" DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP); @@ -2743,8 +2883,7 @@ _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); res = (sign_ish & oparg) ? Py_True : Py_False; - Py_INCREF(res); - #line 2748 "Python/generated_cases.c.h" + #line 2887 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -2755,7 +2894,7 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *res; - #line 1969 "Python/bytecodes.c" + #line 2016 "Python/bytecodes.c" DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); STAT_INC(COMPARE_OP, hit); @@ -2767,8 +2906,7 @@ assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False; - Py_INCREF(res); - #line 2772 "Python/generated_cases.c.h" + #line 2910 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -2779,14 +2917,14 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *b; - #line 1984 "Python/bytecodes.c" + #line 2030 "Python/bytecodes.c" int res = Py_Is(left, right) ^ oparg; - #line 2785 "Python/generated_cases.c.h" + #line 2923 "Python/generated_cases.c.h" Py_DECREF(left); Py_DECREF(right); - #line 1986 "Python/bytecodes.c" - b = Py_NewRef(res ? Py_True : Py_False); - #line 2790 "Python/generated_cases.c.h" + #line 2032 "Python/bytecodes.c" + b = res ? Py_True : Py_False; + #line 2928 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = b; DISPATCH(); @@ -2796,15 +2934,15 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *b; - #line 1990 "Python/bytecodes.c" + #line 2036 "Python/bytecodes.c" int res = PySequence_Contains(right, left); - #line 2802 "Python/generated_cases.c.h" + #line 2940 "Python/generated_cases.c.h" Py_DECREF(left); Py_DECREF(right); - #line 1992 "Python/bytecodes.c" + #line 2038 "Python/bytecodes.c" if (res < 0) goto pop_2_error; - b = Py_NewRef((res^oparg) ? Py_True : Py_False); - #line 2808 "Python/generated_cases.c.h" + b = (res ^ oparg) ? Py_True : Py_False; + #line 2946 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = b; DISPATCH(); @@ -2815,12 +2953,12 @@ PyObject *exc_value = stack_pointer[-2]; PyObject *rest; PyObject *match; - #line 1997 "Python/bytecodes.c" + #line 2043 "Python/bytecodes.c" if (check_except_star_type_valid(tstate, match_type) < 0) { - #line 2821 "Python/generated_cases.c.h" + #line 2959 "Python/generated_cases.c.h" Py_DECREF(exc_value); Py_DECREF(match_type); - #line 1999 "Python/bytecodes.c" + #line 2045 "Python/bytecodes.c" if (true) goto pop_2_error; } @@ -2828,10 +2966,10 @@ rest = NULL; int res = exception_group_match(exc_value, match_type, &match, &rest); - #line 2832 "Python/generated_cases.c.h" + #line 2970 "Python/generated_cases.c.h" Py_DECREF(exc_value); Py_DECREF(match_type); - #line 2007 "Python/bytecodes.c" + #line 2053 "Python/bytecodes.c" if (res < 0) goto pop_2_error; assert((match == NULL) == (rest == NULL)); @@ -2840,7 +2978,7 @@ if (!Py_IsNone(match)) { PyErr_SetHandledException(match); } - #line 2844 "Python/generated_cases.c.h" + #line 2982 "Python/generated_cases.c.h" stack_pointer[-1] = match; stack_pointer[-2] = rest; DISPATCH(); @@ -2850,21 +2988,21 @@ PyObject *right = stack_pointer[-1]; PyObject *left = stack_pointer[-2]; PyObject *b; - #line 2018 "Python/bytecodes.c" + #line 2064 "Python/bytecodes.c" assert(PyExceptionInstance_Check(left)); if (check_except_type_valid(tstate, right) < 0) { - #line 2857 "Python/generated_cases.c.h" + #line 2995 "Python/generated_cases.c.h" Py_DECREF(right); - #line 2021 "Python/bytecodes.c" + #line 2067 "Python/bytecodes.c" if (true) goto pop_1_error; } int res = PyErr_GivenExceptionMatches(left, right); - #line 2864 "Python/generated_cases.c.h" + #line 3002 "Python/generated_cases.c.h" Py_DECREF(right); - #line 2026 "Python/bytecodes.c" - b = Py_NewRef(res ? Py_True : Py_False); - #line 2868 "Python/generated_cases.c.h" + #line 2072 "Python/bytecodes.c" + b = res ? Py_True : Py_False; + #line 3006 "Python/generated_cases.c.h" stack_pointer[-1] = b; DISPATCH(); } @@ -2873,15 +3011,15 @@ PyObject *fromlist = stack_pointer[-1]; PyObject *level = stack_pointer[-2]; PyObject *res; - #line 2030 "Python/bytecodes.c" + #line 2076 "Python/bytecodes.c" PyObject *name = GETITEM(frame->f_code->co_names, oparg); res = import_name(tstate, frame, name, fromlist, level); - #line 2880 "Python/generated_cases.c.h" + #line 3018 "Python/generated_cases.c.h" Py_DECREF(level); Py_DECREF(fromlist); - #line 2033 "Python/bytecodes.c" + #line 2079 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; - #line 2885 "Python/generated_cases.c.h" + #line 3023 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; DISPATCH(); @@ -2890,29 +3028,29 @@ TARGET(IMPORT_FROM) { PyObject *from = stack_pointer[-1]; PyObject *res; - #line 2037 "Python/bytecodes.c" + #line 2083 "Python/bytecodes.c" PyObject *name = GETITEM(frame->f_code->co_names, oparg); res = import_from(tstate, from, name); if (res == NULL) goto error; - #line 2898 "Python/generated_cases.c.h" + #line 3036 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = res; DISPATCH(); } TARGET(JUMP_FORWARD) { - #line 2043 "Python/bytecodes.c" + #line 2089 "Python/bytecodes.c" JUMPBY(oparg); - #line 2907 "Python/generated_cases.c.h" + #line 3045 "Python/generated_cases.c.h" DISPATCH(); } TARGET(JUMP_BACKWARD) { PREDICTED(JUMP_BACKWARD); - #line 2047 "Python/bytecodes.c" + #line 2093 "Python/bytecodes.c" assert(oparg < INSTR_OFFSET()); JUMPBY(-oparg); - #line 2916 "Python/generated_cases.c.h" + #line 3054 "Python/generated_cases.c.h" CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -2920,19 +3058,15 @@ TARGET(POP_JUMP_IF_FALSE) { PREDICTED(POP_JUMP_IF_FALSE); PyObject *cond = stack_pointer[-1]; - #line 2053 "Python/bytecodes.c" - if (Py_IsTrue(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - } - else if (Py_IsFalse(cond)) { - _Py_DECREF_NO_DEALLOC(cond); + #line 2099 "Python/bytecodes.c" + if (Py_IsFalse(cond)) { JUMPBY(oparg); } - else { + else if (!Py_IsTrue(cond)) { int err = PyObject_IsTrue(cond); - #line 2934 "Python/generated_cases.c.h" + #line 3068 "Python/generated_cases.c.h" Py_DECREF(cond); - #line 2063 "Python/bytecodes.c" + #line 2105 "Python/bytecodes.c" if (err == 0) { JUMPBY(oparg); } @@ -2940,26 +3074,22 @@ if (err < 0) goto pop_1_error; } } - #line 2944 "Python/generated_cases.c.h" + #line 3078 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } TARGET(POP_JUMP_IF_TRUE) { PyObject *cond = stack_pointer[-1]; - #line 2073 "Python/bytecodes.c" - if (Py_IsFalse(cond)) { - _Py_DECREF_NO_DEALLOC(cond); - } - else if (Py_IsTrue(cond)) { - _Py_DECREF_NO_DEALLOC(cond); + #line 2115 "Python/bytecodes.c" + if (Py_IsTrue(cond)) { JUMPBY(oparg); } - else { + else if (!Py_IsFalse(cond)) { int err = PyObject_IsTrue(cond); - #line 2961 "Python/generated_cases.c.h" + #line 3091 "Python/generated_cases.c.h" Py_DECREF(cond); - #line 2083 "Python/bytecodes.c" + #line 2121 "Python/bytecodes.c" if (err > 0) { JUMPBY(oparg); } @@ -2967,67 +3097,63 @@ if (err < 0) goto pop_1_error; } } - #line 2971 "Python/generated_cases.c.h" + #line 3101 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } TARGET(POP_JUMP_IF_NOT_NONE) { PyObject *value = stack_pointer[-1]; - #line 2093 "Python/bytecodes.c" + #line 2131 "Python/bytecodes.c" if (!Py_IsNone(value)) { - #line 2980 "Python/generated_cases.c.h" + #line 3110 "Python/generated_cases.c.h" Py_DECREF(value); - #line 2095 "Python/bytecodes.c" + #line 2133 "Python/bytecodes.c" JUMPBY(oparg); } - else { - _Py_DECREF_NO_DEALLOC(value); - } - #line 2988 "Python/generated_cases.c.h" + #line 3115 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } TARGET(POP_JUMP_IF_NONE) { PyObject *value = stack_pointer[-1]; - #line 2103 "Python/bytecodes.c" + #line 2138 "Python/bytecodes.c" if (Py_IsNone(value)) { - _Py_DECREF_NO_DEALLOC(value); JUMPBY(oparg); } else { - #line 3001 "Python/generated_cases.c.h" + #line 3127 "Python/generated_cases.c.h" Py_DECREF(value); - #line 2109 "Python/bytecodes.c" + #line 2143 "Python/bytecodes.c" } - #line 3005 "Python/generated_cases.c.h" + #line 3131 "Python/generated_cases.c.h" STACK_SHRINK(1); DISPATCH(); } TARGET(JUMP_BACKWARD_NO_INTERRUPT) { - #line 2113 "Python/bytecodes.c" + #line 2147 "Python/bytecodes.c" /* This bytecode is used in the `yield from` or `await` loop. * If there is an interrupt, we want it handled in the innermost * generator or coroutine, so we deliberately do not check it here. * (see bpo-30039). */ JUMPBY(-oparg); - #line 3018 "Python/generated_cases.c.h" + #line 3144 "Python/generated_cases.c.h" DISPATCH(); } TARGET(GET_LEN) { PyObject *obj = stack_pointer[-1]; PyObject *len_o; - #line 2122 "Python/bytecodes.c" + #line 2156 "Python/bytecodes.c" // PUSH(len(TOS)) Py_ssize_t len_i = PyObject_Length(obj); if (len_i < 0) goto error; len_o = PyLong_FromSsize_t(len_i); if (len_o == NULL) goto error; - #line 3031 "Python/generated_cases.c.h" + #line 3157 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = len_o; DISPATCH(); @@ -3038,24 +3164,24 @@ PyObject *type = stack_pointer[-2]; PyObject *subject = stack_pointer[-3]; PyObject *attrs; - #line 2130 "Python/bytecodes.c" + #line 2164 "Python/bytecodes.c" // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. assert(PyTuple_CheckExact(names)); attrs = match_class(tstate, subject, type, oparg, names); - #line 3047 "Python/generated_cases.c.h" + #line 3173 "Python/generated_cases.c.h" Py_DECREF(subject); Py_DECREF(type); Py_DECREF(names); - #line 2135 "Python/bytecodes.c" + #line 2169 "Python/bytecodes.c" if (attrs) { assert(PyTuple_CheckExact(attrs)); // Success! } else { if (_PyErr_Occurred(tstate)) goto pop_3_error; - attrs = Py_NewRef(Py_None); // Failure! + attrs = Py_None; // Failure! } - #line 3059 "Python/generated_cases.c.h" + #line 3185 "Python/generated_cases.c.h" STACK_SHRINK(2); stack_pointer[-1] = attrs; DISPATCH(); @@ -3064,10 +3190,10 @@ TARGET(MATCH_MAPPING) { PyObject *subject = stack_pointer[-1]; PyObject *res; - #line 2145 "Python/bytecodes.c" + #line 2179 "Python/bytecodes.c" int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING; - res = Py_NewRef(match ? Py_True : Py_False); - #line 3071 "Python/generated_cases.c.h" + res = match ? Py_True : Py_False; + #line 3197 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = res; PREDICT(POP_JUMP_IF_FALSE); @@ -3077,10 +3203,10 @@ TARGET(MATCH_SEQUENCE) { PyObject *subject = stack_pointer[-1]; PyObject *res; - #line 2151 "Python/bytecodes.c" + #line 2185 "Python/bytecodes.c" int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE; - res = Py_NewRef(match ? Py_True : Py_False); - #line 3084 "Python/generated_cases.c.h" + res = match ? Py_True : Py_False; + #line 3210 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = res; PREDICT(POP_JUMP_IF_FALSE); @@ -3091,11 +3217,11 @@ PyObject *keys = stack_pointer[-1]; PyObject *subject = stack_pointer[-2]; PyObject *values_or_none; - #line 2157 "Python/bytecodes.c" + #line 2191 "Python/bytecodes.c" // On successful match, PUSH(values). Otherwise, PUSH(None). values_or_none = match_keys(tstate, subject, keys); if (values_or_none == NULL) goto error; - #line 3099 "Python/generated_cases.c.h" + #line 3225 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = values_or_none; DISPATCH(); @@ -3104,14 +3230,14 @@ TARGET(GET_ITER) { PyObject *iterable = stack_pointer[-1]; PyObject *iter; - #line 2163 "Python/bytecodes.c" + #line 2197 "Python/bytecodes.c" /* before: [obj]; after [getiter(obj)] */ iter = PyObject_GetIter(iterable); - #line 3111 "Python/generated_cases.c.h" + #line 3237 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 2166 "Python/bytecodes.c" + #line 2200 "Python/bytecodes.c" if (iter == NULL) goto pop_1_error; - #line 3115 "Python/generated_cases.c.h" + #line 3241 "Python/generated_cases.c.h" stack_pointer[-1] = iter; DISPATCH(); } @@ -3119,7 +3245,7 @@ TARGET(GET_YIELD_FROM_ITER) { PyObject *iterable = stack_pointer[-1]; PyObject *iter; - #line 2170 "Python/bytecodes.c" + #line 2204 "Python/bytecodes.c" /* before: [obj]; after [getiter(obj)] */ if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ @@ -3142,11 +3268,11 @@ if (iter == NULL) { goto error; } - #line 3146 "Python/generated_cases.c.h" + #line 3272 "Python/generated_cases.c.h" Py_DECREF(iterable); - #line 2193 "Python/bytecodes.c" + #line 2227 "Python/bytecodes.c" } - #line 3150 "Python/generated_cases.c.h" + #line 3276 "Python/generated_cases.c.h" stack_pointer[-1] = iter; PREDICT(LOAD_CONST); DISPATCH(); @@ -3157,7 +3283,7 @@ static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2212 "Python/bytecodes.c" + #line 2246 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyForIterCache *cache = (_PyForIterCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -3188,7 +3314,7 @@ DISPATCH(); } // Common case: no jump, leave it to the code generator - #line 3192 "Python/generated_cases.c.h" + #line 3318 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = next; next_instr += 1; @@ -3196,7 +3322,7 @@ } TARGET(INSTRUMENTED_FOR_ITER) { - #line 2245 "Python/bytecodes.c" + #line 2279 "Python/bytecodes.c" _Py_CODEUNIT *here = next_instr-1; _Py_CODEUNIT *target; PyObject *iter = TOP(); @@ -3222,14 +3348,14 @@ target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1; } INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH); - #line 3226 "Python/generated_cases.c.h" + #line 3352 "Python/generated_cases.c.h" DISPATCH(); } TARGET(FOR_ITER_LIST) { PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2273 "Python/bytecodes.c" + #line 2307 "Python/bytecodes.c" DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER); _PyListIterObject *it = (_PyListIterObject *)iter; STAT_INC(FOR_ITER, hit); @@ -3249,7 +3375,7 @@ DISPATCH(); end_for_iter_list: // Common case: no jump, leave it to the code generator - #line 3253 "Python/generated_cases.c.h" + #line 3379 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = next; next_instr += 1; @@ -3259,7 +3385,7 @@ TARGET(FOR_ITER_TUPLE) { PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2295 "Python/bytecodes.c" + #line 2329 "Python/bytecodes.c" _PyTupleIterObject *it = (_PyTupleIterObject *)iter; DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); @@ -3279,7 +3405,7 @@ DISPATCH(); end_for_iter_tuple: // Common case: no jump, leave it to the code generator - #line 3283 "Python/generated_cases.c.h" + #line 3409 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = next; next_instr += 1; @@ -3289,7 +3415,7 @@ TARGET(FOR_ITER_RANGE) { PyObject *iter = stack_pointer[-1]; PyObject *next; - #line 2317 "Python/bytecodes.c" + #line 2351 "Python/bytecodes.c" _PyRangeIterObject *r = (_PyRangeIterObject *)iter; DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); STAT_INC(FOR_ITER, hit); @@ -3307,7 +3433,7 @@ if (next == NULL) { goto error; } - #line 3311 "Python/generated_cases.c.h" + #line 3437 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = next; next_instr += 1; @@ -3316,7 +3442,7 @@ TARGET(FOR_ITER_GEN) { PyObject *iter = stack_pointer[-1]; - #line 2337 "Python/bytecodes.c" + #line 2371 "Python/bytecodes.c" DEOPT_IF(tstate->interp->eval_frame, FOR_ITER); PyGenObject *gen = (PyGenObject *)iter; DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); @@ -3324,7 +3450,7 @@ STAT_INC(FOR_ITER, hit); _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; frame->return_offset = oparg; - _PyFrame_StackPush(gen_frame, Py_NewRef(Py_None)); + _PyFrame_StackPush(gen_frame, Py_None); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; @@ -3332,14 +3458,14 @@ assert(next_instr[oparg].op.code == END_FOR || next_instr[oparg].op.code == INSTRUMENTED_END_FOR); DISPATCH_INLINED(gen_frame); - #line 3336 "Python/generated_cases.c.h" + #line 3462 "Python/generated_cases.c.h" } TARGET(BEFORE_ASYNC_WITH) { PyObject *mgr = stack_pointer[-1]; PyObject *exit; PyObject *res; - #line 2355 "Python/bytecodes.c" + #line 2389 "Python/bytecodes.c" PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__)); if (enter == NULL) { if (!_PyErr_Occurred(tstate)) { @@ -3362,16 +3488,16 @@ Py_DECREF(enter); goto error; } - #line 3366 "Python/generated_cases.c.h" + #line 3492 "Python/generated_cases.c.h" Py_DECREF(mgr); - #line 2378 "Python/bytecodes.c" + #line 2412 "Python/bytecodes.c" res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); if (res == NULL) { Py_DECREF(exit); if (true) goto pop_1_error; } - #line 3375 "Python/generated_cases.c.h" + #line 3501 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = res; stack_pointer[-2] = exit; @@ -3383,7 +3509,7 @@ PyObject *mgr = stack_pointer[-1]; PyObject *exit; PyObject *res; - #line 2388 "Python/bytecodes.c" + #line 2422 "Python/bytecodes.c" /* pop the context manager, push its __exit__ and the * value returned from calling its __enter__ */ @@ -3409,16 +3535,16 @@ Py_DECREF(enter); goto error; } - #line 3413 "Python/generated_cases.c.h" + #line 3539 "Python/generated_cases.c.h" Py_DECREF(mgr); - #line 2414 "Python/bytecodes.c" + #line 2448 "Python/bytecodes.c" res = _PyObject_CallNoArgs(enter); Py_DECREF(enter); if (res == NULL) { Py_DECREF(exit); if (true) goto pop_1_error; } - #line 3422 "Python/generated_cases.c.h" + #line 3548 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = res; stack_pointer[-2] = exit; @@ -3430,7 +3556,7 @@ PyObject *lasti = stack_pointer[-3]; PyObject *exit_func = stack_pointer[-4]; PyObject *res; - #line 2423 "Python/bytecodes.c" + #line 2457 "Python/bytecodes.c" /* At the top of the stack are 4 values: - val: TOP = exc_info() - unused: SECOND = previous exception @@ -3451,7 +3577,7 @@ res = PyObject_Vectorcall(exit_func, stack + 1, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); if (res == NULL) goto error; - #line 3455 "Python/generated_cases.c.h" + #line 3581 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = res; DISPATCH(); @@ -3460,17 +3586,17 @@ TARGET(PUSH_EXC_INFO) { PyObject *new_exc = stack_pointer[-1]; PyObject *prev_exc; - #line 2446 "Python/bytecodes.c" + #line 2480 "Python/bytecodes.c" _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { prev_exc = exc_info->exc_value; } else { - prev_exc = Py_NewRef(Py_None); + prev_exc = Py_None; } assert(PyExceptionInstance_Check(new_exc)); exc_info->exc_value = Py_NewRef(new_exc); - #line 3474 "Python/generated_cases.c.h" + #line 3600 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = new_exc; stack_pointer[-2] = prev_exc; @@ -3484,7 +3610,7 @@ uint32_t type_version = read_u32(&next_instr[1].cache); uint32_t keys_version = read_u32(&next_instr[3].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2458 "Python/bytecodes.c" + #line 2492 "Python/bytecodes.c" /* Cached method object */ PyTypeObject *self_cls = Py_TYPE(self); assert(type_version != 0); @@ -3501,7 +3627,7 @@ assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); res = self; assert(oparg & 1); - #line 3505 "Python/generated_cases.c.h" + #line 3631 "Python/generated_cases.c.h" STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } @@ -3515,7 +3641,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2477 "Python/bytecodes.c" + #line 2511 "Python/bytecodes.c" PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); @@ -3525,7 +3651,7 @@ res2 = Py_NewRef(descr); res = self; assert(oparg & 1); - #line 3529 "Python/generated_cases.c.h" + #line 3655 "Python/generated_cases.c.h" STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } @@ -3539,7 +3665,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2489 "Python/bytecodes.c" + #line 2523 "Python/bytecodes.c" PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; @@ -3553,7 +3679,7 @@ res2 = Py_NewRef(descr); res = self; assert(oparg & 1); - #line 3557 "Python/generated_cases.c.h" + #line 3683 "Python/generated_cases.c.h" STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } @@ -3562,16 +3688,16 @@ } TARGET(KW_NAMES) { - #line 2505 "Python/bytecodes.c" + #line 2539 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg < PyTuple_GET_SIZE(frame->f_code->co_consts)); kwnames = GETITEM(frame->f_code->co_consts, oparg); - #line 3570 "Python/generated_cases.c.h" + #line 3696 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_CALL) { - #line 2511 "Python/bytecodes.c" + #line 2545 "Python/bytecodes.c" int is_meth = PEEK(oparg+2) != NULL; int total_args = oparg + is_meth; PyObject *function = PEEK(total_args + 1); @@ -3584,7 +3710,7 @@ _PyCallCache *cache = (_PyCallCache *)next_instr; INCREMENT_ADAPTIVE_COUNTER(cache->counter); GO_TO_INSTRUCTION(CALL); - #line 3588 "Python/generated_cases.c.h" + #line 3714 "Python/generated_cases.c.h" } TARGET(CALL) { @@ -3594,7 +3720,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2556 "Python/bytecodes.c" + #line 2590 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -3676,7 +3802,7 @@ Py_DECREF(args[i]); } if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3680 "Python/generated_cases.c.h" + #line 3806 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3688,7 +3814,7 @@ TARGET(CALL_BOUND_METHOD_EXACT_ARGS) { PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; - #line 2644 "Python/bytecodes.c" + #line 2678 "Python/bytecodes.c" DEOPT_IF(method != NULL, CALL); DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL); STAT_INC(CALL, hit); @@ -3698,7 +3824,7 @@ PEEK(oparg + 2) = Py_NewRef(meth); // method Py_DECREF(callable); GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS); - #line 3702 "Python/generated_cases.c.h" + #line 3828 "Python/generated_cases.c.h" } TARGET(CALL_PY_EXACT_ARGS) { @@ -3707,7 +3833,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; uint32_t func_version = read_u32(&next_instr[1].cache); - #line 2656 "Python/bytecodes.c" + #line 2690 "Python/bytecodes.c" assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); int is_meth = method != NULL; @@ -3733,7 +3859,7 @@ JUMPBY(INLINE_CACHE_ENTRIES_CALL); frame->return_offset = 0; DISPATCH_INLINED(new_frame); - #line 3737 "Python/generated_cases.c.h" + #line 3863 "Python/generated_cases.c.h" } TARGET(CALL_PY_WITH_DEFAULTS) { @@ -3741,7 +3867,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; uint32_t func_version = read_u32(&next_instr[1].cache); - #line 2684 "Python/bytecodes.c" + #line 2718 "Python/bytecodes.c" assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); int is_meth = method != NULL; @@ -3777,7 +3903,7 @@ JUMPBY(INLINE_CACHE_ENTRIES_CALL); frame->return_offset = 0; DISPATCH_INLINED(new_frame); - #line 3781 "Python/generated_cases.c.h" + #line 3907 "Python/generated_cases.c.h" } TARGET(CALL_NO_KW_TYPE_1) { @@ -3785,7 +3911,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2722 "Python/bytecodes.c" + #line 2756 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -3795,7 +3921,7 @@ res = Py_NewRef(Py_TYPE(obj)); Py_DECREF(obj); Py_DECREF(&PyType_Type); // I.e., callable - #line 3799 "Python/generated_cases.c.h" + #line 3925 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3808,7 +3934,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2734 "Python/bytecodes.c" + #line 2768 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -3819,7 +3945,7 @@ Py_DECREF(arg); Py_DECREF(&PyUnicode_Type); // I.e., callable if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3823 "Python/generated_cases.c.h" + #line 3949 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3833,7 +3959,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2748 "Python/bytecodes.c" + #line 2782 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -3844,7 +3970,7 @@ Py_DECREF(arg); Py_DECREF(&PyTuple_Type); // I.e., tuple if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3848 "Python/generated_cases.c.h" + #line 3974 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3858,7 +3984,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2762 "Python/bytecodes.c" + #line 2796 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -3880,7 +4006,7 @@ } Py_DECREF(tp); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3884 "Python/generated_cases.c.h" + #line 4010 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3894,7 +4020,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2787 "Python/bytecodes.c" + #line 2821 "Python/bytecodes.c" /* Builtin METH_O functions */ assert(kwnames == NULL); int is_meth = method != NULL; @@ -3922,7 +4048,7 @@ Py_DECREF(arg); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3926 "Python/generated_cases.c.h" + #line 4052 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3936,7 +4062,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2818 "Python/bytecodes.c" + #line 2852 "Python/bytecodes.c" /* Builtin METH_FASTCALL functions, without keywords */ assert(kwnames == NULL); int is_meth = method != NULL; @@ -3968,7 +4094,7 @@ 'invalid'). In those cases an exception is set, so we must handle it. */ - #line 3972 "Python/generated_cases.c.h" + #line 4098 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3982,7 +4108,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2853 "Python/bytecodes.c" + #line 2887 "Python/bytecodes.c" /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ int is_meth = method != NULL; int total_args = oparg; @@ -4014,7 +4140,7 @@ } Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4018 "Python/generated_cases.c.h" + #line 4144 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4028,7 +4154,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2888 "Python/bytecodes.c" + #line 2922 "Python/bytecodes.c" assert(kwnames == NULL); /* len(o) */ int is_meth = method != NULL; @@ -4053,7 +4179,7 @@ Py_DECREF(callable); Py_DECREF(arg); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4057 "Python/generated_cases.c.h" + #line 4183 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4066,7 +4192,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2915 "Python/bytecodes.c" + #line 2949 "Python/bytecodes.c" assert(kwnames == NULL); /* isinstance(o, o2) */ int is_meth = method != NULL; @@ -4093,7 +4219,7 @@ Py_DECREF(cls); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4097 "Python/generated_cases.c.h" + #line 4223 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4105,7 +4231,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *self = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; - #line 2945 "Python/bytecodes.c" + #line 2979 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); assert(method != NULL); @@ -4123,14 +4249,14 @@ JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1); assert(next_instr[-1].op.code == POP_TOP); DISPATCH(); - #line 4127 "Python/generated_cases.c.h" + #line 4253 "Python/generated_cases.c.h" } TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) { PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2965 "Python/bytecodes.c" + #line 2999 "Python/bytecodes.c" assert(kwnames == NULL); int is_meth = method != NULL; int total_args = oparg; @@ -4161,7 +4287,7 @@ Py_DECREF(arg); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4165 "Python/generated_cases.c.h" + #line 4291 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4174,7 +4300,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2999 "Python/bytecodes.c" + #line 3033 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -4203,7 +4329,7 @@ } Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4207 "Python/generated_cases.c.h" + #line 4333 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4216,7 +4342,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3031 "Python/bytecodes.c" + #line 3065 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 0 || oparg == 1); int is_meth = method != NULL; @@ -4245,7 +4371,7 @@ Py_DECREF(self); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4249 "Python/generated_cases.c.h" + #line 4375 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4258,7 +4384,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3063 "Python/bytecodes.c" + #line 3097 "Python/bytecodes.c" assert(kwnames == NULL); int is_meth = method != NULL; int total_args = oparg; @@ -4286,7 +4412,7 @@ } Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4290 "Python/generated_cases.c.h" + #line 4416 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4296,9 +4422,9 @@ } TARGET(INSTRUMENTED_CALL_FUNCTION_EX) { - #line 3094 "Python/bytecodes.c" + #line 3128 "Python/bytecodes.c" GO_TO_INSTRUCTION(CALL_FUNCTION_EX); - #line 4302 "Python/generated_cases.c.h" + #line 4428 "Python/generated_cases.c.h" } TARGET(CALL_FUNCTION_EX) { @@ -4307,7 +4433,7 @@ PyObject *callargs = stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))]; PyObject *func = stack_pointer[-(2 + ((oparg & 1) ? 1 : 0))]; PyObject *result; - #line 3098 "Python/bytecodes.c" + #line 3132 "Python/bytecodes.c" // DICT_MERGE is called before this opcode if there are kwargs. // It converts all dict subtypes in kwargs into regular dicts. assert(kwargs == NULL || PyDict_CheckExact(kwargs)); @@ -4369,14 +4495,14 @@ } result = PyObject_Call(func, callargs, kwargs); } - #line 4373 "Python/generated_cases.c.h" + #line 4499 "Python/generated_cases.c.h" Py_DECREF(func); Py_DECREF(callargs); Py_XDECREF(kwargs); - #line 3160 "Python/bytecodes.c" + #line 3194 "Python/bytecodes.c" assert(PEEK(3 + (oparg & 1)) == NULL); if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; } - #line 4380 "Python/generated_cases.c.h" + #line 4506 "Python/generated_cases.c.h" STACK_SHRINK(((oparg & 1) ? 1 : 0)); STACK_SHRINK(2); stack_pointer[-1] = result; @@ -4391,7 +4517,7 @@ PyObject *kwdefaults = (oparg & 0x02) ? stack_pointer[-(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0))] : NULL; PyObject *defaults = (oparg & 0x01) ? stack_pointer[-(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x01) ? 1 : 0))] : NULL; PyObject *func; - #line 3170 "Python/bytecodes.c" + #line 3204 "Python/bytecodes.c" PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); @@ -4420,14 +4546,14 @@ func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; func = (PyObject *)func_obj; - #line 4424 "Python/generated_cases.c.h" + #line 4550 "Python/generated_cases.c.h" STACK_SHRINK(((oparg & 0x01) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x08) ? 1 : 0)); stack_pointer[-1] = func; DISPATCH(); } TARGET(RETURN_GENERATOR) { - #line 3201 "Python/bytecodes.c" + #line 3235 "Python/bytecodes.c" assert(PyFunction_Check(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); @@ -4448,7 +4574,7 @@ frame = cframe.current_frame = prev; _PyFrame_StackPush(frame, (PyObject *)gen); goto resume_frame; - #line 4452 "Python/generated_cases.c.h" + #line 4578 "Python/generated_cases.c.h" } TARGET(BUILD_SLICE) { @@ -4456,15 +4582,15 @@ PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))]; PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))]; PyObject *slice; - #line 3224 "Python/bytecodes.c" + #line 3258 "Python/bytecodes.c" slice = PySlice_New(start, stop, step); - #line 4462 "Python/generated_cases.c.h" + #line 4588 "Python/generated_cases.c.h" Py_DECREF(start); Py_DECREF(stop); Py_XDECREF(step); - #line 3226 "Python/bytecodes.c" + #line 3260 "Python/bytecodes.c" if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; } - #line 4468 "Python/generated_cases.c.h" + #line 4594 "Python/generated_cases.c.h" STACK_SHRINK(((oparg == 3) ? 1 : 0)); STACK_SHRINK(1); stack_pointer[-1] = slice; @@ -4475,7 +4601,7 @@ PyObject *fmt_spec = ((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? stack_pointer[-((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))] : NULL; PyObject *value = stack_pointer[-(1 + (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))]; PyObject *result; - #line 3230 "Python/bytecodes.c" + #line 3264 "Python/bytecodes.c" /* Handles f-string value formatting. */ PyObject *(*conv_fn)(PyObject *); int which_conversion = oparg & FVC_MASK; @@ -4510,7 +4636,7 @@ Py_DECREF(value); Py_XDECREF(fmt_spec); if (result == NULL) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; } - #line 4514 "Python/generated_cases.c.h" + #line 4640 "Python/generated_cases.c.h" STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); stack_pointer[-1] = result; DISPATCH(); @@ -4519,10 +4645,10 @@ TARGET(COPY) { PyObject *bottom = stack_pointer[-(1 + (oparg-1))]; PyObject *top; - #line 3267 "Python/bytecodes.c" + #line 3301 "Python/bytecodes.c" assert(oparg > 0); top = Py_NewRef(bottom); - #line 4526 "Python/generated_cases.c.h" + #line 4652 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = top; DISPATCH(); @@ -4534,7 +4660,7 @@ PyObject *rhs = stack_pointer[-1]; PyObject *lhs = stack_pointer[-2]; PyObject *res; - #line 3272 "Python/bytecodes.c" + #line 3306 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -4549,12 +4675,12 @@ assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops)); assert(binary_ops[oparg]); res = binary_ops[oparg](lhs, rhs); - #line 4553 "Python/generated_cases.c.h" + #line 4679 "Python/generated_cases.c.h" Py_DECREF(lhs); Py_DECREF(rhs); - #line 3287 "Python/bytecodes.c" + #line 3321 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; - #line 4558 "Python/generated_cases.c.h" + #line 4684 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -4564,16 +4690,16 @@ TARGET(SWAP) { PyObject *top = stack_pointer[-1]; PyObject *bottom = stack_pointer[-(2 + (oparg-2))]; - #line 3292 "Python/bytecodes.c" + #line 3326 "Python/bytecodes.c" assert(oparg >= 2); - #line 4570 "Python/generated_cases.c.h" + #line 4696 "Python/generated_cases.c.h" stack_pointer[-1] = bottom; stack_pointer[-(2 + (oparg-2))] = top; DISPATCH(); } TARGET(INSTRUMENTED_INSTRUCTION) { - #line 3296 "Python/bytecodes.c" + #line 3330 "Python/bytecodes.c" int next_opcode = _Py_call_instrumentation_instruction( tstate, frame, next_instr-1); if (next_opcode < 0) goto error; @@ -4585,26 +4711,26 @@ assert(next_opcode > 0 && next_opcode < 256); opcode = next_opcode; DISPATCH_GOTO(); - #line 4589 "Python/generated_cases.c.h" + #line 4715 "Python/generated_cases.c.h" } TARGET(INSTRUMENTED_JUMP_FORWARD) { - #line 3310 "Python/bytecodes.c" + #line 3344 "Python/bytecodes.c" INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP); - #line 4595 "Python/generated_cases.c.h" + #line 4721 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_JUMP_BACKWARD) { - #line 3314 "Python/bytecodes.c" + #line 3348 "Python/bytecodes.c" INSTRUMENTED_JUMP(next_instr-1, next_instr-oparg, PY_MONITORING_EVENT_JUMP); - #line 4602 "Python/generated_cases.c.h" + #line 4728 "Python/generated_cases.c.h" CHECK_EVAL_BREAKER(); DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) { - #line 3319 "Python/bytecodes.c" + #line 3353 "Python/bytecodes.c" PyObject *cond = POP(); int err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -4613,12 +4739,12 @@ assert(err == 0 || err == 1); int offset = err*oparg; INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4617 "Python/generated_cases.c.h" + #line 4743 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { - #line 3330 "Python/bytecodes.c" + #line 3364 "Python/bytecodes.c" PyObject *cond = POP(); int err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -4627,17 +4753,16 @@ assert(err == 0 || err == 1); int offset = (1-err)*oparg; INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4631 "Python/generated_cases.c.h" + #line 4757 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) { - #line 3341 "Python/bytecodes.c" + #line 3375 "Python/bytecodes.c" PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; if (Py_IsNone(value)) { - _Py_DECREF_NO_DEALLOC(value); offset = oparg; } else { @@ -4645,17 +4770,16 @@ offset = 0; } INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4649 "Python/generated_cases.c.h" + #line 4774 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) { - #line 3356 "Python/bytecodes.c" + #line 3389 "Python/bytecodes.c" PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; if (Py_IsNone(value)) { - _Py_DECREF_NO_DEALLOC(value); offset = 0; } else { @@ -4663,30 +4787,30 @@ offset = oparg; } INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4667 "Python/generated_cases.c.h" + #line 4791 "Python/generated_cases.c.h" DISPATCH(); } TARGET(EXTENDED_ARG) { - #line 3371 "Python/bytecodes.c" + #line 3403 "Python/bytecodes.c" assert(oparg); opcode = next_instr->op.code; oparg = oparg << 8 | next_instr->op.arg; PRE_DISPATCH_GOTO(); DISPATCH_GOTO(); - #line 4678 "Python/generated_cases.c.h" + #line 4802 "Python/generated_cases.c.h" } TARGET(CACHE) { - #line 3379 "Python/bytecodes.c" + #line 3411 "Python/bytecodes.c" assert(0 && "Executing a cache."); Py_UNREACHABLE(); - #line 4685 "Python/generated_cases.c.h" + #line 4809 "Python/generated_cases.c.h" } TARGET(RESERVED) { - #line 3384 "Python/bytecodes.c" + #line 3416 "Python/bytecodes.c" assert(0 && "Executing RESERVED instruction."); Py_UNREACHABLE(); - #line 4692 "Python/generated_cases.c.h" + #line 4816 "Python/generated_cases.c.h" } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 9152744d7c2c1c..c70668e8295ae5 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -35,6 +35,8 @@ static const int8_t EVENT_FOR_OPCODE[256] = { [INSTRUMENTED_CALL] = PY_MONITORING_EVENT_CALL, [CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL, [INSTRUMENTED_CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL, + [LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL, + [INSTRUMENTED_LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL, [RESUME] = -1, [YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD, [INSTRUMENTED_YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD, @@ -74,6 +76,7 @@ static const uint8_t DE_INSTRUMENT[256] = { [INSTRUMENTED_FOR_ITER] = FOR_ITER, [INSTRUMENTED_END_FOR] = END_FOR, [INSTRUMENTED_END_SEND] = END_SEND, + [INSTRUMENTED_LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR, }; static const uint8_t INSTRUMENTED_OPCODES[256] = { @@ -107,6 +110,8 @@ static const uint8_t INSTRUMENTED_OPCODES[256] = { [INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND, [FOR_ITER] = INSTRUMENTED_FOR_ITER, [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER, + [LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, + [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, [INSTRUMENTED_LINE] = INSTRUMENTED_LINE, [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION, diff --git a/Python/intrinsics.c b/Python/intrinsics.c index cca29d859902a4..c6f5ac5402d644 100644 --- a/Python/intrinsics.c +++ b/Python/intrinsics.c @@ -3,10 +3,12 @@ #include "Python.h" #include "pycore_frame.h" +#include "pycore_function.h" #include "pycore_runtime.h" #include "pycore_global_objects.h" #include "pycore_intrinsics.h" #include "pycore_pyerrors.h" +#include "pycore_typevarobject.h" /******** Unary functions ********/ @@ -199,6 +201,13 @@ list_to_tuple(PyThreadState* unused, PyObject *v) return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v)); } +static PyObject * +make_typevar(PyThreadState* Py_UNUSED(ignored), PyObject *v) +{ + assert(PyUnicode_Check(v)); + return _Py_make_typevar(v, NULL, NULL); +} + const instrinsic_func1 _PyIntrinsics_UnaryFunctions[] = { [0] = no_intrinsic, @@ -208,6 +217,11 @@ _PyIntrinsics_UnaryFunctions[] = { [INTRINSIC_ASYNC_GEN_WRAP] = _PyAsyncGenValueWrapperNew, [INTRINSIC_UNARY_POSITIVE] = unary_pos, [INTRINSIC_LIST_TO_TUPLE] = list_to_tuple, + [INTRINSIC_TYPEVAR] = make_typevar, + [INTRINSIC_PARAMSPEC] = _Py_make_paramspec, + [INTRINSIC_TYPEVARTUPLE] = _Py_make_typevartuple, + [INTRINSIC_SUBSCRIPT_GENERIC] = _Py_subscript_generic, + [INTRINSIC_TYPEALIAS] = _Py_make_typealias, }; @@ -221,8 +235,26 @@ prep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs) return _PyExc_PrepReraiseStar(orig, excs); } +static PyObject * +make_typevar_with_bound(PyThreadState* Py_UNUSED(ignored), PyObject *name, + PyObject *evaluate_bound) +{ + assert(PyUnicode_Check(name)); + return _Py_make_typevar(name, evaluate_bound, NULL); +} + +static PyObject * +make_typevar_with_constraints(PyThreadState* Py_UNUSED(ignored), PyObject *name, + PyObject *evaluate_constraints) +{ + assert(PyUnicode_Check(name)); + return _Py_make_typevar(name, NULL, evaluate_constraints); +} + const instrinsic_func2 _PyIntrinsics_BinaryFunctions[] = { [INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star, + [INTRINSIC_TYPEVAR_WITH_BOUND] = make_typevar_with_bound, + [INTRINSIC_TYPEVAR_WITH_CONSTRAINTS] = make_typevar_with_constraints, + [INTRINSIC_SET_FUNCTION_TYPE_PARAMS] = _Py_set_function_type_params, }; - diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index ae68e045a6119f..53fbaa3e317e56 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -161,8 +161,12 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 1; case DELETE_GLOBAL: return 0; - case LOAD_NAME: + case LOAD_LOCALS: return 0; + case LOAD_NAME: + return 0+1; + case LOAD_FROM_DICT_OR_GLOBALS: + return 1; case LOAD_GLOBAL: return 0; case LOAD_GLOBAL_MODULE: @@ -175,8 +179,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 0; case DELETE_DEREF: return 0; - case LOAD_CLASSDEREF: - return 0; + case LOAD_FROM_DICT_OR_DEREF: + return 1; case LOAD_DEREF: return 0; case STORE_DEREF: @@ -207,6 +211,8 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) { return 1; case MAP_ADD: return 2; + case INSTRUMENTED_LOAD_SUPER_ATTR: + return 3; case LOAD_SUPER_ATTR: return 3; case LOAD_SUPER_ATTR_ATTR: @@ -551,7 +557,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 0; case DELETE_GLOBAL: return 0; + case LOAD_LOCALS: + return 1; case LOAD_NAME: + return 1+1; + case LOAD_FROM_DICT_OR_GLOBALS: return 1; case LOAD_GLOBAL: return ((oparg & 1) ? 1 : 0) + 1; @@ -565,7 +575,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 0; case DELETE_DEREF: return 0; - case LOAD_CLASSDEREF: + case LOAD_FROM_DICT_OR_DEREF: return 1; case LOAD_DEREF: return 1; @@ -597,6 +607,8 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) { return 0; case MAP_ADD: return 0; + case INSTRUMENTED_LOAD_SUPER_ATTR: + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_SUPER_ATTR: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_SUPER_ATTR_ATTR: @@ -869,14 +881,16 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = { [DELETE_ATTR] = { true, INSTR_FMT_IB }, [STORE_GLOBAL] = { true, INSTR_FMT_IB }, [DELETE_GLOBAL] = { true, INSTR_FMT_IB }, + [LOAD_LOCALS] = { true, INSTR_FMT_IB }, [LOAD_NAME] = { true, INSTR_FMT_IB }, + [LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB }, [LOAD_GLOBAL] = { true, INSTR_FMT_IBC000 }, [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000 }, [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000 }, [DELETE_FAST] = { true, INSTR_FMT_IB }, [MAKE_CELL] = { true, INSTR_FMT_IB }, [DELETE_DEREF] = { true, INSTR_FMT_IB }, - [LOAD_CLASSDEREF] = { true, INSTR_FMT_IB }, + [LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB }, [LOAD_DEREF] = { true, INSTR_FMT_IB }, [STORE_DEREF] = { true, INSTR_FMT_IB }, [COPY_FREE_VARS] = { true, INSTR_FMT_IB }, @@ -892,6 +906,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[256] = { [DICT_UPDATE] = { true, INSTR_FMT_IB }, [DICT_MERGE] = { true, INSTR_FMT_IB }, [MAP_ADD] = { true, INSTR_FMT_IB }, + [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC00000000 }, [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC }, [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC }, [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC }, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index f2742f4ad1f20e..3add06362711c9 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -86,8 +86,8 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_LOCALS, &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, &&TARGET_DELETE_NAME, @@ -110,9 +110,9 @@ static void *opcode_targets[256] = { &&TARGET_IMPORT_NAME, &&TARGET_IMPORT_FROM, &&TARGET_JUMP_FORWARD, + &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, - &&TARGET_STORE_ATTR_SLOT, &&TARGET_POP_JUMP_IF_FALSE, &&TARGET_POP_JUMP_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -147,7 +147,7 @@ static void *opcode_targets[256] = { &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, - &&TARGET_LOAD_CLASSDEREF, + &&TARGET_STORE_ATTR_SLOT, &&TARGET_COPY_FREE_VARS, &&TARGET_YIELD_VALUE, &&TARGET_RESUME, @@ -174,6 +174,8 @@ static void *opcode_targets[256] = { &&TARGET_KW_NAMES, &&TARGET_CALL_INTRINSIC_1, &&TARGET_CALL_INTRINSIC_2, + &&TARGET_LOAD_FROM_DICT_OR_GLOBALS, + &&TARGET_LOAD_FROM_DICT_OR_DEREF, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -234,9 +236,7 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR, &&TARGET_INSTRUMENTED_POP_JUMP_IF_NONE, &&TARGET_INSTRUMENTED_POP_JUMP_IF_NOT_NONE, &&TARGET_INSTRUMENTED_RESUME, diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c index 3b183280e1f24c..6a6f223d095d3b 100644 --- a/Python/perf_trampoline.c +++ b/Python/perf_trampoline.c @@ -193,75 +193,33 @@ typedef struct trampoline_api_st trampoline_api_t; #define trampoline_api _PyRuntime.ceval.perf.trampoline_api #define perf_map_file _PyRuntime.ceval.perf.map_file -static void * -perf_map_get_file(void) -{ - if (perf_map_file) { - return perf_map_file; - } - char filename[100]; - pid_t pid = getpid(); - // Location and file name of perf map is hard-coded in perf tool. - // Use exclusive create flag wit nofollow to prevent symlink attacks. - int flags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC; - snprintf(filename, sizeof(filename) - 1, "/tmp/perf-%jd.map", - (intmax_t)pid); - int fd = open(filename, flags, 0600); - if (fd == -1) { - perf_status = PERF_STATUS_FAILED; - PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename); - return NULL; - } - perf_map_file = fdopen(fd, "w"); - if (!perf_map_file) { - perf_status = PERF_STATUS_FAILED; - PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename); - close(fd); - return NULL; - } - return perf_map_file; -} - -static int -perf_map_close(void *state) -{ - FILE *fp = (FILE *)state; - int ret = 0; - if (fp) { - ret = fclose(fp); - } - perf_map_file = NULL; - perf_status = PERF_STATUS_NO_INIT; - return ret; -} static void perf_map_write_entry(void *state, const void *code_addr, unsigned int code_size, PyCodeObject *co) { - assert(state != NULL); - FILE *method_file = (FILE *)state; - const char *entry = PyUnicode_AsUTF8(co->co_qualname); - if (entry == NULL) { - _PyErr_WriteUnraisableMsg("Failed to get qualname from code object", - NULL); - return; + const char *entry = ""; + if (co->co_qualname != NULL) { + entry = PyUnicode_AsUTF8(co->co_qualname); } - const char *filename = PyUnicode_AsUTF8(co->co_filename); - if (filename == NULL) { - _PyErr_WriteUnraisableMsg("Failed to get filename from code object", - NULL); + const char *filename = ""; + if (co->co_filename != NULL) { + filename = PyUnicode_AsUTF8(co->co_filename); + } + size_t perf_map_entry_size = snprintf(NULL, 0, "py::%s:%s", entry, filename) + 1; + char* perf_map_entry = (char*) PyMem_RawMalloc(perf_map_entry_size); + if (perf_map_entry == NULL) { return; } - fprintf(method_file, "%" PRIxPTR " %x py::%s:%s\n", (uintptr_t) code_addr, code_size, entry, - filename); - fflush(method_file); + snprintf(perf_map_entry, perf_map_entry_size, "py::%s:%s", entry, filename); + PyUnstable_WritePerfMapEntry(code_addr, code_size, perf_map_entry); + PyMem_RawFree(perf_map_entry); } _PyPerf_Callbacks _Py_perfmap_callbacks = { - &perf_map_get_file, + NULL, &perf_map_write_entry, - &perf_map_close + NULL, }; static int @@ -465,13 +423,6 @@ _PyPerfTrampoline_Init(int activate) if (new_code_arena() < 0) { return -1; } - if (trampoline_api.state == NULL) { - void *state = trampoline_api.init_state(); - if (state == NULL) { - return -1; - } - trampoline_api.state = state; - } extra_code_index = _PyEval_RequestCodeExtraIndex(NULL); if (extra_code_index == -1) { return -1; @@ -491,10 +442,6 @@ _PyPerfTrampoline_Fini(void) tstate->interp->eval_frame = NULL; } free_code_arenas(); - if (trampoline_api.state != NULL) { - trampoline_api.free_state(trampoline_api.state); - trampoline_api.state = NULL; - } extra_code_index = -1; #endif return 0; @@ -507,6 +454,7 @@ _PyPerfTrampoline_AfterFork_Child(void) // Restart trampoline in file in child. int was_active = _PyIsPerfTrampolineActive(); _PyPerfTrampoline_Fini(); + PyUnstable_PerfMapState_Fini(); if (was_active) { _PyPerfTrampoline_Init(1); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index c5dc0f44a38068..06c43459624c67 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -26,6 +26,7 @@ #include "pycore_sysmodule.h" // _PySys_ClearAuditHooks() #include "pycore_traceback.h" // _Py_DumpTracebackThreads() #include "pycore_typeobject.h" // _PyTypes_InitTypes() +#include "pycore_typevarobject.h" // _Py_clear_generic_types() #include "pycore_unicodeobject.h" // _PyUnicode_InitTypes() #include "opcode.h" @@ -1128,11 +1129,12 @@ init_interp_main(PyThreadState *tstate) return _PyStatus_ERR("can't initialize signals"); } - if (_PyTraceMalloc_Init(config->tracemalloc) < 0) { - return _PyStatus_ERR("can't initialize tracemalloc"); + if (config->tracemalloc) { + if (_PyTraceMalloc_Start(config->tracemalloc) < 0) { + return _PyStatus_ERR("can't start tracemalloc"); + } } - #ifdef PY_HAVE_PERF_TRAMPOLINE if (config->perf_profiling) { if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_callbacks) < 0 || @@ -1698,6 +1700,7 @@ finalize_interp_clear(PyThreadState *tstate) int is_main_interp = _Py_IsMainInterpreter(tstate->interp); _PyExc_ClearExceptionGroupType(tstate->interp); + _Py_clear_generic_types(tstate->interp); /* Clear interpreter state and all thread states */ _PyInterpreterState_Clear(tstate); @@ -1772,6 +1775,7 @@ Py_FinalizeEx(void) */ _PyAtExit_Call(tstate->interp); + PyUnstable_PerfMapState_Fini(); /* Copy the core config, PyInterpreterState_Delete() free the core config memory */ @@ -1788,6 +1792,7 @@ Py_FinalizeEx(void) /* Remaining daemon threads will automatically exit when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ + _PyInterpreterState_SetFinalizing(tstate->interp, tstate); _PyRuntimeState_SetFinalizing(runtime, tstate); runtime->initialized = 0; runtime->core_initialized = 0; @@ -2142,6 +2147,10 @@ Py_EndInterpreter(PyThreadState *tstate) Py_FatalError("not the last thread"); } + /* Remaining daemon threads will automatically exit + when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ + _PyInterpreterState_SetFinalizing(interp, tstate); + // XXX Call something like _PyImport_Disable() here? _PyImport_FiniExternal(tstate->interp); @@ -2152,6 +2161,18 @@ Py_EndInterpreter(PyThreadState *tstate) finalize_interp_delete(tstate->interp); } +int +_Py_IsInterpreterFinalizing(PyInterpreterState *interp) +{ + /* We check the runtime first since, in a daemon thread, + interp might be dangling pointer. */ + PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime); + if (finalizing == NULL) { + finalizing = _PyInterpreterState_GetFinalizing(interp); + } + return finalizing != NULL; +} + /* Add the __main__ module */ static PyStatus diff --git a/Python/pystate.c b/Python/pystate.c index 26debf1f88b94a..25e655a2027918 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1436,11 +1436,13 @@ PyThreadState_Clear(PyThreadState *tstate) if (verbose && tstate->cframe->current_frame != NULL) { /* bpo-20526: After the main thread calls - _PyRuntimeState_SetFinalizing() in Py_FinalizeEx(), threads must - exit when trying to take the GIL. If a thread exit in the middle of - _PyEval_EvalFrameDefault(), tstate->frame is not reset to its - previous value. It is more likely with daemon threads, but it can - happen with regular threads if threading._shutdown() fails + _PyInterpreterState_SetFinalizing() in Py_FinalizeEx() + (or in Py_EndInterpreter() for subinterpreters), + threads must exit when trying to take the GIL. + If a thread exit in the middle of _PyEval_EvalFrameDefault(), + tstate->frame is not reset to its previous value. + It is more likely with daemon threads, but it can happen + with regular threads if threading._shutdown() fails (ex: interrupted by CTRL+C). */ fprintf(stderr, "PyThreadState_Clear: warning: thread still has a frame\n"); diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h index ed4a0ac2dd32de..b926caf4a57907 100644 --- a/Python/stdlib_module_names.h +++ b/Python/stdlib_module_names.h @@ -172,7 +172,6 @@ static const char* _Py_stdlib_module_names[] = { "itertools", "json", "keyword", -"lib2to3", "linecache", "locale", "logging", @@ -261,7 +260,6 @@ static const char* _Py_stdlib_module_names[] = { "syslog", "tabnanny", "tarfile", -"telnetlib", "tempfile", "termios", "textwrap", diff --git a/Python/symtable.c b/Python/symtable.c index 2c29f608413501..e2c00d17480dd1 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -35,6 +35,15 @@ #define NAMED_EXPR_COMP_IN_CLASS \ "assignment expression within a comprehension cannot be used in a class body" +#define NAMED_EXPR_COMP_IN_TYPEVAR_BOUND \ +"assignment expression within a comprehension cannot be used in a TypeVar bound" + +#define NAMED_EXPR_COMP_IN_TYPEALIAS \ +"assignment expression within a comprehension cannot be used in a type alias" + +#define NAMED_EXPR_COMP_IN_TYPEPARAM \ +"assignment expression within a comprehension cannot be used within the definition of a generic" + #define NAMED_EXPR_COMP_CONFLICT \ "assignment expression cannot rebind comprehension iteration variable '%U'" @@ -45,7 +54,19 @@ "assignment expression cannot be used in a comprehension iterable expression" #define ANNOTATION_NOT_ALLOWED \ -"'%s' can not be used within an annotation" +"%s cannot be used within an annotation" + +#define TYPEVAR_BOUND_NOT_ALLOWED \ +"%s cannot be used within a TypeVar bound" + +#define TYPEALIAS_NOT_ALLOWED \ +"%s cannot be used within a type alias" + +#define TYPEPARAM_NOT_ALLOWED \ +"%s cannot be used within the definition of a generic" + +#define DUPLICATE_TYPE_PARAM \ +"duplicate type parameter '%U'" #define LOCATION(x) \ @@ -95,7 +116,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, if (st->st_cur != NULL && (st->st_cur->ste_nested || - st->st_cur->ste_type == FunctionBlock)) + _PyST_IsFunctionLike(st->st_cur))) ste->ste_nested = 1; ste->ste_child_free = 0; ste->ste_generator = 0; @@ -105,7 +126,9 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_needs_class_closure = 0; ste->ste_comp_inlined = 0; ste->ste_comp_iter_target = 0; + ste->ste_can_see_class_scope = 0; ste->ste_comp_iter_expr = 0; + ste->ste_needs_classdict = 0; ste->ste_symbols = PyDict_New(); ste->ste_varnames = PyList_New(0); @@ -208,6 +231,7 @@ static int symtable_enter_block(struct symtable *st, identifier name, static int symtable_exit_block(struct symtable *st); static int symtable_visit_stmt(struct symtable *st, stmt_ty s); static int symtable_visit_expr(struct symtable *st, expr_ty s); +static int symtable_visit_type_param(struct symtable *st, type_param_ty s); static int symtable_visit_genexp(struct symtable *st, expr_ty s); static int symtable_visit_listcomp(struct symtable *st, expr_ty s); static int symtable_visit_setcomp(struct symtable *st, expr_ty s); @@ -403,6 +427,15 @@ _PyST_GetScope(PySTEntryObject *ste, PyObject *name) return (symbol >> SCOPE_OFFSET) & SCOPE_MASK; } +int +_PyST_IsFunctionLike(PySTEntryObject *ste) +{ + return ste->ste_type == FunctionBlock + || ste->ste_type == TypeVarBoundBlock + || ste->ste_type == TypeAliasBlock + || ste->ste_type == TypeParamBlock; +} + static int error_at_directive(PySTEntryObject *ste, PyObject *name) { @@ -495,7 +528,7 @@ error_at_directive(PySTEntryObject *ste, PyObject *name) static int analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, PyObject *bound, PyObject *local, PyObject *free, - PyObject *global) + PyObject *global, PyObject *type_params, PySTEntryObject *class_entry) { if (flags & DEF_GLOBAL) { if (flags & DEF_NONLOCAL) { @@ -524,6 +557,12 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, return error_at_directive(ste, name); } + if (PySet_Contains(type_params, name)) { + PyErr_Format(PyExc_SyntaxError, + "nonlocal binding not allowed for type parameter '%U'", + name); + return error_at_directive(ste, name); + } SET_SCOPE(scopes, name, FREE); ste->ste_free = 1; return PySet_Add(free, name) >= 0; @@ -534,8 +573,34 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, return 0; if (PySet_Discard(global, name) < 0) return 0; + if (flags & DEF_TYPE_PARAM) { + if (PySet_Add(type_params, name) < 0) + return 0; + } + else { + if (PySet_Discard(type_params, name) < 0) + return 0; + } return 1; } + // If we were passed class_entry (i.e., we're in an ste_can_see_class_scope scope) + // and the bound name is in that set, then the name is potentially bound both by + // the immediately enclosing class namespace, and also by an outer function namespace. + // In that case, we want the runtime name resolution to look at only the class + // namespace and the globals (not the namespace providing the bound). + // Similarly, if the name is explicitly global in the class namespace (through the + // global statement), we want to also treat it as a global in this scope. + if (class_entry != NULL) { + long class_flags = _PyST_GetSymbol(class_entry, name); + if (class_flags & DEF_GLOBAL) { + SET_SCOPE(scopes, name, GLOBAL_EXPLICIT); + return 1; + } + else if (class_flags & DEF_BOUND && !(class_flags & DEF_NONLOCAL)) { + SET_SCOPE(scopes, name, GLOBAL_IMPLICIT); + return 1; + } + } /* If an enclosing block has a binding for this name, it is a free variable rather than a global variable. Note that having a non-NULL bound implies that the block @@ -576,7 +641,7 @@ is_free_in_any_child(PySTEntryObject *entry, PyObject *key) static int inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, PyObject *scopes, PyObject *comp_free, - PyObject *promote_to_cell) + PyObject *inlined_cells) { PyObject *k, *v; Py_ssize_t pos = 0; @@ -589,6 +654,11 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, } int scope = (comp_flags >> SCOPE_OFFSET) & SCOPE_MASK; int only_flags = comp_flags & ((1 << SCOPE_OFFSET) - 1); + if (scope == CELL || only_flags & DEF_COMP_CELL) { + if (PySet_Add(inlined_cells, k) < 0) { + return 0; + } + } PyObject *existing = PyDict_GetItemWithError(ste->ste_symbols, k); if (existing == NULL && PyErr_Occurred()) { return 0; @@ -609,17 +679,10 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, } else { if (PyLong_AsLong(existing) & DEF_BOUND) { - // cell vars in comprehension that are locals in outer scope - // must be promoted to cell so u_cellvars isn't wrong - if (scope == CELL && ste->ste_type == FunctionBlock) { - if (PySet_Add(promote_to_cell, k) < 0) { - return 0; - } - } - // free vars in comprehension that are locals in outer scope can - // now simply be locals, unless they are free in comp children - if (!is_free_in_any_child(comp, k)) { + // now simply be locals, unless they are free in comp children, + // or if the outer scope is a class block + if (!is_free_in_any_child(comp, k) && ste->ste_type != ClassBlock) { if (PySet_Discard(comp_free, k) < 0) { return 0; } @@ -641,7 +704,7 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, */ static int -analyze_cells(PyObject *scopes, PyObject *free, PyObject *promote_to_cell) +analyze_cells(PyObject *scopes, PyObject *free, PyObject *inlined_cells) { PyObject *name, *v, *v_cell; int success = 0; @@ -656,7 +719,7 @@ analyze_cells(PyObject *scopes, PyObject *free, PyObject *promote_to_cell) scope = PyLong_AS_LONG(v); if (scope != LOCAL) continue; - if (!PySet_Contains(free, name) && !PySet_Contains(promote_to_cell, name)) + if (!PySet_Contains(free, name) && !PySet_Contains(inlined_cells, name)) continue; /* Replace LOCAL with CELL for this name, and remove from free. It is safe to replace the value of name @@ -682,6 +745,11 @@ drop_class_free(PySTEntryObject *ste, PyObject *free) return 0; if (res) ste->ste_needs_class_closure = 1; + res = PySet_Discard(free, &_Py_ID(__classdict__)); + if (res < 0) + return 0; + if (res) + ste->ste_needs_classdict = 1; return 1; } @@ -691,7 +759,8 @@ drop_class_free(PySTEntryObject *ste, PyObject *free) */ static int update_symbols(PyObject *symbols, PyObject *scopes, - PyObject *bound, PyObject *free, int classflag) + PyObject *bound, PyObject *free, + PyObject *inlined_cells, int classflag) { PyObject *name = NULL, *itr = NULL; PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = NULL; @@ -702,6 +771,9 @@ update_symbols(PyObject *symbols, PyObject *scopes, long scope, flags; assert(PyLong_Check(v)); flags = PyLong_AS_LONG(v); + if (PySet_Contains(inlined_cells, name)) { + flags |= DEF_COMP_CELL; + } v_scope = PyDict_GetItemWithError(scopes, name); assert(v_scope && PyLong_Check(v_scope)); scope = PyLong_AS_LONG(v_scope); @@ -799,14 +871,16 @@ update_symbols(PyObject *symbols, PyObject *scopes, static int analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, - PyObject *global, PyObject **child_free); + PyObject *global, PyObject *type_params, + PySTEntryObject *class_entry, PyObject **child_free); static int analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, - PyObject *global) + PyObject *global, PyObject *type_params, + PySTEntryObject *class_entry) { PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL, *promote_to_cell = NULL; + PyObject *newglobal = NULL, *newfree = NULL, *inlined_cells = NULL; PyObject *temp; int success = 0; Py_ssize_t i, pos = 0; @@ -838,8 +912,8 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, newbound = PySet_New(NULL); if (!newbound) goto error; - promote_to_cell = PySet_New(NULL); - if (!promote_to_cell) + inlined_cells = PySet_New(NULL); + if (!inlined_cells) goto error; /* Class namespace has no effect on names visible in @@ -865,14 +939,14 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { long flags = PyLong_AS_LONG(v); if (!analyze_name(ste, scopes, name, flags, - bound, local, free, global)) + bound, local, free, global, type_params, class_entry)) goto error; } /* Populate global and bound sets to be passed to children. */ if (ste->ste_type != ClassBlock) { /* Add function locals to bound set */ - if (ste->ste_type == FunctionBlock) { + if (_PyST_IsFunctionLike(ste)) { temp = PyNumber_InPlaceOr(newbound, local); if (!temp) goto error; @@ -892,9 +966,11 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, Py_DECREF(temp); } else { - /* Special-case __class__ */ + /* Special-case __class__ and __classdict__ */ if (PySet_Add(newbound, &_Py_ID(__class__)) < 0) goto error; + if (PySet_Add(newbound, &_Py_ID(__classdict__)) < 0) + goto error; } /* Recursively call analyze_child_block() on each child block. @@ -910,18 +986,28 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, assert(c && PySTEntry_Check(c)); entry = (PySTEntryObject*)c; + PySTEntryObject *new_class_entry = NULL; + if (entry->ste_can_see_class_scope) { + if (ste->ste_type == ClassBlock) { + new_class_entry = ste; + } + else if (class_entry) { + new_class_entry = class_entry; + } + } + // we inline all non-generator-expression comprehensions int inline_comp = entry->ste_comprehension && !entry->ste_generator; if (!analyze_child_block(entry, newbound, newfree, newglobal, - &child_free)) + type_params, new_class_entry, &child_free)) { goto error; } if (inline_comp) { - if (!inline_comprehension(ste, entry, scopes, child_free, promote_to_cell)) { + if (!inline_comprehension(ste, entry, scopes, child_free, inlined_cells)) { Py_DECREF(child_free); goto error; } @@ -952,12 +1038,12 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, } /* Check if any local variables must be converted to cell variables */ - if (ste->ste_type == FunctionBlock && !analyze_cells(scopes, newfree, promote_to_cell)) + if (_PyST_IsFunctionLike(ste) && !analyze_cells(scopes, newfree, inlined_cells)) goto error; else if (ste->ste_type == ClassBlock && !drop_class_free(ste, newfree)) goto error; /* Records the results of the analysis in the symbol table entry */ - if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, + if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, inlined_cells, ste->ste_type == ClassBlock)) goto error; @@ -972,7 +1058,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, Py_XDECREF(newbound); Py_XDECREF(newglobal); Py_XDECREF(newfree); - Py_XDECREF(promote_to_cell); + Py_XDECREF(inlined_cells); if (!success) assert(PyErr_Occurred()); return success; @@ -980,9 +1066,11 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, static int analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, - PyObject *global, PyObject** child_free) + PyObject *global, PyObject *type_params, + PySTEntryObject *class_entry, PyObject** child_free) { PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL; + PyObject *temp_type_params = NULL; /* Copy the bound/global/free sets. @@ -1000,24 +1088,30 @@ analyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free, temp_global = PySet_New(global); if (!temp_global) goto error; + temp_type_params = PySet_New(type_params); + if (!temp_type_params) + goto error; - if (!analyze_block(entry, temp_bound, temp_free, temp_global)) + if (!analyze_block(entry, temp_bound, temp_free, temp_global, + temp_type_params, class_entry)) goto error; *child_free = temp_free; Py_DECREF(temp_bound); Py_DECREF(temp_global); + Py_DECREF(temp_type_params); return 1; error: Py_XDECREF(temp_bound); Py_XDECREF(temp_free); Py_XDECREF(temp_global); + Py_XDECREF(temp_type_params); return 0; } static int symtable_analyze(struct symtable *st) { - PyObject *free, *global; + PyObject *free, *global, *type_params; int r; free = PySet_New(NULL); @@ -1028,9 +1122,16 @@ symtable_analyze(struct symtable *st) Py_DECREF(free); return 0; } - r = analyze_block(st->st_top, NULL, free, global); + type_params = PySet_New(NULL); + if (!type_params) { + Py_DECREF(free); + Py_DECREF(global); + return 0; + } + r = analyze_block(st->st_top, NULL, free, global, type_params, NULL); Py_DECREF(free); Py_DECREF(global); + Py_DECREF(type_params); return r; } @@ -1133,6 +1234,13 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s end_lineno, end_col_offset + 1); goto error; } + if ((flag & DEF_TYPE_PARAM) && (val & DEF_TYPE_PARAM)) { + PyErr_Format(PyExc_SyntaxError, DUPLICATE_TYPE_PARAM, name); + PyErr_RangedSyntaxLocationObject(st->st_filename, + lineno, col_offset + 1, + end_lineno, end_col_offset + 1); + goto error; + } val |= flag; } else if (PyErr_Occurred()) { @@ -1204,6 +1312,65 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag, lineno, col_offset, end_lineno, end_col_offset); } +static int +symtable_enter_type_param_block(struct symtable *st, identifier name, + void *ast, int has_defaults, int has_kwdefaults, + enum _stmt_kind kind, + int lineno, int col_offset, + int end_lineno, int end_col_offset) +{ + _Py_block_ty current_type = st->st_cur->ste_type; + if(!symtable_enter_block(st, name, TypeParamBlock, ast, lineno, + col_offset, end_lineno, end_col_offset)) { + return 0; + } + if (current_type == ClassBlock) { + st->st_cur->ste_can_see_class_scope = 1; + if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, lineno, col_offset, end_lineno, end_col_offset)) { + return 0; + } + } + if (kind == ClassDef_kind) { + _Py_DECLARE_STR(type_params, ".type_params"); + // It gets "set" when we create the type params tuple and + // "used" when we build up the bases. + if (!symtable_add_def(st, &_Py_STR(type_params), DEF_LOCAL, + lineno, col_offset, end_lineno, end_col_offset)) { + return 0; + } + if (!symtable_add_def(st, &_Py_STR(type_params), USE, + lineno, col_offset, end_lineno, end_col_offset)) { + return 0; + } + st->st_private = name; + // This is used for setting the generic base + _Py_DECLARE_STR(generic_base, ".generic_base"); + if (!symtable_add_def(st, &_Py_STR(generic_base), DEF_LOCAL, + lineno, col_offset, end_lineno, end_col_offset)) { + return 0; + } + if (!symtable_add_def(st, &_Py_STR(generic_base), USE, + lineno, col_offset, end_lineno, end_col_offset)) { + return 0; + } + } + if (has_defaults) { + _Py_DECLARE_STR(defaults, ".defaults"); + if (!symtable_add_def(st, &_Py_STR(defaults), DEF_PARAM, + lineno, col_offset, end_lineno, end_col_offset)) { + return 0; + } + } + if (has_kwdefaults) { + _Py_DECLARE_STR(kwdefaults, ".kwdefaults"); + if (!symtable_add_def(st, &_Py_STR(kwdefaults), DEF_PARAM, + lineno, col_offset, end_lineno, end_col_offset)) { + return 0; + } + } + return 1; +} + /* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. They use the ASDL name to synthesize the name of the C type and the visit function. @@ -1275,6 +1442,17 @@ symtable_record_directive(struct symtable *st, identifier name, int lineno, return res == 0; } +static int +has_kwonlydefaults(asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults) +{ + for (int i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { + expr_ty default_ = asdl_seq_GET(kw_defaults, i); + if (default_) { + return 1; + } + } + return 0; +} static int symtable_visit_stmt(struct symtable *st, stmt_ty s) @@ -1292,11 +1470,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); if (s->v.FunctionDef.args->kw_defaults) VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults); + if (s->v.FunctionDef.decorator_list) + VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); + if (asdl_seq_LEN(s->v.FunctionDef.type_params) > 0) { + if (!symtable_enter_type_param_block( + st, s->v.FunctionDef.name, + (void *)s->v.FunctionDef.type_params, + s->v.FunctionDef.args->defaults != NULL, + has_kwonlydefaults(s->v.FunctionDef.args->kwonlyargs, + s->v.FunctionDef.args->kw_defaults), + s->kind, + LOCATION(s))) { + VISIT_QUIT(st, 0); + } + VISIT_SEQ(st, type_param, s->v.FunctionDef.type_params); + } if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args, s->v.FunctionDef.returns)) VISIT_QUIT(st, 0); - if (s->v.FunctionDef.decorator_list) - VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, FunctionBlock, (void *)s, LOCATION(s))) @@ -1305,25 +1496,85 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, stmt, s->v.FunctionDef.body); if (!symtable_exit_block(st)) VISIT_QUIT(st, 0); + if (asdl_seq_LEN(s->v.FunctionDef.type_params) > 0) { + if (!symtable_exit_block(st)) + VISIT_QUIT(st, 0); + } break; case ClassDef_kind: { PyObject *tmp; if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s))) VISIT_QUIT(st, 0); - VISIT_SEQ(st, expr, s->v.ClassDef.bases); - VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); if (s->v.ClassDef.decorator_list) VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); + if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) { + if (!symtable_enter_type_param_block(st, s->v.ClassDef.name, + (void *)s->v.ClassDef.type_params, + false, false, s->kind, + LOCATION(s))) { + VISIT_QUIT(st, 0); + } + VISIT_SEQ(st, type_param, s->v.ClassDef.type_params); + } + VISIT_SEQ(st, expr, s->v.ClassDef.bases); + VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno, s->col_offset, s->end_lineno, s->end_col_offset)) VISIT_QUIT(st, 0); tmp = st->st_private; st->st_private = s->v.ClassDef.name; + if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) { + if (!symtable_add_def(st, &_Py_ID(__type_params__), + DEF_LOCAL, LOCATION(s))) { + VISIT_QUIT(st, 0); + } + _Py_DECLARE_STR(type_params, ".type_params"); + if (!symtable_add_def(st, &_Py_STR(type_params), + USE, LOCATION(s))) { + VISIT_QUIT(st, 0); + } + } VISIT_SEQ(st, stmt, s->v.ClassDef.body); st->st_private = tmp; if (!symtable_exit_block(st)) VISIT_QUIT(st, 0); + if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) { + if (!symtable_exit_block(st)) + VISIT_QUIT(st, 0); + } + break; + } + case TypeAlias_kind: { + VISIT(st, expr, s->v.TypeAlias.name); + assert(s->v.TypeAlias.name->kind == Name_kind); + PyObject *name = s->v.TypeAlias.name->v.Name.id; + int is_in_class = st->st_cur->ste_type == ClassBlock; + int is_generic = asdl_seq_LEN(s->v.TypeAlias.type_params) > 0; + if (is_generic) { + if (!symtable_enter_type_param_block( + st, name, + (void *)s->v.TypeAlias.type_params, + false, false, s->kind, + LOCATION(s))) { + VISIT_QUIT(st, 0); + } + VISIT_SEQ(st, type_param, s->v.TypeAlias.type_params); + } + if (!symtable_enter_block(st, name, TypeAliasBlock, + (void *)s, LOCATION(s))) + VISIT_QUIT(st, 0); + st->st_cur->ste_can_see_class_scope = is_in_class; + if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(s->v.TypeAlias.value))) { + VISIT_QUIT(st, 0); + } + VISIT(st, expr, s->v.TypeAlias.value); + if (!symtable_exit_block(st)) + VISIT_QUIT(st, 0); + if (is_generic) { + if (!symtable_exit_block(st)) + VISIT_QUIT(st, 0); + } break; } case Return_kind: @@ -1532,11 +1783,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (s->v.AsyncFunctionDef.args->kw_defaults) VISIT_SEQ_WITH_NULL(st, expr, s->v.AsyncFunctionDef.args->kw_defaults); + if (s->v.AsyncFunctionDef.decorator_list) + VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list); + if (asdl_seq_LEN(s->v.AsyncFunctionDef.type_params) > 0) { + if (!symtable_enter_type_param_block( + st, s->v.AsyncFunctionDef.name, + (void *)s->v.AsyncFunctionDef.type_params, + s->v.AsyncFunctionDef.args->defaults != NULL, + has_kwonlydefaults(s->v.AsyncFunctionDef.args->kwonlyargs, + s->v.AsyncFunctionDef.args->kw_defaults), + s->kind, + LOCATION(s))) { + VISIT_QUIT(st, 0); + } + VISIT_SEQ(st, type_param, s->v.AsyncFunctionDef.type_params); + } if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args, s->v.AsyncFunctionDef.returns)) VISIT_QUIT(st, 0); - if (s->v.AsyncFunctionDef.decorator_list) - VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name, FunctionBlock, (void *)s, s->lineno, s->col_offset, @@ -1547,6 +1811,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body); if (!symtable_exit_block(st)) VISIT_QUIT(st, 0); + if (asdl_seq_LEN(s->v.AsyncFunctionDef.type_params) > 0) { + if (!symtable_exit_block(st)) + VISIT_QUIT(st, 0); + } break; case AsyncWith_kind: VISIT_SEQ(st, withitem, s->v.AsyncWith.items); @@ -1621,9 +1889,27 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste, LOCATION(e)); } - /* Disallow usage in ClassBlock */ - if (ste->ste_type == ClassBlock) { - PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS); + /* Disallow usage in ClassBlock and type scopes */ + if (ste->ste_type == ClassBlock || + ste->ste_type == TypeParamBlock || + ste->ste_type == TypeAliasBlock || + ste->ste_type == TypeVarBoundBlock) { + switch (ste->ste_type) { + case ClassBlock: + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS); + break; + case TypeParamBlock: + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEPARAM); + break; + case TypeAliasBlock: + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEALIAS); + break; + case TypeVarBoundBlock: + PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEVAR_BOUND); + break; + default: + Py_UNREACHABLE(); + } PyErr_RangedSyntaxLocationObject(st->st_filename, e->lineno, e->col_offset + 1, @@ -1633,7 +1919,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e) } } - /* We should always find either a FunctionBlock, ModuleBlock or ClassBlock + /* We should always find either a function-like block, ModuleBlock or ClassBlock and should never fall to this case */ Py_UNREACHABLE(); @@ -1806,7 +2092,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && - st->st_cur->ste_type == FunctionBlock && + _PyST_IsFunctionLike(st->st_cur) && _PyUnicode_EqualToASCIIString(e->v.Name.id, "super")) { if (!symtable_add_def(st, &_Py_ID(__class__), USE, LOCATION(e))) VISIT_QUIT(st, 0); @@ -1823,6 +2109,45 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT_QUIT(st, 1); } +static int +symtable_visit_type_param(struct symtable *st, type_param_ty tp) +{ + if (++st->recursion_depth > st->recursion_limit) { + PyErr_SetString(PyExc_RecursionError, + "maximum recursion depth exceeded during compilation"); + VISIT_QUIT(st, 0); + } + switch(tp->kind) { + case TypeVar_kind: + if (!symtable_add_def(st, tp->v.TypeVar.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp))) + VISIT_QUIT(st, 0); + if (tp->v.TypeVar.bound) { + int is_in_class = st->st_cur->ste_can_see_class_scope; + if (!symtable_enter_block(st, tp->v.TypeVar.name, + TypeVarBoundBlock, (void *)tp, + LOCATION(tp))) + VISIT_QUIT(st, 0); + st->st_cur->ste_can_see_class_scope = is_in_class; + if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(tp->v.TypeVar.bound))) { + VISIT_QUIT(st, 0); + } + VISIT(st, expr, tp->v.TypeVar.bound); + if (!symtable_exit_block(st)) + VISIT_QUIT(st, 0); + } + break; + case TypeVarTuple_kind: + if (!symtable_add_def(st, tp->v.TypeVarTuple.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp))) + VISIT_QUIT(st, 0); + break; + case ParamSpec_kind: + if (!symtable_add_def(st, tp->v.ParamSpec.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp))) + VISIT_QUIT(st, 0); + break; + } + VISIT_QUIT(st, 1); +} + static int symtable_visit_pattern(struct symtable *st, pattern_ty p) { @@ -2194,11 +2519,18 @@ symtable_visit_dictcomp(struct symtable *st, expr_ty e) static int symtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_ty e) { - if (st->st_cur->ste_type != AnnotationBlock) { + enum _block_type type = st->st_cur->ste_type; + if (type == AnnotationBlock) + PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name); + else if (type == TypeVarBoundBlock) + PyErr_Format(PyExc_SyntaxError, TYPEVAR_BOUND_NOT_ALLOWED, name); + else if (type == TypeAliasBlock) + PyErr_Format(PyExc_SyntaxError, TYPEALIAS_NOT_ALLOWED, name); + else if (type == TypeParamBlock) + PyErr_Format(PyExc_SyntaxError, TYPEPARAM_NOT_ALLOWED, name); + else return 1; - } - PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name); PyErr_RangedSyntaxLocationObject(st->st_filename, e->lineno, e->col_offset + 1, diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 894a3e8a98fd8a..33147f012b611d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -52,6 +52,10 @@ extern const char *PyWin_DLLVersionString; #include #endif +#ifdef HAVE_FCNTL_H +#include +#endif + /*[clinic input] module sys [clinic start generated code]*/ @@ -332,6 +336,7 @@ _PySys_ClearAuditHooks(PyThreadState *ts) } _PyRuntimeState *runtime = ts->interp->runtime; + /* The hooks are global so we have to check for runtime finalization. */ PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime); assert(finalizing == ts); if (finalizing != ts) { @@ -949,10 +954,6 @@ call_trampoline(PyThreadState *tstate, PyObject* callback, PyObject *result = _PyObject_FastCallTstate(tstate, callback, stack, 3); PyFrame_LocalsToFast(frame, 1); - if (result == NULL) { - PyTraceBack_Here(frame); - } - return result; } @@ -2039,6 +2040,9 @@ sys__clear_type_cache_impl(PyObject *module) Py_RETURN_NONE; } +/* Note that, for now, we do not have a per-interpreter equivalent + for sys.is_finalizing(). */ + /*[clinic input] sys.is_finalizing @@ -2144,7 +2148,7 @@ sys_activate_stack_trampoline_impl(PyObject *module, const char *backend) if (strcmp(backend, "perf") == 0) { _PyPerf_Callbacks cur_cb; _PyPerfTrampoline_GetCallbacks(&cur_cb); - if (cur_cb.init_state != _Py_perfmap_callbacks.init_state) { + if (cur_cb.write_state != _Py_perfmap_callbacks.write_state) { if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_callbacks) < 0 ) { PyErr_SetString(PyExc_ValueError, "can't activate perf trampoline"); return NULL; @@ -2240,6 +2244,80 @@ sys__getframemodulename_impl(PyObject *module, int depth) } +#ifdef __cplusplus +extern "C" { +#endif + +static PerfMapState perf_map_state; + +PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void) { +#ifndef MS_WINDOWS + char filename[100]; + pid_t pid = getpid(); + // Use nofollow flag to prevent symlink attacks. + int flags = O_WRONLY | O_CREAT | O_APPEND | O_NOFOLLOW | O_CLOEXEC; + snprintf(filename, sizeof(filename) - 1, "/tmp/perf-%jd.map", + (intmax_t)pid); + int fd = open(filename, flags, 0600); + if (fd == -1) { + return -1; + } + else{ + perf_map_state.perf_map = fdopen(fd, "a"); + if (perf_map_state.perf_map == NULL) { + close(fd); + return -1; + } + } + perf_map_state.map_lock = PyThread_allocate_lock(); + if (perf_map_state.map_lock == NULL) { + fclose(perf_map_state.perf_map); + return -2; + } +#endif + return 0; +} + +PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry( + const void *code_addr, + unsigned int code_size, + const char *entry_name +) { +#ifndef MS_WINDOWS + if (perf_map_state.perf_map == NULL) { + int ret = PyUnstable_PerfMapState_Init(); + if(ret != 0){ + return ret; + } + } + PyThread_acquire_lock(perf_map_state.map_lock, 1); + fprintf(perf_map_state.perf_map, "%" PRIxPTR " %x %s\n", (uintptr_t) code_addr, code_size, entry_name); + fflush(perf_map_state.perf_map); + PyThread_release_lock(perf_map_state.map_lock); +#endif + return 0; +} + +PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void) { +#ifndef MS_WINDOWS + if (perf_map_state.perf_map != NULL) { + // close the file + PyThread_acquire_lock(perf_map_state.map_lock, 1); + fclose(perf_map_state.perf_map); + PyThread_release_lock(perf_map_state.map_lock); + + // clean up the lock and state + PyThread_free_lock(perf_map_state.map_lock); + perf_map_state.perf_map = NULL; + } +#endif +} + +#ifdef __cplusplus +} +#endif + + static PyMethodDef sys_methods[] = { /* Might as well keep this in alphabetic order */ SYS_ADDAUDITHOOK_METHODDEF diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c new file mode 100644 index 00000000000000..bc765623522288 --- /dev/null +++ b/Python/tracemalloc.c @@ -0,0 +1,1560 @@ +#include "Python.h" +#include "pycore_fileutils.h" // _Py_write_noraise() +#include "pycore_gc.h" // PyGC_Head +#include "pycore_hashtable.h" // _Py_hashtable_t +#include "pycore_object.h" // _PyType_PreHeaderSize +#include "pycore_pymem.h" // _Py_tracemalloc_config +#include "pycore_runtime.h" // _Py_ID() +#include "pycore_traceback.h" +#include +#include "frameobject.h" // _PyInterpreterFrame_GetLine + +#include // malloc() + +#define tracemalloc_config _PyRuntime.tracemalloc.config + +_Py_DECLARE_STR(anon_unknown, ""); + +/* Forward declaration */ +static void* raw_malloc(size_t size); +static void raw_free(void *ptr); + +#ifdef Py_DEBUG +# define TRACE_DEBUG +#endif + +#define TO_PTR(key) ((const void *)(uintptr_t)(key)) +#define FROM_PTR(key) ((uintptr_t)(key)) + +#define allocators _PyRuntime.tracemalloc.allocators + + +#if defined(TRACE_RAW_MALLOC) +/* This lock is needed because tracemalloc_free() is called without + the GIL held from PyMem_RawFree(). It cannot acquire the lock because it + would introduce a deadlock in _PyThreadState_DeleteCurrent(). */ +# define tables_lock _PyRuntime.tracemalloc.tables_lock +# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1) +# define TABLES_UNLOCK() PyThread_release_lock(tables_lock) +#else + /* variables are protected by the GIL */ +# define TABLES_LOCK() +# define TABLES_UNLOCK() +#endif + + +#define DEFAULT_DOMAIN 0 + +typedef struct tracemalloc_frame frame_t; +typedef struct tracemalloc_traceback traceback_t; + +#define TRACEBACK_SIZE(NFRAME) \ + (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1)) + +/* The maximum number of frames is either: + - The maximum number of frames we can store in `traceback_t.nframe` + - The maximum memory size_t we can allocate */ +static const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1)); + + +#define tracemalloc_empty_traceback _PyRuntime.tracemalloc.empty_traceback + + +/* Trace of a memory block */ +typedef struct { + /* Size of the memory block in bytes */ + size_t size; + + /* Traceback where the memory block was allocated */ + traceback_t *traceback; +} trace_t; + + +#define tracemalloc_traced_memory _PyRuntime.tracemalloc.traced_memory +#define tracemalloc_peak_traced_memory _PyRuntime.tracemalloc.peak_traced_memory +#define tracemalloc_filenames _PyRuntime.tracemalloc.filenames +#define tracemalloc_traceback _PyRuntime.tracemalloc.traceback +#define tracemalloc_tracebacks _PyRuntime.tracemalloc.tracebacks +#define tracemalloc_traces _PyRuntime.tracemalloc.traces +#define tracemalloc_domains _PyRuntime.tracemalloc.domains + + +#ifdef TRACE_DEBUG +static void +tracemalloc_error(const char *format, ...) +{ + va_list ap; + fprintf(stderr, "tracemalloc: "); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fprintf(stderr, "\n"); + fflush(stderr); +} +#endif + + +#if defined(TRACE_RAW_MALLOC) +#define REENTRANT_THREADLOCAL + +#define tracemalloc_reentrant_key _PyRuntime.tracemalloc.reentrant_key + +/* Any non-NULL pointer can be used */ +#define REENTRANT Py_True + +static int +get_reentrant(void) +{ + void *ptr; + + assert(PyThread_tss_is_created(&tracemalloc_reentrant_key)); + ptr = PyThread_tss_get(&tracemalloc_reentrant_key); + if (ptr != NULL) { + assert(ptr == REENTRANT); + return 1; + } + else + return 0; +} + +static void +set_reentrant(int reentrant) +{ + assert(reentrant == 0 || reentrant == 1); + assert(PyThread_tss_is_created(&tracemalloc_reentrant_key)); + + if (reentrant) { + assert(!get_reentrant()); + PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT); + } + else { + assert(get_reentrant()); + PyThread_tss_set(&tracemalloc_reentrant_key, NULL); + } +} + +#else + +/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */ +static int tracemalloc_reentrant = 0; + +static int +get_reentrant(void) +{ + return tracemalloc_reentrant; +} + +static void +set_reentrant(int reentrant) +{ + assert(reentrant != tracemalloc_reentrant); + tracemalloc_reentrant = reentrant; +} +#endif + + +static Py_uhash_t +hashtable_hash_pyobject(const void *key) +{ + PyObject *obj = (PyObject *)key; + return PyObject_Hash(obj); +} + + +static int +hashtable_compare_unicode(const void *key1, const void *key2) +{ + PyObject *obj1 = (PyObject *)key1; + PyObject *obj2 = (PyObject *)key2; + if (obj1 != NULL && obj2 != NULL) { + return (PyUnicode_Compare(obj1, obj2) == 0); + } + else { + return obj1 == obj2; + } +} + + +static Py_uhash_t +hashtable_hash_uint(const void *key_raw) +{ + unsigned int key = (unsigned int)FROM_PTR(key_raw); + return (Py_uhash_t)key; +} + + +static _Py_hashtable_t * +hashtable_new(_Py_hashtable_hash_func hash_func, + _Py_hashtable_compare_func compare_func, + _Py_hashtable_destroy_func key_destroy_func, + _Py_hashtable_destroy_func value_destroy_func) +{ + _Py_hashtable_allocator_t hashtable_alloc = {malloc, free}; + return _Py_hashtable_new_full(hash_func, compare_func, + key_destroy_func, value_destroy_func, + &hashtable_alloc); +} + + +static void* +raw_malloc(size_t size) +{ + return allocators.raw.malloc(allocators.raw.ctx, size); +} + +static void +raw_free(void *ptr) +{ + allocators.raw.free(allocators.raw.ctx, ptr); +} + + +static Py_uhash_t +hashtable_hash_traceback(const void *key) +{ + const traceback_t *traceback = (const traceback_t *)key; + return traceback->hash; +} + + +static int +hashtable_compare_traceback(const void *key1, const void *key2) +{ + const traceback_t *traceback1 = (const traceback_t *)key1; + const traceback_t *traceback2 = (const traceback_t *)key2; + + if (traceback1->nframe != traceback2->nframe) { + return 0; + } + if (traceback1->total_nframe != traceback2->total_nframe) { + return 0; + } + + for (int i=0; i < traceback1->nframe; i++) { + const frame_t *frame1 = &traceback1->frames[i]; + const frame_t *frame2 = &traceback2->frames[i]; + + if (frame1->lineno != frame2->lineno) { + return 0; + } + if (frame1->filename != frame2->filename) { + assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0); + return 0; + } + } + return 1; +} + + +static void +tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame) +{ + frame->filename = &_Py_STR(anon_unknown); + int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe); + if (lineno < 0) { + lineno = 0; + } + frame->lineno = (unsigned int)lineno; + + PyObject *filename = pyframe->f_code->co_filename; + + if (filename == NULL) { +#ifdef TRACE_DEBUG + tracemalloc_error("failed to get the filename of the code object"); +#endif + return; + } + + if (!PyUnicode_Check(filename)) { +#ifdef TRACE_DEBUG + tracemalloc_error("filename is not a unicode string"); +#endif + return; + } + if (!PyUnicode_IS_READY(filename)) { + /* Don't make a Unicode string ready to avoid reentrant calls + to tracemalloc_malloc() or tracemalloc_realloc() */ +#ifdef TRACE_DEBUG + tracemalloc_error("filename is not a ready unicode string"); +#endif + return; + } + + /* intern the filename */ + _Py_hashtable_entry_t *entry; + entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename); + if (entry != NULL) { + filename = (PyObject *)entry->key; + } + else { + /* tracemalloc_filenames is responsible to keep a reference + to the filename */ + if (_Py_hashtable_set(tracemalloc_filenames, Py_NewRef(filename), + NULL) < 0) { + Py_DECREF(filename); +#ifdef TRACE_DEBUG + tracemalloc_error("failed to intern the filename"); +#endif + return; + } + } + + /* the tracemalloc_filenames table keeps a reference to the filename */ + frame->filename = filename; +} + + +static Py_uhash_t +traceback_hash(traceback_t *traceback) +{ + /* code based on tuplehash() of Objects/tupleobject.c */ + Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */ + int len = traceback->nframe; + Py_uhash_t mult = _PyHASH_MULTIPLIER; + frame_t *frame; + + x = 0x345678UL; + frame = traceback->frames; + while (--len >= 0) { + y = (Py_uhash_t)PyObject_Hash(frame->filename); + y ^= (Py_uhash_t)frame->lineno; + frame++; + + x = (x ^ y) * mult; + /* the cast might truncate len; that doesn't change hash stability */ + mult += (Py_uhash_t)(82520UL + len + len); + } + x ^= traceback->total_nframe; + x += 97531UL; + return x; +} + + +static void +traceback_get_frames(traceback_t *traceback) +{ + PyThreadState *tstate = PyGILState_GetThisThreadState(); + if (tstate == NULL) { +#ifdef TRACE_DEBUG + tracemalloc_error("failed to get the current thread state"); +#endif + return; + } + + _PyInterpreterFrame *pyframe = _PyThreadState_GetFrame(tstate); + while (pyframe) { + if (traceback->nframe < tracemalloc_config.max_nframe) { + tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]); + assert(traceback->frames[traceback->nframe].filename != NULL); + traceback->nframe++; + } + if (traceback->total_nframe < UINT16_MAX) { + traceback->total_nframe++; + } + pyframe = _PyFrame_GetFirstComplete(pyframe->previous); + } +} + + +static traceback_t * +traceback_new(void) +{ + traceback_t *traceback; + _Py_hashtable_entry_t *entry; + + assert(PyGILState_Check()); + + /* get frames */ + traceback = tracemalloc_traceback; + traceback->nframe = 0; + traceback->total_nframe = 0; + traceback_get_frames(traceback); + if (traceback->nframe == 0) + return &tracemalloc_empty_traceback; + traceback->hash = traceback_hash(traceback); + + /* intern the traceback */ + entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback); + if (entry != NULL) { + traceback = (traceback_t *)entry->key; + } + else { + traceback_t *copy; + size_t traceback_size; + + traceback_size = TRACEBACK_SIZE(traceback->nframe); + + copy = raw_malloc(traceback_size); + if (copy == NULL) { +#ifdef TRACE_DEBUG + tracemalloc_error("failed to intern the traceback: malloc failed"); +#endif + return NULL; + } + memcpy(copy, traceback, traceback_size); + + if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL) < 0) { + raw_free(copy); +#ifdef TRACE_DEBUG + tracemalloc_error("failed to intern the traceback: putdata failed"); +#endif + return NULL; + } + traceback = copy; + } + return traceback; +} + + +static _Py_hashtable_t* +tracemalloc_create_traces_table(void) +{ + return hashtable_new(_Py_hashtable_hash_ptr, + _Py_hashtable_compare_direct, + NULL, raw_free); +} + + +static _Py_hashtable_t* +tracemalloc_create_domains_table(void) +{ + return hashtable_new(hashtable_hash_uint, + _Py_hashtable_compare_direct, + NULL, + (_Py_hashtable_destroy_func)_Py_hashtable_destroy); +} + + +static _Py_hashtable_t* +tracemalloc_get_traces_table(unsigned int domain) +{ + if (domain == DEFAULT_DOMAIN) { + return tracemalloc_traces; + } + else { + return _Py_hashtable_get(tracemalloc_domains, TO_PTR(domain)); + } +} + + +static void +tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr) +{ + assert(tracemalloc_config.tracing); + + _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); + if (!traces) { + return; + } + + trace_t *trace = _Py_hashtable_steal(traces, TO_PTR(ptr)); + if (!trace) { + return; + } + assert(tracemalloc_traced_memory >= trace->size); + tracemalloc_traced_memory -= trace->size; + raw_free(trace); +} + +#define REMOVE_TRACE(ptr) \ + tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr)) + + +static int +tracemalloc_add_trace(unsigned int domain, uintptr_t ptr, + size_t size) +{ + assert(tracemalloc_config.tracing); + + traceback_t *traceback = traceback_new(); + if (traceback == NULL) { + return -1; + } + + _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); + if (traces == NULL) { + traces = tracemalloc_create_traces_table(); + if (traces == NULL) { + return -1; + } + + if (_Py_hashtable_set(tracemalloc_domains, TO_PTR(domain), traces) < 0) { + _Py_hashtable_destroy(traces); + return -1; + } + } + + trace_t *trace = _Py_hashtable_get(traces, TO_PTR(ptr)); + if (trace != NULL) { + /* the memory block is already tracked */ + assert(tracemalloc_traced_memory >= trace->size); + tracemalloc_traced_memory -= trace->size; + + trace->size = size; + trace->traceback = traceback; + } + else { + trace = raw_malloc(sizeof(trace_t)); + if (trace == NULL) { + return -1; + } + trace->size = size; + trace->traceback = traceback; + + int res = _Py_hashtable_set(traces, TO_PTR(ptr), trace); + if (res != 0) { + raw_free(trace); + return res; + } + } + + assert(tracemalloc_traced_memory <= SIZE_MAX - size); + tracemalloc_traced_memory += size; + if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory) { + tracemalloc_peak_traced_memory = tracemalloc_traced_memory; + } + return 0; +} + +#define ADD_TRACE(ptr, size) \ + tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size) + + +static void* +tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize) +{ + PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; + void *ptr; + + assert(elsize == 0 || nelem <= SIZE_MAX / elsize); + + if (use_calloc) + ptr = alloc->calloc(alloc->ctx, nelem, elsize); + else + ptr = alloc->malloc(alloc->ctx, nelem * elsize); + if (ptr == NULL) + return NULL; + + TABLES_LOCK(); + if (ADD_TRACE(ptr, nelem * elsize) < 0) { + /* Failed to allocate a trace for the new memory block */ + TABLES_UNLOCK(); + alloc->free(alloc->ctx, ptr); + return NULL; + } + TABLES_UNLOCK(); + return ptr; +} + + +static void* +tracemalloc_realloc(void *ctx, void *ptr, size_t new_size) +{ + PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; + void *ptr2; + + ptr2 = alloc->realloc(alloc->ctx, ptr, new_size); + if (ptr2 == NULL) + return NULL; + + if (ptr != NULL) { + /* an existing memory block has been resized */ + + TABLES_LOCK(); + + /* tracemalloc_add_trace() updates the trace if there is already + a trace at address ptr2 */ + if (ptr2 != ptr) { + REMOVE_TRACE(ptr); + } + + if (ADD_TRACE(ptr2, new_size) < 0) { + /* Memory allocation failed. The error cannot be reported to + the caller, because realloc() may already have shrunk the + memory block and so removed bytes. + + This case is very unlikely: a hash entry has just been + released, so the hash table should have at least one free entry. + + The GIL and the table lock ensures that only one thread is + allocating memory. */ + Py_FatalError("tracemalloc_realloc() failed to allocate a trace"); + } + TABLES_UNLOCK(); + } + else { + /* new allocation */ + + TABLES_LOCK(); + if (ADD_TRACE(ptr2, new_size) < 0) { + /* Failed to allocate a trace for the new memory block */ + TABLES_UNLOCK(); + alloc->free(alloc->ctx, ptr2); + return NULL; + } + TABLES_UNLOCK(); + } + return ptr2; +} + + +static void +tracemalloc_free(void *ctx, void *ptr) +{ + PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; + + if (ptr == NULL) + return; + + /* GIL cannot be locked in PyMem_RawFree() because it would introduce + a deadlock in _PyThreadState_DeleteCurrent(). */ + + alloc->free(alloc->ctx, ptr); + + TABLES_LOCK(); + REMOVE_TRACE(ptr); + TABLES_UNLOCK(); +} + + +static void* +tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize) +{ + void *ptr; + + if (get_reentrant()) { + PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; + if (use_calloc) + return alloc->calloc(alloc->ctx, nelem, elsize); + else + return alloc->malloc(alloc->ctx, nelem * elsize); + } + + /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for + allocations larger than 512 bytes, don't trace the same memory + allocation twice. */ + set_reentrant(1); + + ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize); + + set_reentrant(0); + return ptr; +} + + +static void* +tracemalloc_malloc_gil(void *ctx, size_t size) +{ + return tracemalloc_alloc_gil(0, ctx, 1, size); +} + + +static void* +tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize) +{ + return tracemalloc_alloc_gil(1, ctx, nelem, elsize); +} + + +static void* +tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size) +{ + void *ptr2; + + if (get_reentrant()) { + /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc(). + Example: PyMem_RawRealloc() is called internally by pymalloc + (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new + arena (new_arena()). */ + PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; + + ptr2 = alloc->realloc(alloc->ctx, ptr, new_size); + if (ptr2 != NULL && ptr != NULL) { + TABLES_LOCK(); + REMOVE_TRACE(ptr); + TABLES_UNLOCK(); + } + return ptr2; + } + + /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for + allocations larger than 512 bytes. Don't trace the same memory + allocation twice. */ + set_reentrant(1); + + ptr2 = tracemalloc_realloc(ctx, ptr, new_size); + + set_reentrant(0); + return ptr2; +} + + +#ifdef TRACE_RAW_MALLOC +static void* +tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize) +{ + PyGILState_STATE gil_state; + void *ptr; + + if (get_reentrant()) { + PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; + if (use_calloc) + return alloc->calloc(alloc->ctx, nelem, elsize); + else + return alloc->malloc(alloc->ctx, nelem * elsize); + } + + /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc() + indirectly which would call PyGILState_Ensure() if reentrant are not + disabled. */ + set_reentrant(1); + + gil_state = PyGILState_Ensure(); + ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize); + PyGILState_Release(gil_state); + + set_reentrant(0); + return ptr; +} + + +static void* +tracemalloc_raw_malloc(void *ctx, size_t size) +{ + return tracemalloc_raw_alloc(0, ctx, 1, size); +} + + +static void* +tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize) +{ + return tracemalloc_raw_alloc(1, ctx, nelem, elsize); +} + + +static void* +tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size) +{ + PyGILState_STATE gil_state; + void *ptr2; + + if (get_reentrant()) { + /* Reentrant call to PyMem_RawRealloc(). */ + PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx; + + ptr2 = alloc->realloc(alloc->ctx, ptr, new_size); + + if (ptr2 != NULL && ptr != NULL) { + TABLES_LOCK(); + REMOVE_TRACE(ptr); + TABLES_UNLOCK(); + } + return ptr2; + } + + /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc() + indirectly which would call PyGILState_Ensure() if reentrant calls are + not disabled. */ + set_reentrant(1); + + gil_state = PyGILState_Ensure(); + ptr2 = tracemalloc_realloc(ctx, ptr, new_size); + PyGILState_Release(gil_state); + + set_reentrant(0); + return ptr2; +} +#endif /* TRACE_RAW_MALLOC */ + + +static void +tracemalloc_clear_filename(void *value) +{ + PyObject *filename = (PyObject *)value; + Py_DECREF(filename); +} + + +/* reentrant flag must be set to call this function and GIL must be held */ +static void +tracemalloc_clear_traces(void) +{ + /* The GIL protects variables against concurrent access */ + assert(PyGILState_Check()); + + TABLES_LOCK(); + _Py_hashtable_clear(tracemalloc_traces); + _Py_hashtable_clear(tracemalloc_domains); + tracemalloc_traced_memory = 0; + tracemalloc_peak_traced_memory = 0; + TABLES_UNLOCK(); + + _Py_hashtable_clear(tracemalloc_tracebacks); + + _Py_hashtable_clear(tracemalloc_filenames); +} + + +int +_PyTraceMalloc_Init(void) +{ + if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) { + PyErr_SetString(PyExc_RuntimeError, + "the tracemalloc module has been unloaded"); + return -1; + } + + if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED) + return 0; + + PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); + +#ifdef REENTRANT_THREADLOCAL + if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) { +#ifdef MS_WINDOWS + PyErr_SetFromWindowsErr(0); +#else + PyErr_SetFromErrno(PyExc_OSError); +#endif + return -1; + } +#endif + +#if defined(TRACE_RAW_MALLOC) + if (tables_lock == NULL) { + tables_lock = PyThread_allocate_lock(); + if (tables_lock == NULL) { + PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock"); + return -1; + } + } +#endif + + tracemalloc_filenames = hashtable_new(hashtable_hash_pyobject, + hashtable_compare_unicode, + tracemalloc_clear_filename, NULL); + + tracemalloc_tracebacks = hashtable_new(hashtable_hash_traceback, + hashtable_compare_traceback, + NULL, raw_free); + + tracemalloc_traces = tracemalloc_create_traces_table(); + tracemalloc_domains = tracemalloc_create_domains_table(); + + if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL + || tracemalloc_traces == NULL || tracemalloc_domains == NULL) { + PyErr_NoMemory(); + return -1; + } + + tracemalloc_empty_traceback.nframe = 1; + tracemalloc_empty_traceback.total_nframe = 1; + /* borrowed reference */ + tracemalloc_empty_traceback.frames[0].filename = &_Py_STR(anon_unknown); + tracemalloc_empty_traceback.frames[0].lineno = 0; + tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback); + + tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED; + return 0; +} + + +static void +tracemalloc_deinit(void) +{ + if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED) + return; + tracemalloc_config.initialized = TRACEMALLOC_FINALIZED; + + _PyTraceMalloc_Stop(); + + /* destroy hash tables */ + _Py_hashtable_destroy(tracemalloc_domains); + _Py_hashtable_destroy(tracemalloc_traces); + _Py_hashtable_destroy(tracemalloc_tracebacks); + _Py_hashtable_destroy(tracemalloc_filenames); + +#if defined(TRACE_RAW_MALLOC) + if (tables_lock != NULL) { + PyThread_free_lock(tables_lock); + tables_lock = NULL; + } +#endif + +#ifdef REENTRANT_THREADLOCAL + PyThread_tss_delete(&tracemalloc_reentrant_key); +#endif +} + + +int +_PyTraceMalloc_Start(int max_nframe) +{ + PyMemAllocatorEx alloc; + size_t size; + + if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) { + PyErr_Format(PyExc_ValueError, + "the number of frames must be in range [1; %lu]", + MAX_NFRAME); + return -1; + } + + if (_PyTraceMalloc_Init() < 0) { + return -1; + } + + if (tracemalloc_config.tracing) { + /* hook already installed: do nothing */ + return 0; + } + + tracemalloc_config.max_nframe = max_nframe; + + /* allocate a buffer to store a new traceback */ + size = TRACEBACK_SIZE(max_nframe); + assert(tracemalloc_traceback == NULL); + tracemalloc_traceback = raw_malloc(size); + if (tracemalloc_traceback == NULL) { + PyErr_NoMemory(); + return -1; + } + +#ifdef TRACE_RAW_MALLOC + alloc.malloc = tracemalloc_raw_malloc; + alloc.calloc = tracemalloc_raw_calloc; + alloc.realloc = tracemalloc_raw_realloc; + alloc.free = tracemalloc_free; + + alloc.ctx = &allocators.raw; + PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc); +#endif + + alloc.malloc = tracemalloc_malloc_gil; + alloc.calloc = tracemalloc_calloc_gil; + alloc.realloc = tracemalloc_realloc_gil; + alloc.free = tracemalloc_free; + + alloc.ctx = &allocators.mem; + PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem); + PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc); + + alloc.ctx = &allocators.obj; + PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj); + PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc); + + /* everything is ready: start tracing Python memory allocations */ + tracemalloc_config.tracing = 1; + + return 0; +} + + +void +_PyTraceMalloc_Stop(void) +{ + if (!tracemalloc_config.tracing) + return; + + /* stop tracing Python memory allocations */ + tracemalloc_config.tracing = 0; + + /* unregister the hook on memory allocators */ +#ifdef TRACE_RAW_MALLOC + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); +#endif + PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem); + PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj); + + tracemalloc_clear_traces(); + + /* release memory */ + raw_free(tracemalloc_traceback); + tracemalloc_traceback = NULL; +} + + + +static PyObject* +frame_to_pyobject(frame_t *frame) +{ + PyObject *frame_obj, *lineno_obj; + + frame_obj = PyTuple_New(2); + if (frame_obj == NULL) + return NULL; + + PyTuple_SET_ITEM(frame_obj, 0, Py_NewRef(frame->filename)); + + lineno_obj = PyLong_FromUnsignedLong(frame->lineno); + if (lineno_obj == NULL) { + Py_DECREF(frame_obj); + return NULL; + } + PyTuple_SET_ITEM(frame_obj, 1, lineno_obj); + + return frame_obj; +} + + +static PyObject* +traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) +{ + PyObject *frames; + + if (intern_table != NULL) { + frames = _Py_hashtable_get(intern_table, (const void *)traceback); + if (frames) { + return Py_NewRef(frames); + } + } + + frames = PyTuple_New(traceback->nframe); + if (frames == NULL) + return NULL; + + for (int i=0; i < traceback->nframe; i++) { + PyObject *frame = frame_to_pyobject(&traceback->frames[i]); + if (frame == NULL) { + Py_DECREF(frames); + return NULL; + } + PyTuple_SET_ITEM(frames, i, frame); + } + + if (intern_table != NULL) { + if (_Py_hashtable_set(intern_table, traceback, frames) < 0) { + Py_DECREF(frames); + PyErr_NoMemory(); + return NULL; + } + /* intern_table keeps a new reference to frames */ + Py_INCREF(frames); + } + return frames; +} + + +static PyObject* +trace_to_pyobject(unsigned int domain, const trace_t *trace, + _Py_hashtable_t *intern_tracebacks) +{ + PyObject *trace_obj = NULL; + PyObject *obj; + + trace_obj = PyTuple_New(4); + if (trace_obj == NULL) + return NULL; + + obj = PyLong_FromSize_t(domain); + if (obj == NULL) { + Py_DECREF(trace_obj); + return NULL; + } + PyTuple_SET_ITEM(trace_obj, 0, obj); + + obj = PyLong_FromSize_t(trace->size); + if (obj == NULL) { + Py_DECREF(trace_obj); + return NULL; + } + PyTuple_SET_ITEM(trace_obj, 1, obj); + + obj = traceback_to_pyobject(trace->traceback, intern_tracebacks); + if (obj == NULL) { + Py_DECREF(trace_obj); + return NULL; + } + PyTuple_SET_ITEM(trace_obj, 2, obj); + + obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe); + if (obj == NULL) { + Py_DECREF(trace_obj); + return NULL; + } + PyTuple_SET_ITEM(trace_obj, 3, obj); + + return trace_obj; +} + + +typedef struct { + _Py_hashtable_t *traces; + _Py_hashtable_t *domains; + _Py_hashtable_t *tracebacks; + PyObject *list; + unsigned int domain; +} get_traces_t; + + +static int +tracemalloc_copy_trace(_Py_hashtable_t *traces, + const void *key, const void *value, + void *user_data) +{ + _Py_hashtable_t *traces2 = (_Py_hashtable_t *)user_data; + + trace_t *trace = (trace_t *)value; + + trace_t *trace2 = raw_malloc(sizeof(trace_t)); + if (trace2 == NULL) { + return -1; + } + *trace2 = *trace; + if (_Py_hashtable_set(traces2, key, trace2) < 0) { + raw_free(trace2); + return -1; + } + return 0; +} + + +static _Py_hashtable_t* +tracemalloc_copy_traces(_Py_hashtable_t *traces) +{ + _Py_hashtable_t *traces2 = tracemalloc_create_traces_table(); + if (traces2 == NULL) { + return NULL; + } + + int err = _Py_hashtable_foreach(traces, + tracemalloc_copy_trace, + traces2); + if (err) { + _Py_hashtable_destroy(traces2); + return NULL; + } + return traces2; +} + + +static int +tracemalloc_copy_domain(_Py_hashtable_t *domains, + const void *key, const void *value, + void *user_data) +{ + _Py_hashtable_t *domains2 = (_Py_hashtable_t *)user_data; + + unsigned int domain = (unsigned int)FROM_PTR(key); + _Py_hashtable_t *traces = (_Py_hashtable_t *)value; + + _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces); + if (traces2 == NULL) { + return -1; + } + if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) { + _Py_hashtable_destroy(traces2); + return -1; + } + return 0; +} + + +static _Py_hashtable_t* +tracemalloc_copy_domains(_Py_hashtable_t *domains) +{ + _Py_hashtable_t *domains2 = tracemalloc_create_domains_table(); + if (domains2 == NULL) { + return NULL; + } + + int err = _Py_hashtable_foreach(domains, + tracemalloc_copy_domain, + domains2); + if (err) { + _Py_hashtable_destroy(domains2); + return NULL; + } + return domains2; +} + + +static int +tracemalloc_get_traces_fill(_Py_hashtable_t *traces, + const void *key, const void *value, + void *user_data) +{ + get_traces_t *get_traces = user_data; + + const trace_t *trace = (const trace_t *)value; + + PyObject *tuple = trace_to_pyobject(get_traces->domain, trace, + get_traces->tracebacks); + if (tuple == NULL) { + return 1; + } + + int res = PyList_Append(get_traces->list, tuple); + Py_DECREF(tuple); + if (res < 0) { + return 1; + } + + return 0; +} + + +static int +tracemalloc_get_traces_domain(_Py_hashtable_t *domains, + const void *key, const void *value, + void *user_data) +{ + get_traces_t *get_traces = user_data; + + unsigned int domain = (unsigned int)FROM_PTR(key); + _Py_hashtable_t *traces = (_Py_hashtable_t *)value; + + get_traces->domain = domain; + return _Py_hashtable_foreach(traces, + tracemalloc_get_traces_fill, + get_traces); +} + + +static void +tracemalloc_pyobject_decref(void *value) +{ + PyObject *obj = (PyObject *)value; + Py_DECREF(obj); +} + + +static traceback_t* +tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr) +{ + + if (!tracemalloc_config.tracing) + return NULL; + + trace_t *trace; + TABLES_LOCK(); + _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); + if (traces) { + trace = _Py_hashtable_get(traces, TO_PTR(ptr)); + } + else { + trace = NULL; + } + TABLES_UNLOCK(); + + if (!trace) { + return NULL; + } + + return trace->traceback; +} + + +#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) + +static void +_PyMem_DumpFrame(int fd, frame_t * frame) +{ + PUTS(fd, " File \""); + _Py_DumpASCII(fd, frame->filename); + PUTS(fd, "\", line "); + _Py_DumpDecimal(fd, frame->lineno); + PUTS(fd, "\n"); +} + +/* Dump the traceback where a memory block was allocated into file descriptor + fd. The function may block on TABLES_LOCK() but it is unlikely. */ +void +_PyMem_DumpTraceback(int fd, const void *ptr) +{ + traceback_t *traceback; + int i; + + if (!tracemalloc_config.tracing) { + PUTS(fd, "Enable tracemalloc to get the memory block " + "allocation traceback\n\n"); + return; + } + + traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr); + if (traceback == NULL) + return; + + PUTS(fd, "Memory block allocated at (most recent call first):\n"); + for (i=0; i < traceback->nframe; i++) { + _PyMem_DumpFrame(fd, &traceback->frames[i]); + } + PUTS(fd, "\n"); +} + +#undef PUTS + + +static int +tracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains, + const void *key, const void *value, + void *user_data) +{ + const _Py_hashtable_t *traces = value; + size_t *size = (size_t*)user_data; + *size += _Py_hashtable_size(traces); + return 0; +} + +int +PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, + size_t size) +{ + int res; + PyGILState_STATE gil_state; + + if (!tracemalloc_config.tracing) { + /* tracemalloc is not tracing: do nothing */ + return -2; + } + + gil_state = PyGILState_Ensure(); + + TABLES_LOCK(); + res = tracemalloc_add_trace(domain, ptr, size); + TABLES_UNLOCK(); + + PyGILState_Release(gil_state); + return res; +} + + +int +PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr) +{ + if (!tracemalloc_config.tracing) { + /* tracemalloc is not tracing: do nothing */ + return -2; + } + + TABLES_LOCK(); + tracemalloc_remove_trace(domain, ptr); + TABLES_UNLOCK(); + + return 0; +} + + +void +_PyTraceMalloc_Fini(void) +{ + assert(PyGILState_Check()); + tracemalloc_deinit(); +} + + +/* If the object memory block is already traced, update its trace + with the current Python traceback. + + Do nothing if tracemalloc is not tracing memory allocations + or if the object memory block is not already traced. */ +int +_PyTraceMalloc_NewReference(PyObject *op) +{ + assert(PyGILState_Check()); + + if (!tracemalloc_config.tracing) { + /* tracemalloc is not tracing: do nothing */ + return -1; + } + + PyTypeObject *type = Py_TYPE(op); + const size_t presize = _PyType_PreHeaderSize(type); + uintptr_t ptr = (uintptr_t)((char *)op - presize); + + int res = -1; + + TABLES_LOCK(); + trace_t *trace = _Py_hashtable_get(tracemalloc_traces, TO_PTR(ptr)); + if (trace != NULL) { + /* update the traceback of the memory block */ + traceback_t *traceback = traceback_new(); + if (traceback != NULL) { + trace->traceback = traceback; + res = 0; + } + } + /* else: cannot track the object, its memory block size is unknown */ + TABLES_UNLOCK(); + + return res; +} + + +PyObject* +_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr) +{ + traceback_t *traceback; + + traceback = tracemalloc_get_traceback(domain, ptr); + if (traceback == NULL) + Py_RETURN_NONE; + + return traceback_to_pyobject(traceback, NULL); +} + +int +_PyTraceMalloc_IsTracing(void) +{ + return tracemalloc_config.tracing; +} + +void +_PyTraceMalloc_ClearTraces(void) +{ + + if (!tracemalloc_config.tracing) { + return; + } + set_reentrant(1); + tracemalloc_clear_traces(); + set_reentrant(0); +} + +PyObject * +_PyTraceMalloc_GetTraces(void) +{ + get_traces_t get_traces; + get_traces.domain = DEFAULT_DOMAIN; + get_traces.traces = NULL; + get_traces.domains = NULL; + get_traces.tracebacks = NULL; + get_traces.list = PyList_New(0); + if (get_traces.list == NULL) + goto error; + + if (!tracemalloc_config.tracing) + return get_traces.list; + + /* the traceback hash table is used temporarily to intern traceback tuple + of (filename, lineno) tuples */ + get_traces.tracebacks = hashtable_new(_Py_hashtable_hash_ptr, + _Py_hashtable_compare_direct, + NULL, tracemalloc_pyobject_decref); + if (get_traces.tracebacks == NULL) { + goto no_memory; + } + + // Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable + // temporarily tracemalloc which would impact other threads and so would + // miss allocations while get_traces() is called. + TABLES_LOCK(); + get_traces.traces = tracemalloc_copy_traces(tracemalloc_traces); + TABLES_UNLOCK(); + + if (get_traces.traces == NULL) { + goto no_memory; + } + + TABLES_LOCK(); + get_traces.domains = tracemalloc_copy_domains(tracemalloc_domains); + TABLES_UNLOCK(); + + if (get_traces.domains == NULL) { + goto no_memory; + } + + // Convert traces to a list of tuples + set_reentrant(1); + int err = _Py_hashtable_foreach(get_traces.traces, + tracemalloc_get_traces_fill, + &get_traces); + if (!err) { + err = _Py_hashtable_foreach(get_traces.domains, + tracemalloc_get_traces_domain, + &get_traces); + } + set_reentrant(0); + if (err) { + goto error; + } + + goto finally; + +no_memory: + PyErr_NoMemory(); + +error: + Py_CLEAR(get_traces.list); + +finally: + if (get_traces.tracebacks != NULL) { + _Py_hashtable_destroy(get_traces.tracebacks); + } + if (get_traces.traces != NULL) { + _Py_hashtable_destroy(get_traces.traces); + } + if (get_traces.domains != NULL) { + _Py_hashtable_destroy(get_traces.domains); + } + + return get_traces.list; +} + +PyObject * +_PyTraceMalloc_GetObjectTraceback(PyObject *obj) +/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/ +{ + PyTypeObject *type; + traceback_t *traceback; + + type = Py_TYPE(obj); + const size_t presize = _PyType_PreHeaderSize(type); + uintptr_t ptr = (uintptr_t)((char *)obj - presize); + + traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, ptr); + if (traceback == NULL) { + Py_RETURN_NONE; + } + + return traceback_to_pyobject(traceback, NULL); +} + +int _PyTraceMalloc_GetTracebackLimit(void) { + return tracemalloc_config.max_nframe; +} + +size_t +_PyTraceMalloc_GetMemory(void) { + + size_t size; + + size = _Py_hashtable_size(tracemalloc_tracebacks); + size += _Py_hashtable_size(tracemalloc_filenames); + + TABLES_LOCK(); + size += _Py_hashtable_size(tracemalloc_traces); + _Py_hashtable_foreach(tracemalloc_domains, + tracemalloc_get_tracemalloc_memory_cb, &size); + TABLES_UNLOCK(); + return size; +} + + +PyObject * +_PyTraceMalloc_GetTracedMemory(void) +{ + Py_ssize_t size, peak_size; + + if (!tracemalloc_config.tracing) + return Py_BuildValue("ii", 0, 0); + + TABLES_LOCK(); + size = tracemalloc_traced_memory; + peak_size = tracemalloc_peak_traced_memory; + TABLES_UNLOCK(); + + return Py_BuildValue("nn", size, peak_size); +} + +void +_PyTraceMalloc_ResetPeak(void) +{ + if (!tracemalloc_config.tracing) { + return; + } + TABLES_LOCK(); + tracemalloc_peak_traced_memory = tracemalloc_traced_memory; + TABLES_UNLOCK(); +} diff --git a/README.rst b/README.rst index 06c4f0a1fa3917..4a4c8ab65dceff 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -This is Python version 3.12.0 alpha 7 +This is Python version 3.13.0 alpha 0 ===================================== .. image:: https://github.com/python/cpython/workflows/Tests/badge.svg @@ -133,7 +133,7 @@ What's New ---------- We have a comprehensive overview of the changes in the `What's New in Python -3.12 `_ document. For a more +3.13 `_ document. For a more detailed change log, read `Misc/NEWS `_, but a full accounting of changes can only be gleaned from the `commit history @@ -146,7 +146,7 @@ entitled "Installing multiple versions". Documentation ------------- -`Documentation for Python 3.12 `_ is online, +`Documentation for Python 3.13 `_ is online, updated daily. It can also be downloaded in many formats for faster access. The documentation @@ -206,8 +206,8 @@ intend to install multiple versions using the same prefix you must decide which version (if any) is your "primary" version. Install that version using ``make install``. Install all other versions using ``make altinstall``. -For example, if you want to install Python 2.7, 3.6, and 3.12 with 3.12 being the -primary version, you would execute ``make install`` in your 3.12 build directory +For example, if you want to install Python 2.7, 3.6, and 3.13 with 3.13 being the +primary version, you would execute ``make install`` in your 3.13 build directory and ``make altinstall`` in the others. @@ -238,7 +238,7 @@ All current PEPs, as well as guidelines for submitting a new PEP, are listed at Release Schedule ---------------- -See :pep:`693` for Python 3.12 release details. +See :pep:`XXX` for Python 3.13 release details. Copyright and License Information diff --git a/Tools/README b/Tools/README index e51624f453c5bb..9c4b6d86e990ba 100644 --- a/Tools/README +++ b/Tools/README @@ -39,10 +39,8 @@ patchcheck Tools for checking and applying patches to the Python source cod peg_generator PEG-based parser generator (pegen) used for new parser. -scripts A number of useful single-file programs, e.g. tabnanny.py - by Tim Peters, which checks for inconsistent mixing of - tabs and spaces, and 2to3, which converts Python 2 code - to Python 3 code. +scripts A number of useful single-file programs, e.g. run_tests.py + which runs the Python test suite. ssl Scripts to generate ssl_data.h from OpenSSL sources, and run tests against multiple installations of OpenSSL and LibreSSL. diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 9863acdade308b..622c98d16283a8 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -90,6 +90,7 @@ Objects/typeobject.c - _PyBufferWrapper_Type - Objects/typeobject.c - PyBaseObject_Type - Objects/typeobject.c - PySuper_Type - Objects/typeobject.c - PyType_Type - +Objects/typevarobject.c - _PyTypeAlias_Type - Objects/unicodeobject.c - PyUnicodeIter_Type - Objects/unicodeobject.c - PyUnicode_Type - Objects/weakrefobject.c - _PyWeakref_CallableProxyType - @@ -458,7 +459,6 @@ Modules/_tkinter.c - trbInCmd - ## pre-allocated buffer Modules/nismodule.c nisproc_maplist_2 res - -Modules/pyexpat.c PyUnknownEncodingHandler template_buffer - ## other Include/datetime.h - PyDateTimeAPI - diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 7ba116dcb171cf..e9056aed5dc0b2 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -356,6 +356,7 @@ Python/pystate.c - initial - Python/specialize.c - adaptive_opcodes - Python/specialize.c - cache_requirements - Python/stdlib_module_names.h - _Py_stdlib_module_names - +Python/sysmodule.c - perf_map_state - Python/sysmodule.c - _PySys_ImplCacheTag - Python/sysmodule.c - _PySys_ImplName - Python/sysmodule.c - whatstrings - diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py index 4270fb3cc56613..d182e5e7764e46 100755 --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -12,6 +12,7 @@ import contextlib import copy import cpp +import enum import functools import hashlib import inspect @@ -25,11 +26,10 @@ import sys import textwrap import traceback -import types from collections.abc import Callable -from types import * -from typing import Any, NamedTuple +from types import FunctionType, NoneType +from typing import Any, Final, NamedTuple, NoReturn, Literal, overload # TODO: # @@ -59,38 +59,40 @@ "return_value", } -class Unspecified: - def __repr__(self): - return '' -unspecified = Unspecified() +class Sentinels(enum.Enum): + unspecified = "unspecified" + unknown = "unknown" + def __repr__(self) -> str: + return f"<{self.value.capitalize()}>" -class Null: - def __repr__(self): - return '' -NULL = Null() +unspecified: Final = Sentinels.unspecified +unknown: Final = Sentinels.unknown -class Unknown: - def __repr__(self): - return '' +# This one needs to be a distinct class, unlike the other two +class Null: + def __repr__(self) -> str: + return '' + -unknown = Unknown() +NULL = Null() sig_end_marker = '--' Appender = Callable[[str], None] -Outputter = Callable[[None], str] +Outputter = Callable[[], str] +TemplateDict = dict[str, str] class _TextAccumulator(NamedTuple): text: list[str] append: Appender output: Outputter -def _text_accumulator(): - text = [] +def _text_accumulator() -> _TextAccumulator: + text: list[str] = [] def output(): s = ''.join(text) text.clear() @@ -99,10 +101,10 @@ def output(): class TextAccumulator(NamedTuple): - text: list[str] append: Appender + output: Outputter -def text_accumulator(): +def text_accumulator() -> TextAccumulator: """ Creates a simple text accumulator / joiner. @@ -116,8 +118,28 @@ def text_accumulator(): text, append, output = _text_accumulator() return TextAccumulator(append, output) - -def warn_or_fail(fail=False, *args, filename=None, line_number=None): +@overload +def warn_or_fail( + *args: object, + fail: Literal[True], + filename: str | None = None, + line_number: int | None = None, +) -> NoReturn: ... + +@overload +def warn_or_fail( + *args: object, + fail: Literal[False] = False, + filename: str | None = None, + line_number: int | None = None, +) -> None: ... + +def warn_or_fail( + *args: object, + fail: bool = False, + filename: str | None = None, + line_number: int | None = None, +) -> None: joined = " ".join([str(a) for a in args]) add, output = text_accumulator() if fail: @@ -140,14 +162,22 @@ def warn_or_fail(fail=False, *args, filename=None, line_number=None): sys.exit(-1) -def warn(*args, filename=None, line_number=None): - return warn_or_fail(False, *args, filename=filename, line_number=line_number) +def warn( + *args: object, + filename: str | None = None, + line_number: int | None = None, +) -> None: + return warn_or_fail(*args, filename=filename, line_number=line_number, fail=False) -def fail(*args, filename=None, line_number=None): - return warn_or_fail(True, *args, filename=filename, line_number=line_number) +def fail( + *args: object, + filename: str | None = None, + line_number: int | None = None, +) -> NoReturn: + warn_or_fail(*args, filename=filename, line_number=line_number, fail=True) -def quoted_for_c_string(s): +def quoted_for_c_string(s: str) -> str: for old, new in ( ('\\', '\\\\'), # must be first! ('"', '\\"'), @@ -156,13 +186,13 @@ def quoted_for_c_string(s): s = s.replace(old, new) return s -def c_repr(s): +def c_repr(s: str) -> str: return '"' + s + '"' is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match -def is_legal_py_identifier(s): +def is_legal_py_identifier(s: str) -> bool: return all(is_legal_c_identifier(field) for field in s.split('.')) # identifiers that are okay in Python but aren't a good idea in C. @@ -175,16 +205,16 @@ def is_legal_py_identifier(s): typedef typeof union unsigned void volatile while """.strip().split()) -def ensure_legal_c_identifier(s): +def ensure_legal_c_identifier(s: str) -> str: # for now, just complain if what we're given isn't legal if not is_legal_c_identifier(s): - fail("Illegal C identifier: {}".format(s)) + fail("Illegal C identifier:", s) # but if we picked a C keyword, pick something else if s in c_keywords: return s + "_value" return s -def rstrip_lines(s): +def rstrip_lines(s: str) -> str: text, add, output = _text_accumulator() for line in s.split('\n'): add(line.rstrip()) @@ -192,14 +222,14 @@ def rstrip_lines(s): text.pop() return output() -def format_escape(s): +def format_escape(s: str) -> str: # double up curly-braces, this string will be used # as part of a format_map() template later s = s.replace('{', '{{') s = s.replace('}', '}}') return s -def linear_format(s, **kwargs): +def linear_format(s: str, **kwargs: str) -> str: """ Perform str.format-like substitution, except: * The strings substituted must be on lines by @@ -243,7 +273,7 @@ def linear_format(s, **kwargs): return output()[:-1] -def indent_all_lines(s, prefix): +def indent_all_lines(s: str, prefix: str) -> str: """ Returns 's', with 'prefix' prepended to all lines. @@ -264,7 +294,7 @@ def indent_all_lines(s, prefix): final.append(last) return ''.join(final) -def suffix_all_lines(s, suffix): +def suffix_all_lines(s: str, suffix: str) -> str: """ Returns 's', with 'suffix' appended to all lines. @@ -284,7 +314,7 @@ def suffix_all_lines(s, suffix): return ''.join(final) -def version_splitter(s): +def version_splitter(s: str) -> tuple[int, ...]: """Splits a version string into a tuple of integers. The following ASCII characters are allowed, and employ @@ -294,9 +324,9 @@ def version_splitter(s): c -> -1 (This permits Python-style version strings such as "1.4b3".) """ - version = [] - accumulator = [] - def flush(): + version: list[int] = [] + accumulator: list[str] = [] + def flush() -> None: if not accumulator: raise ValueError('Unsupported version string: ' + repr(s)) version.append(int(''.join(accumulator))) @@ -315,7 +345,7 @@ def flush(): flush() return tuple(version) -def version_comparitor(version1, version2): +def version_comparitor(version1: str, version2: str) -> Literal[-1, 0, 1]: iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0) for i, (a, b) in enumerate(iterator): if a < b: @@ -518,8 +548,6 @@ def permute_optional_groups(left, required, right): If required is empty, left must also be empty. """ required = tuple(required) - result = [] - if not required: if left: raise ValueError("required is empty but left is not") @@ -963,7 +991,7 @@ def parser_body(prototype, *fields, declarations=''): argname_fmt = 'PyTuple_GET_ITEM(args, %d)' - left_args = "{} - {}".format(nargs, max_pos) + left_args = f"{nargs} - {max_pos}" max_args = NO_VARARG if (vararg != NO_VARARG) else max_pos parser_code = [normalize_snippet(""" if (!_PyArg_CheckPositional("{name}", %s, %d, %s)) {{ @@ -1308,7 +1336,6 @@ def render_option_group_parsing(self, f, template_dict): if isinstance(parameters[0].converter, self_converter): del parameters[0] - groups = [] group = None left = [] right = [] @@ -1398,8 +1425,6 @@ def render_function(self, clinic, f): first_optional = len(selfless) positional = selfless and selfless[-1].is_positional_only() new_or_init = f.kind in (METHOD_NEW, METHOD_INIT) - default_return_converter = (not f.return_converter or - f.return_converter.type == 'PyObject *') has_option_groups = False # offset i by -1 because first_optional needs to ignore self @@ -1410,7 +1435,7 @@ def render_function(self, clinic, f): first_optional = min(first_optional, i) if p.is_vararg(): - data.cleanup.append("Py_XDECREF({});".format(c.parser_name)) + data.cleanup.append(f"Py_XDECREF({c.parser_name});") # insert group variable group = p.group @@ -1462,8 +1487,7 @@ def render_function(self, clinic, f): template_dict['c_basename'] = c_basename - methoddef_name = "{}_METHODDEF".format(c_basename.upper()) - template_dict['methoddef_name'] = methoddef_name + template_dict['methoddef_name'] = c_basename.upper() + "_METHODDEF" template_dict['docstring'] = self.docstring_for_c_string(f) @@ -1496,7 +1520,6 @@ def render_function(self, clinic, f): template_dict['return_value'] = data.return_value # used by unpack tuple code generator - ignore_self = -1 if isinstance(converters[0], self_converter) else 0 unpack_min = first_optional unpack_max = len(selfless) template_dict['unpack_min'] = str(unpack_min) @@ -1717,7 +1740,7 @@ def is_stop_line(line): # make sure to recognize stop line even if it # doesn't end with EOL (it could be the very end of the file) if line.startswith(stop_line): - remainder = line[len(stop_line):] + remainder = line.removeprefix(stop_line) if remainder and not remainder.isspace(): fail(f"Garbage after stop line: {remainder!r}") return True @@ -1735,7 +1758,7 @@ def is_stop_line(line): if body_prefix: line = line.lstrip() assert line.startswith(body_prefix) - line = line[len(body_prefix):] + line = line.removeprefix(body_prefix) input_add(line) # consume output and checksum line, if present. @@ -1767,16 +1790,14 @@ def is_stop_line(line): for field in shlex.split(arguments): name, equals, value = field.partition('=') if not equals: - fail("Mangled Argument Clinic marker line: {!r}".format(line)) + fail("Mangled Argument Clinic marker line:", repr(line)) d[name.strip()] = value.strip() if self.verify: if 'input' in d: checksum = d['output'] - input_checksum = d['input'] else: checksum = d['checksum'] - input_checksum = None computed = compute_checksum(output, len(checksum)) if checksum != computed: @@ -1845,7 +1866,10 @@ def print_block(self, block, *, core_includes=False): output += '\n' write(output) - arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16)) + arguments = "output={output} input={input}".format( + output=compute_checksum(output, 16), + input=compute_checksum(input, 16) + ) write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments)) write("\n") @@ -1942,40 +1966,17 @@ def dump(self): extensions['py'] = PythonLanguage -# maps strings to callables. -# these callables must be of the form: -# def foo(name, default, *, ...) -# The callable may have any number of keyword-only parameters. -# The callable must return a CConverter object. -# The callable should not call builtins.print. -converters = {} - -# maps strings to callables. -# these callables follow the same rules as those for "converters" above. -# note however that they will never be called with keyword-only parameters. -legacy_converters = {} - - -# maps strings to callables. -# these callables must be of the form: -# def foo(*, ...) -# The callable may have any number of keyword-only parameters. -# The callable must return a CConverter object. -# The callable should not call builtins.print. -return_converters = {} - - -def write_file(filename, new_contents, force=False): +def file_changed(filename: str, new_contents: str) -> bool: + """Return true if file contents changed (meaning we must update it)""" try: - with open(filename, 'r', encoding="utf-8") as fp: + with open(filename, encoding="utf-8") as fp: old_contents = fp.read() - - if old_contents == new_contents and not force: - # no change: avoid modifying the file modification time - return + return old_contents != new_contents except FileNotFoundError: - pass + return True + +def write_file(filename: str, new_contents: str): # Atomic write using a temporary file and os.replace() filename_new = f"{filename}.new" with open(filename_new, "w", encoding="utf-8") as fp: @@ -1988,6 +1989,11 @@ def write_file(filename, new_contents, force=False): raise +ClassDict = dict[str, "Class"] +DestinationDict = dict[str, Destination] +ModuleDict = dict[str, "Module"] +ParserDict = dict[str, "DSLParser"] + clinic = None class Clinic: @@ -2034,23 +2040,30 @@ class Clinic: """ - def __init__(self, language, printer=None, *, verify=True, filename=None): + def __init__( + self, + language: CLanguage, + printer: BlockPrinter | None = None, + *, + verify: bool = True, + filename: str | None = None + ) -> None: # maps strings to Parser objects. # (instantiated from the "parsers" global.) - self.parsers = {} - self.language = language + self.parsers: ParserDict = {} + self.language: CLanguage = language if printer: fail("Custom printers are broken right now") self.printer = printer or BlockPrinter(language) self.verify = verify self.filename = filename - self.modules = collections.OrderedDict() - self.classes = collections.OrderedDict() - self.functions = [] + self.modules: ModuleDict = {} + self.classes: ClassDict = {} + self.functions: list[Function] = [] self.line_prefix = self.line_suffix = '' - self.destinations = {} + self.destinations: DestinationDict = {} self.add_destination("block", "buffer") self.add_destination("suppress", "suppress") self.add_destination("buffer", "buffer") @@ -2058,23 +2071,26 @@ def __init__(self, language, printer=None, *, verify=True, filename=None): self.add_destination("file", "file", "{dirname}/clinic/{basename}.h") d = self.get_destination_buffer - self.destination_buffers = collections.OrderedDict(( - ('cpp_if', d('file')), - ('docstring_prototype', d('suppress')), - ('docstring_definition', d('file')), - ('methoddef_define', d('file')), - ('impl_prototype', d('file')), - ('parser_prototype', d('suppress')), - ('parser_definition', d('file')), - ('cpp_endif', d('file')), - ('methoddef_ifndef', d('file', 1)), - ('impl_definition', d('block')), - )) - - self.destination_buffers_stack = [] - self.ifndef_symbols = set() - - self.presets = {} + self.destination_buffers = { + 'cpp_if': d('file'), + 'docstring_prototype': d('suppress'), + 'docstring_definition': d('file'), + 'methoddef_define': d('file'), + 'impl_prototype': d('file'), + 'parser_prototype': d('suppress'), + 'parser_definition': d('file'), + 'cpp_endif': d('file'), + 'methoddef_ifndef': d('file', 1), + 'impl_definition': d('block'), + } + + DestBufferType = dict[str, Callable[..., Any]] + DestBufferList = list[DestBufferType] + + self.destination_buffers_stack: DestBufferList = [] + self.ifndef_symbols: set[str] = set() + + self.presets: dict[str, dict[Any, Any]] = {} preset = None for line in self.presets_text.strip().split('\n'): line = line.strip() @@ -2082,7 +2098,7 @@ def __init__(self, language, printer=None, *, verify=True, filename=None): continue name, value, *options = line.split() if name == 'preset': - self.presets[value] = preset = collections.OrderedDict() + self.presets[value] = preset = {} continue if len(options): @@ -2102,18 +2118,27 @@ def __init__(self, language, printer=None, *, verify=True, filename=None): global clinic clinic = self - def add_destination(self, name, type, *args): + def add_destination( + self, + name: str, + type: str, + *args + ) -> None: if name in self.destinations: fail("Destination already exists: " + repr(name)) self.destinations[name] = Destination(name, type, self, *args) - def get_destination(self, name): + def get_destination(self, name: str) -> Destination: d = self.destinations.get(name) if not d: fail("Destination does not exist: " + repr(name)) return d - def get_destination_buffer(self, name, item=0): + def get_destination_buffer( + self, + name: str, + item: int = 0 + ): d = self.get_destination(name) return d.buffers[item] @@ -2124,7 +2149,7 @@ def parse(self, input): dsl_name = block.dsl_name if dsl_name: if dsl_name not in self.parsers: - assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name) + assert dsl_name in parsers, f"No parser to handle {dsl_name!r} block." self.parsers[dsl_name] = parsers[dsl_name](self) parser = self.parsers[dsl_name] try: @@ -2164,7 +2189,7 @@ def parse(self, input): "can't make directory {}!".format( destination.filename, dirname)) if self.verify: - with open(destination.filename, "rt") as f: + with open(destination.filename) as f: parser_2 = BlockParser(f.read(), language=self.language) blocks = list(parser_2) if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'): @@ -2213,7 +2238,12 @@ def _module_and_class(self, fields): return module, cls -def parse_file(filename, *, verify=True, output=None): +def parse_file( + filename: str, + *, + verify: bool = True, + output: str | None = None +) -> None: if not output: output = filename @@ -2226,7 +2256,7 @@ def parse_file(filename, *, verify=True, output=None): except KeyError: fail("Can't identify file type for file " + repr(filename)) - with open(filename, 'r', encoding="utf-8") as f: + with open(filename, encoding="utf-8") as f: raw = f.read() # exit quickly if there are no clinic markers in the file @@ -2234,17 +2264,22 @@ def parse_file(filename, *, verify=True, output=None): if not find_start_re.search(raw): return + assert isinstance(language, CLanguage) clinic = Clinic(language, verify=verify, filename=filename) src_out, clinic_out = clinic.parse(raw) - # If clinic output changed, force updating the source file as well. - force = bool(clinic_out) - write_file(output, src_out, force=force) - for fn, data in clinic_out: - write_file(fn, data) + changes = [(fn, data) for fn, data in clinic_out if file_changed(fn, data)] + if changes: + # Always (re)write the source file. + write_file(output, src_out) + for fn, data in clinic_out: + write_file(fn, data) -def compute_checksum(input, length=None): +def compute_checksum( + input: str | None, + length: int | None = None +) -> str: input = input or '' s = hashlib.sha1(input.encode('utf-8')).hexdigest() if length: @@ -2255,10 +2290,10 @@ def compute_checksum(input, length=None): class PythonParser: - def __init__(self, clinic): + def __init__(self, clinic: Clinic) -> None: pass - def parse(self, block): + def parse(self, block: Block) -> None: s = io.StringIO() with OverrideStdioWith(s): exec(block.input) @@ -2266,19 +2301,31 @@ def parse(self, block): class Module: - def __init__(self, name, module=None): + def __init__( + self, + name: str, + module = None + ) -> None: self.name = name self.module = self.parent = module - self.modules = collections.OrderedDict() - self.classes = collections.OrderedDict() - self.functions = [] + self.modules: ModuleDict = {} + self.classes: ClassDict = {} + self.functions: list[Function] = [] - def __repr__(self): + def __repr__(self) -> str: return "" + class Class: - def __init__(self, name, module=None, cls=None, typedef=None, type_object=None): + def __init__( + self, + name: str, + module: Module | None = None, + cls = None, + typedef: str | None = None, + type_object: str | None = None + ) -> None: self.name = name self.module = module self.cls = cls @@ -2286,13 +2333,14 @@ def __init__(self, name, module=None, cls=None, typedef=None, type_object=None): self.type_object = type_object self.parent = cls or module - self.classes = collections.OrderedDict() - self.functions = [] + self.classes: ClassDict = {} + self.functions: list[Function] = [] - def __repr__(self): + def __repr__(self) -> str: return "" -unsupported_special_methods = set(""" + +unsupported_special_methods: set[str] = set(""" __abs__ __add__ @@ -2368,6 +2416,9 @@ def __repr__(self): INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW """.replace(",", "").strip().split() +ParamDict = dict[str, "Parameter"] +ReturnConverterType = Callable[..., "CReturnConverter"] + class Function: """ Mutable duck type for inspect.Function. @@ -2380,13 +2431,23 @@ class Function: (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring)) """ - def __init__(self, parameters=None, *, name, - module, cls=None, c_basename=None, - full_name=None, - return_converter, return_annotation=inspect.Signature.empty, - docstring=None, kind=CALLABLE, coexist=False, - docstring_only=False): - self.parameters = parameters or collections.OrderedDict() + def __init__( + self, + parameters: ParamDict | None = None, + *, + name: str, + module: Module, + cls: Class | None = None, + c_basename: str | None = None, + full_name: str | None = None, + return_converter: ReturnConverterType, + return_annotation = inspect.Signature.empty, + docstring: str | None = None, + kind: str = CALLABLE, + coexist: bool = False, + docstring_only: bool = False + ) -> None: + self.parameters = parameters or {} self.return_annotation = return_annotation self.name = name self.full_name = full_name @@ -2419,7 +2480,7 @@ def render_parameters(self): return self.__render_parameters__ @property - def methoddef_flags(self): + def methoddef_flags(self) -> str | None: if self.kind in (METHOD_INIT, METHOD_NEW): return None flags = [] @@ -2433,10 +2494,10 @@ def methoddef_flags(self): flags.append('METH_COEXIST') return '|'.join(flags) - def __repr__(self): + def __repr__(self) -> str: return '' - def copy(self, **overrides): + def copy(self, **overrides) -> "Function": kwargs = { 'name': self.name, 'module': self.module, 'parameters': self.parameters, 'cls': self.cls, 'c_basename': self.c_basename, @@ -2447,12 +2508,10 @@ def copy(self, **overrides): } kwargs.update(overrides) f = Function(**kwargs) - - parameters = collections.OrderedDict() - for name, value in f.parameters.items(): - value = value.copy(function=f) - parameters[name] = value - f.parameters = parameters + f.parameters = { + name: value.copy(function=f) + for name, value in f.parameters.items() + } return f @@ -2461,9 +2520,18 @@ class Parameter: Mutable duck type of inspect.Parameter. """ - def __init__(self, name, kind, *, default=inspect.Parameter.empty, - function, converter, annotation=inspect.Parameter.empty, - docstring=None, group=0): + def __init__( + self, + name: str, + kind: str, + *, + default = inspect.Parameter.empty, + function: Function, + converter: "CConverter", + annotation = inspect.Parameter.empty, + docstring: str | None = None, + group: int = 0 + ) -> None: self.name = name self.kind = kind self.default = default @@ -2473,22 +2541,22 @@ def __init__(self, name, kind, *, default=inspect.Parameter.empty, self.docstring = docstring or '' self.group = group - def __repr__(self): + def __repr__(self) -> str: return '' - def is_keyword_only(self): + def is_keyword_only(self) -> bool: return self.kind == inspect.Parameter.KEYWORD_ONLY - def is_positional_only(self): + def is_positional_only(self) -> bool: return self.kind == inspect.Parameter.POSITIONAL_ONLY - def is_vararg(self): + def is_vararg(self) -> bool: return self.kind == inspect.Parameter.VAR_POSITIONAL - def is_optional(self): + def is_optional(self) -> bool: return not self.is_vararg() and (self.default is not unspecified) - def copy(self, **overrides): + def copy(self, **overrides) -> "Parameter": kwargs = { 'name': self.name, 'kind': self.kind, 'default':self.default, 'function': self.function, 'converter': self.converter, 'annotation': self.annotation, @@ -2501,24 +2569,24 @@ def copy(self, **overrides): kwargs['converter'] = converter return Parameter(**kwargs) - def get_displayname(self, i): + def get_displayname(self, i: int) -> str: if i == 0: return '"argument"' if not self.is_positional_only(): - return '''"argument '{}'"'''.format(self.name) + return f'"argument {self.name!r}"' else: - return '"argument {}"'.format(i) + return f'"argument {i}"' class LandMine: # try to access any - def __init__(self, message): + def __init__(self, message: str) -> None: self.__message__ = message - def __repr__(self): + def __repr__(self) -> str: return '" - def __getattribute__(self, name): + def __getattribute__(self, name: str): if name in ('__repr__', '__message__'): return super().__getattribute__(name) # raise RuntimeError(repr(name)) @@ -2530,7 +2598,7 @@ def add_c_converter(f, name=None): name = f.__name__ if not name.endswith('_converter'): return f - name = name[:-len('_converter')] + name = name.removesuffix('_converter') converters[name] = f return f @@ -2585,7 +2653,7 @@ class CConverter(metaclass=CConverterAutoRegister): # Or the magic value "unknown" if this value is a cannot be evaluated # at Argument-Clinic-preprocessing time (but is presumed to be valid # at runtime). - default = unspecified + default: object = unspecified # If not None, default must be isinstance() of this type. # (You can also specify a tuple of types.) @@ -2640,7 +2708,7 @@ class CConverter(metaclass=CConverterAutoRegister): # What encoding do we want for this variable? Only used # by format units starting with 'e'. - encoding = None + encoding: str | None = None # Should this object be required to be a subclass of a specific type? # If not None, should be a string representing a pointer to a @@ -2668,15 +2736,15 @@ class CConverter(metaclass=CConverterAutoRegister): # keep in sync with self_converter.__init__! def __init__(self, # Positional args: - name, - py_name, + name: str, + py_name: str, function, - default=unspecified, + default: object = unspecified, *, # Keyword only args: - c_default=None, - py_default=None, - annotation=unspecified, - unused=False, + c_default: str | None = None, + py_default: str | None = None, + annotation: str | Literal[Sentinels.unspecified] = unspecified, + unused: bool = False, **kwargs ): self.name = ensure_legal_c_identifier(name) @@ -2684,11 +2752,15 @@ def __init__(self, self.unused = unused if default is not unspecified: - if self.default_type and not isinstance(default, (self.default_type, Unknown)): + if (self.default_type + and default is not unknown + and not isinstance(default, self.default_type) + ): if isinstance(self.default_type, type): types_str = self.default_type.__name__ else: - types_str = ', '.join((cls.__name__ for cls in self.default_type)) + names = [cls.__name__ for cls in self.default_type] + types_str = ', '.join(names) fail("{}: default value {!r} for field {} is not of type {}".format( self.__class__.__name__, default, name, types_str)) self.default = default @@ -2698,7 +2770,7 @@ def __init__(self, if py_default: self.py_default = py_default - if annotation != unspecified: + if annotation is not unspecified: fail("The 'annotation' parameter is not currently permitted.") # this is deliberate, to prevent you from caching information @@ -2712,10 +2784,10 @@ def __init__(self, def converter_init(self): pass - def is_optional(self): + def is_optional(self) -> bool: return (self.default is not unspecified) - def _render_self(self, parameter, data): + def _render_self(self, parameter: str, data: CRenderData) -> None: self.parameter = parameter name = self.parser_name @@ -2775,7 +2847,7 @@ def _render_non_self(self, parameter, data): if cleanup: data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n") - def render(self, parameter, data): + def render(self, parameter: str, data: CRenderData) -> None: """ parameter is a clinic.Parameter instance. data is a CRenderData instance. @@ -2851,7 +2923,7 @@ def declaration(self, *, in_parser=False): declaration.append(';') return "".join(declaration) - def initialize(self): + def initialize(self) -> str: """ The C statements required to set up this variable before parsing. Returns a string containing this code indented at column 0. @@ -2859,7 +2931,7 @@ def initialize(self): """ return "" - def modify(self): + def modify(self) -> str: """ The C statements required to modify this variable after parsing. Returns a string containing this code indented at column 0. @@ -2867,7 +2939,7 @@ def modify(self): """ return "" - def post_parsing(self): + def post_parsing(self) -> str: """ The C statements required to do some operations after the end of parsing but before cleaning up. Return a string containing this code indented at column 0. @@ -2875,7 +2947,7 @@ def post_parsing(self): """ return "" - def cleanup(self): + def cleanup(self) -> str: """ The C statements required to clean up after this variable. Returns a string containing this code indented at column 0. @@ -2928,7 +3000,7 @@ def parse_arg(self, argname, displayname): """.format(argname=argname, paramname=self.parser_name, cast=cast) return None - def set_template_dict(self, template_dict): + def set_template_dict(self, template_dict: TemplateDict) -> None: pass @property @@ -2951,13 +3023,41 @@ def parser_name(self): } +ConverterType = Callable[..., CConverter] +ConverterDict = dict[str, ConverterType] + +# maps strings to callables. +# these callables must be of the form: +# def foo(name, default, *, ...) +# The callable may have any number of keyword-only parameters. +# The callable must return a CConverter object. +# The callable should not call builtins.print. +converters: ConverterDict = {} + +# maps strings to callables. +# these callables follow the same rules as those for "converters" above. +# note however that they will never be called with keyword-only parameters. +legacy_converters: ConverterDict = {} + +# maps strings to callables. +# these callables must be of the form: +# def foo(*, ...) +# The callable may have any number of keyword-only parameters. +# The callable must return a CReturnConverter object. +# The callable should not call builtins.print. +ReturnConverterDict = dict[str, ReturnConverterType] +return_converters: ReturnConverterDict = {} + +TypeSet = set[bltns.type[Any]] + + class bool_converter(CConverter): type = 'int' default_type = bool format_unit = 'p' c_ignored_default = '0' - def converter_init(self, *, accept={object}): + def converter_init(self, *, accept: TypeSet = {object}) -> None: if accept == {int}: self.format_unit = 'i' elif accept != {object}: @@ -2966,7 +3066,7 @@ def converter_init(self, *, accept={object}): self.default = bool(self.default) self.c_default = str(int(self.default)) - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'i': return """ {paramname} = _PyLong_AsInt({argname}); @@ -2992,10 +3092,10 @@ class defining_class_converter(CConverter): format_unit = '' show_in_signature = False - def converter_init(self, *, type=None): + def converter_init(self, *, type=None) -> None: self.specified_type = type - def render(self, parameter, data): + def render(self, parameter, data) -> None: self._render_self(parameter, data) def set_template_dict(self, template_dict): @@ -3008,7 +3108,7 @@ class char_converter(CConverter): format_unit = 'c' c_ignored_default = "'\0'" - def converter_init(self): + def converter_init(self) -> None: if isinstance(self.default, self.default_type): if len(self.default) != 1: fail("char_converter: illegal default value " + repr(self.default)) @@ -3017,7 +3117,7 @@ def converter_init(self): if self.c_default == '"\'"': self.c_default = r"'\''" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'c': return """ if (PyBytes_Check({argname}) && PyBytes_GET_SIZE({argname}) == 1) {{{{ @@ -3042,11 +3142,11 @@ class unsigned_char_converter(CConverter): format_unit = 'b' c_ignored_default = "'\0'" - def converter_init(self, *, bitwise=False): + def converter_init(self, *, bitwise: bool = False) -> None: if bitwise: self.format_unit = 'B' - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'b': return """ {{{{ @@ -3091,7 +3191,7 @@ class short_converter(CConverter): format_unit = 'h' c_ignored_default = "0" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'h': return """ {{{{ @@ -3121,13 +3221,13 @@ class unsigned_short_converter(CConverter): default_type = int c_ignored_default = "0" - def converter_init(self, *, bitwise=False): + def converter_init(self, *, bitwise: bool = False) -> None: if bitwise: self.format_unit = 'H' else: self.converter = '_PyLong_UnsignedShort_Converter' - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'H': return """ {paramname} = (unsigned short)PyLong_AsUnsignedLongMask({argname}); @@ -3144,7 +3244,7 @@ class int_converter(CConverter): format_unit = 'i' c_ignored_default = "0" - def converter_init(self, *, accept={int}, type=None): + def converter_init(self, *, accept: TypeSet = {int}, type=None) -> None: if accept == {str}: self.format_unit = 'C' elif accept != {int}: @@ -3152,7 +3252,7 @@ def converter_init(self, *, accept={int}, type=None): if type is not None: self.type = type - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'i': return """ {paramname} = _PyLong_AsInt({argname}); @@ -3183,13 +3283,13 @@ class unsigned_int_converter(CConverter): default_type = int c_ignored_default = "0" - def converter_init(self, *, bitwise=False): + def converter_init(self, *, bitwise: bool = False) -> None: if bitwise: self.format_unit = 'I' else: self.converter = '_PyLong_UnsignedInt_Converter' - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'I': return """ {paramname} = (unsigned int)PyLong_AsUnsignedLongMask({argname}); @@ -3205,7 +3305,7 @@ class long_converter(CConverter): format_unit = 'l' c_ignored_default = "0" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'l': return """ {paramname} = PyLong_AsLong({argname}); @@ -3220,13 +3320,13 @@ class unsigned_long_converter(CConverter): default_type = int c_ignored_default = "0" - def converter_init(self, *, bitwise=False): + def converter_init(self, *, bitwise: bool = False) -> None: if bitwise: self.format_unit = 'k' else: self.converter = '_PyLong_UnsignedLong_Converter' - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'k': return """ if (!PyLong_Check({argname})) {{{{ @@ -3244,7 +3344,7 @@ class long_long_converter(CConverter): format_unit = 'L' c_ignored_default = "0" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'L': return """ {paramname} = PyLong_AsLongLong({argname}); @@ -3259,13 +3359,13 @@ class unsigned_long_long_converter(CConverter): default_type = int c_ignored_default = "0" - def converter_init(self, *, bitwise=False): + def converter_init(self, *, bitwise: bool = False) -> None: if bitwise: self.format_unit = 'K' else: self.converter = '_PyLong_UnsignedLongLong_Converter' - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'K': return """ if (!PyLong_Check({argname})) {{{{ @@ -3281,7 +3381,7 @@ class Py_ssize_t_converter(CConverter): type = 'Py_ssize_t' c_ignored_default = "0" - def converter_init(self, *, accept={int}): + def converter_init(self, *, accept: TypeSet = {int}) -> None: if accept == {int}: self.format_unit = 'n' self.default_type = int @@ -3290,7 +3390,7 @@ def converter_init(self, *, accept={int}): else: fail("Py_ssize_t_converter: illegal 'accept' argument " + repr(accept)) - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'n': return """ {{{{ @@ -3312,7 +3412,7 @@ def parse_arg(self, argname, displayname): class slice_index_converter(CConverter): type = 'Py_ssize_t' - def converter_init(self, *, accept={int, NoneType}): + def converter_init(self, *, accept: TypeSet = {int, NoneType}) -> None: if accept == {int}: self.converter = '_PyEval_SliceIndexNotNone' elif accept == {int, NoneType}: @@ -3325,7 +3425,7 @@ class size_t_converter(CConverter): converter = '_PyLong_Size_t_Converter' c_ignored_default = "0" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'n': return """ {paramname} = PyNumber_AsSsize_t({argname}, PyExc_OverflowError); @@ -3340,7 +3440,7 @@ class fildes_converter(CConverter): type = 'int' converter = '_PyLong_FileDescriptor_Converter' - def _parse_arg(self, argname, displayname): + def _parse_arg(self, argname: str, displayname: str) -> str: return """ {paramname} = PyObject_AsFileDescriptor({argname}); if ({paramname} == -1) {{{{ @@ -3355,7 +3455,7 @@ class float_converter(CConverter): format_unit = 'f' c_ignored_default = "0.0" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'f': return """ if (PyFloat_CheckExact({argname})) {{{{ @@ -3377,7 +3477,7 @@ class double_converter(CConverter): format_unit = 'd' c_ignored_default = "0.0" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'd': return """ if (PyFloat_CheckExact({argname})) {{{{ @@ -3400,7 +3500,7 @@ class Py_complex_converter(CConverter): format_unit = 'D' c_ignored_default = "{0.0, 0.0}" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'D': return """ {paramname} = PyComplex_AsCComplex({argname}); @@ -3415,7 +3515,12 @@ class object_converter(CConverter): type = 'PyObject *' format_unit = 'O' - def converter_init(self, *, converter=None, type=None, subclass_of=None): + def converter_init( + self, *, + converter=None, + type=None, + subclass_of=None + ) -> None: if converter: if subclass_of: fail("object: Cannot pass in both 'converter' and 'subclass_of'") @@ -3451,7 +3556,13 @@ class str_converter(CConverter): default_type = (str, Null, NoneType) format_unit = 's' - def converter_init(self, *, accept={str}, encoding=None, zeroes=False): + def converter_init( + self, + *, + accept: TypeSet = {str}, + encoding: str | None = None, + zeroes: bool = False + ) -> None: key = str_converter_key(accept, encoding, zeroes) format_unit = str_converter_argument_map.get(key) @@ -3476,7 +3587,7 @@ def post_parsing(self): name = self.name return f"PyMem_FREE({name});\n" - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 's': return """ if (!PyUnicode_Check({argname})) {{{{ @@ -3529,7 +3640,14 @@ def parse_arg(self, argname, displayname): # mapping from arguments to format unit *and* registers the # legacy C converter for that format unit. # -def r(format_unit, *, accept, encoding=False, zeroes=False): +ConverterKeywordDict = dict[str, TypeSet | bool] + +def r(format_unit: str, + *, + accept: TypeSet, + encoding: bool = False, + zeroes: bool = False +) -> None: if not encoding and format_unit != 's': # add the legacy c converters here too. # @@ -3539,7 +3657,7 @@ def r(format_unit, *, accept, encoding=False, zeroes=False): # # also don't add the converter for 's' because # the metaclass for CConverter adds it for us. - kwargs = {} + kwargs: ConverterKeywordDict = {} if accept != {str}: kwargs['accept'] = accept if zeroes: @@ -3571,7 +3689,7 @@ class PyBytesObject_converter(CConverter): format_unit = 'S' # accept = {bytes} - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'S': return """ if (!PyBytes_Check({argname})) {{{{ @@ -3588,7 +3706,7 @@ class PyByteArrayObject_converter(CConverter): format_unit = 'Y' # accept = {bytearray} - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'Y': return """ if (!PyByteArray_Check({argname})) {{{{ @@ -3605,7 +3723,7 @@ class unicode_converter(CConverter): default_type = (str, Null, NoneType) format_unit = 'U' - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'U': return """ if (!PyUnicode_Check({argname})) {{{{ @@ -3628,7 +3746,11 @@ class Py_UNICODE_converter(CConverter): type = 'const Py_UNICODE *' default_type = (str, Null, NoneType) - def converter_init(self, *, accept={str}, zeroes=False): + def converter_init( + self, *, + accept: TypeSet = {str}, + zeroes: bool = False + ) -> None: format_unit = 'Z' if accept=={str, NoneType} else 'u' if zeroes: format_unit += '#' @@ -3650,7 +3772,7 @@ def cleanup(self): PyMem_Free((void *){name}); """.format(name=self.name) - def parse_arg(self, argname, argnum): + def parse_arg(self, argname: str, argnum: str) -> str: if not self.length: if self.accept == {str}: return """ @@ -3690,7 +3812,7 @@ class Py_buffer_converter(CConverter): impl_by_reference = True c_ignored_default = "{NULL, NULL}" - def converter_init(self, *, accept={buffer}): + def converter_init(self, *, accept: TypeSet = {buffer}) -> None: if self.default not in (unspecified, None): fail("The only legal default value for Py_buffer is None.") @@ -3713,7 +3835,7 @@ def cleanup(self): name = self.name return "".join(["if (", name, ".obj) {\n PyBuffer_Release(&", name, ");\n}\n"]) - def parse_arg(self, argname, displayname): + def parse_arg(self, argname: str, displayname: str) -> str: if self.format_unit == 'y*': return """ if (PyObject_GetBuffer({argname}, &{paramname}, PyBUF_SIMPLE) != 0) {{{{ @@ -3762,7 +3884,7 @@ def parse_arg(self, argname, displayname): return super().parse_arg(argname, displayname) -def correct_name_for_self(f): +def correct_name_for_self(f) -> tuple[str, str]: if f.kind in (CALLABLE, METHOD_INIT): if f.cls: return "PyObject *", "self" @@ -3788,7 +3910,7 @@ class self_converter(CConverter): type = None format_unit = '' - def converter_init(self, *, type=None): + def converter_init(self, *, type=None) -> None: self.specified_type = type def pre_render(self): @@ -3879,7 +4001,7 @@ def set_template_dict(self, template_dict): ' Py_TYPE({0})->tp_new == base_tp->tp_new)' ).format(self.name) - line = '{} &&\n '.format(type_check) + line = f'{type_check} &&\n ' template_dict['self_type_check'] = line type_object = self.function.cls.type_object @@ -3887,21 +4009,29 @@ def set_template_dict(self, template_dict): template_dict['base_type_ptr'] = type_ptr - -def add_c_return_converter(f, name=None): +def add_c_return_converter( + f: ReturnConverterType, + name: str | None = None +) -> ReturnConverterType: if not name: name = f.__name__ if not name.endswith('_return_converter'): return f - name = name[:-len('_return_converter')] + name = name.removesuffix('_return_converter') return_converters[name] = f return f class CReturnConverterAutoRegister(type): - def __init__(cls, name, bases, classdict): + def __init__( + cls: ReturnConverterType, + name: str, + bases: tuple[type, ...], + classdict: dict[str, Any] + ) -> None: add_c_return_converter(cls) + class CReturnConverter(metaclass=CReturnConverterAutoRegister): # The C type to use for this variable. @@ -3911,9 +4041,14 @@ class CReturnConverter(metaclass=CReturnConverterAutoRegister): # The Python default value for this parameter, as a Python value. # Or the magic value "unspecified" if there is no default. - default = None - - def __init__(self, *, py_default=None, **kwargs): + default: object = None + + def __init__( + self, + *, + py_default: str | None = None, + **kwargs + ) -> None: self.py_default = py_default try: self.return_converter_init(**kwargs) @@ -3921,11 +4056,10 @@ def __init__(self, *, py_default=None, **kwargs): s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items()) sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e)) - def return_converter_init(self): - pass + def return_converter_init(self) -> None: ... - def declare(self, data): - line = [] + def declare(self, data: CRenderData) -> None: + line: list[str] = [] add = line.append add(self.type) if not self.type.endswith('*'): @@ -3934,48 +4068,70 @@ def declare(self, data): data.declarations.append(''.join(line)) data.return_value = data.converter_retval - def err_occurred_if(self, expr, data): - data.return_conversion.append('if (({}) && PyErr_Occurred()) {{\n goto exit;\n}}\n'.format(expr)) + def err_occurred_if( + self, + expr: str, + data: CRenderData + ) -> None: + line = f'if (({expr}) && PyErr_Occurred()) {{\n goto exit;\n}}\n' + data.return_conversion.append(line) + + def err_occurred_if_null_pointer( + self, + variable: str, + data: CRenderData + ) -> None: + line = f'if ({variable} == NULL) {{\n goto exit;\n}}\n' + data.return_conversion.append(line) + + def render( + self, + function: Function, + data: CRenderData + ) -> None: ... - def err_occurred_if_null_pointer(self, variable, data): - data.return_conversion.append('if ({} == NULL) {{\n goto exit;\n}}\n'.format(variable)) - - def render(self, function, data): - """ - function is a clinic.Function instance. - data is a CRenderData instance. - """ - pass add_c_return_converter(CReturnConverter, 'object') + class bool_return_converter(CReturnConverter): type = 'int' - def render(self, function, data): + def render( + self, + function: Function, + data: CRenderData + ) -> None: self.declare(data) self.err_occurred_if(f"{data.converter_retval} == -1", data) data.return_conversion.append( f'return_value = PyBool_FromLong((long){data.converter_retval});\n' ) + class long_return_converter(CReturnConverter): type = 'long' conversion_fn = 'PyLong_FromLong' cast = '' unsigned_cast = '' - def render(self, function, data): + def render( + self, + function: Function, + data: CRenderData + ) -> None: self.declare(data) self.err_occurred_if(f"{data.converter_retval} == {self.unsigned_cast}-1", data) data.return_conversion.append( f'return_value = {self.conversion_fn}({self.cast}{data.converter_retval});\n' ) + class int_return_converter(long_return_converter): type = 'int' cast = '(long)' + class init_return_converter(long_return_converter): """ Special return converter for __init__ functions. @@ -3983,23 +4139,30 @@ class init_return_converter(long_return_converter): type = 'int' cast = '(long)' - def render(self, function, data): - pass + def render( + self, + function: Function, + data: CRenderData + ) -> None: ... + class unsigned_long_return_converter(long_return_converter): type = 'unsigned long' conversion_fn = 'PyLong_FromUnsignedLong' unsigned_cast = '(unsigned long)' + class unsigned_int_return_converter(unsigned_long_return_converter): type = 'unsigned int' cast = '(unsigned long)' unsigned_cast = '(unsigned int)' + class Py_ssize_t_return_converter(long_return_converter): type = 'Py_ssize_t' conversion_fn = 'PyLong_FromSsize_t' + class size_t_return_converter(long_return_converter): type = 'size_t' conversion_fn = 'PyLong_FromSize_t' @@ -4010,13 +4173,18 @@ class double_return_converter(CReturnConverter): type = 'double' cast = '' - def render(self, function, data): + def render( + self, + function: Function, + data: CRenderData + ) -> None: self.declare(data) self.err_occurred_if(f"{data.converter_retval} == -1.0", data) data.return_conversion.append( f'return_value = PyFloat_FromDouble({self.cast}{data.converter_retval});\n' ) + class float_return_converter(double_return_converter): type = 'float' cast = '(double)' @@ -4036,7 +4204,7 @@ def eval_ast_expr(node, globals, *, filename='-'): node = ast.Expression(node) co = compile(node, filename, 'eval') - fn = types.FunctionType(co, globals) + fn = FunctionType(co, globals) return fn() @@ -4120,8 +4288,10 @@ def dedent(self, line): return line[indent:] +StateKeeper = Callable[[str | None], None] + class DSLParser: - def __init__(self, clinic): + def __init__(self, clinic: Clinic) -> None: self.clinic = clinic self.directives = {} @@ -4138,9 +4308,9 @@ def __init__(self, clinic): self.reset() - def reset(self): + def reset(self) -> None: self.function = None - self.state = self.state_dsl_start + self.state: StateKeeper = self.state_dsl_start self.parameter_indent = None self.keyword_only = False self.positional_only = False @@ -4153,14 +4323,13 @@ def reset(self): self.parameter_continuation = '' self.preserve_output = False - def directive_version(self, required): + def directive_version(self, required: str) -> None: global version if version_comparitor(version, required) < 0: fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required) - def directive_module(self, name): - fields = name.split('.') - new = fields.pop() + def directive_module(self, name: str) -> None: + fields = name.split('.')[:-1] module, cls = self.clinic._module_and_class(fields) if cls: fail("Can't nest a module inside a class!") @@ -4172,12 +4341,14 @@ def directive_module(self, name): module.modules[name] = m self.block.signatures.append(m) - def directive_class(self, name, typedef, type_object): + def directive_class( + self, + name: str, + typedef: str, + type_object: str + ) -> None: fields = name.split('.') - in_classes = False - parent = self name = fields.pop() - so_far = [] module, cls = self.clinic._module_and_class(fields) parent = cls or module @@ -4188,7 +4359,7 @@ def directive_class(self, name, typedef, type_object): parent.classes[name] = c self.block.signatures.append(c) - def directive_set(self, name, value): + def directive_set(self, name: str, value: str) -> None: if name not in ("line_prefix", "line_suffix"): fail("unknown variable", repr(name)) @@ -4199,7 +4370,12 @@ def directive_set(self, name, value): self.clinic.__dict__[name] = value - def directive_destination(self, name, command, *args): + def directive_destination( + self, + name: str, + command: str, + *args + ) -> None: if command == 'new': self.clinic.add_destination(name, *args) return @@ -4209,7 +4385,11 @@ def directive_destination(self, name, command, *args): fail("unknown destination command", repr(command)) - def directive_output(self, command_or_name, destination=''): + def directive_output( + self, + command_or_name: str, + destination: str = '' + ) -> None: fd = self.clinic.destination_buffers if command_or_name == "preset": @@ -4247,34 +4427,34 @@ def directive_output(self, command_or_name, destination=''): fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n preset push pop print everything " + " ".join(fd)) fd[command_or_name] = d - def directive_dump(self, name): + def directive_dump(self, name: str) -> None: self.block.output.append(self.clinic.get_destination(name).dump()) - def directive_printout(self, *args): + def directive_printout(self, *args: str) -> None: self.block.output.append(' '.join(args)) self.block.output.append('\n') - def directive_preserve(self): + def directive_preserve(self) -> None: if self.preserve_output: fail("Can't have preserve twice in one block!") self.preserve_output = True - def at_classmethod(self): + def at_classmethod(self) -> None: if self.kind is not CALLABLE: fail("Can't set @classmethod, function is not a normal callable") self.kind = CLASS_METHOD - def at_staticmethod(self): + def at_staticmethod(self) -> None: if self.kind is not CALLABLE: fail("Can't set @staticmethod, function is not a normal callable") self.kind = STATIC_METHOD - def at_coexist(self): + def at_coexist(self) -> None: if self.coexist: fail("Called @coexist twice!") self.coexist = True - def parse(self, block): + def parse(self, block: Block) -> None: self.reset() self.block = block self.saved_output = self.block.output @@ -4310,10 +4490,14 @@ def ignore_line(line): return False @staticmethod - def calculate_indent(line): + def calculate_indent(line: str) -> int: return len(line) - len(line.strip()) - def next(self, state, line=None): + def next( + self, + state: StateKeeper, + line: str | None = None + ) -> None: # real_print(self.state.__name__, "->", state.__name__, ", line=", line) self.state = state if line is not None: @@ -4404,13 +4588,13 @@ def state_modulename_name(self, line): c_basename = c_basename.strip() or None if not is_legal_py_identifier(full_name): - fail("Illegal function name: {}".format(full_name)) + fail("Illegal function name:", full_name) if c_basename and not is_legal_c_identifier(c_basename): - fail("Illegal C basename: {}".format(c_basename)) + fail("Illegal C basename:", c_basename) return_converter = None if returns: - ast_input = "def x() -> {}: pass".format(returns) + ast_input = f"def x() -> {returns}: pass" module = None try: module = ast.parse(ast_input) @@ -4623,7 +4807,7 @@ def state_parameter(self, line): module = None try: - ast_input = "def x({}): pass".format(base) + ast_input = f"def x({base}): pass" module = ast.parse(ast_input) except SyntaxError: try: @@ -4631,7 +4815,7 @@ def state_parameter(self, line): # c: int(accept={str}) # so assume there was no actual default value. default = None - ast_input = "def x({}): pass".format(line) + ast_input = f"def x({line}): pass" module = ast.parse(ast_input) except SyntaxError: pass @@ -4675,8 +4859,7 @@ def state_parameter(self, line): self.parameter_state = self.ps_optional default = default.strip() bad = False - ast_input = "x = {}".format(default) - bad = False + ast_input = f"x = {default}" try: module = ast.parse(ast_input) @@ -4713,7 +4896,7 @@ def bad_node(self, node): # but at least make an attempt at ensuring it's a valid expression. try: value = eval(default) - if value == unspecified: + if value is unspecified: fail("'unspecified' is not a legal default value!") except NameError: pass # probably a named constant @@ -4783,7 +4966,7 @@ def bad_node(self, node): dict = legacy_converters if legacy else converters legacy_str = "legacy " if legacy else "" if name not in dict: - fail('{} is not a valid {}converter'.format(name, legacy_str)) + fail(f'{name} is not a valid {legacy_str}converter') # if you use a c_name for the parameter, we just give that name to the converter # but the parameter object gets the python name converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs) @@ -4833,22 +5016,26 @@ def bad_node(self, node): key = f"{parameter_name}_as_{c_name}" if c_name else parameter_name self.function.parameters[key] = p - def parse_converter(self, annotation): - if (isinstance(annotation, ast.Constant) and - type(annotation.value) is str): - return annotation.value, True, {} - - if isinstance(annotation, ast.Name): - return annotation.id, False, {} + KwargDict = dict[str | None, Any] - if not isinstance(annotation, ast.Call): - fail("Annotations must be either a name, a function call, or a string.") - - name = annotation.func.id - symbols = globals() - - kwargs = {node.arg: eval_ast_expr(node.value, symbols) for node in annotation.keywords} - return name, False, kwargs + @staticmethod + def parse_converter(annotation: ast.expr | None) -> tuple[str, bool, KwargDict]: + match annotation: + case ast.Constant(value=str() as value): + return value, True, {} + case ast.Name(name): + return name, False, {} + case ast.Call(func=ast.Name(name)): + symbols = globals() + kwargs = { + node.arg: eval_ast_expr(node.value, symbols) + for node in annotation.keywords + } + return name, False, kwargs + case _: + fail( + "Annotations must be either a name, a function call, or a string." + ) def parse_special_symbol(self, symbol): if symbol == '*': @@ -5287,7 +5474,7 @@ def main(argv): if name in ignored: continue if name.endswith(suffix): - ids.append((name, name[:-len(suffix)])) + ids.append((name, name.removesuffix(suffix))) break print() @@ -5315,7 +5502,7 @@ def main(argv): for parameter_name, parameter in signature.parameters.items(): if parameter.kind == inspect.Parameter.KEYWORD_ONLY: if parameter.default != inspect.Parameter.empty: - s = '{}={!r}'.format(parameter_name, parameter.default) + s = f'{parameter_name}={parameter.default!r}' else: s = parameter_name parameters.append(s) diff --git a/Tools/clinic/cpp.py b/Tools/clinic/cpp.py index bc2cc713aac394..c1a2eeef22deca 100644 --- a/Tools/clinic/cpp.py +++ b/Tools/clinic/cpp.py @@ -1,6 +1,7 @@ import re import sys from collections.abc import Callable +from typing import NoReturn TokenAndCondition = tuple[str, str] @@ -30,7 +31,7 @@ class Monitor: is_a_simple_defined: Callable[[str], re.Match[str] | None] is_a_simple_defined = re.compile(r'^defined\s*\(\s*[A-Za-z0-9_]+\s*\)$').match - def __init__(self, filename=None, *, verbose: bool = False): + def __init__(self, filename: str | None = None, *, verbose: bool = False) -> None: self.stack: TokenStack = [] self.in_comment = False self.continuation: str | None = None @@ -55,7 +56,7 @@ def condition(self) -> str: """ return " && ".join(condition for token, condition in self.stack) - def fail(self, *a): + def fail(self, *a: object) -> NoReturn: if self.filename: filename = " " + self.filename else: @@ -64,7 +65,7 @@ def fail(self, *a): print(" ", ' '.join(str(x) for x in a)) sys.exit(-1) - def close(self): + def close(self) -> None: if self.stack: self.fail("Ended file while still in a preprocessor conditional block!") @@ -184,7 +185,7 @@ def pop_stack() -> TokenAndCondition: if __name__ == '__main__': for filename in sys.argv[1:]: - with open(filename, "rt") as f: + with open(filename) as f: cpp = Monitor(filename, verbose=True) print() print(filename) diff --git a/Tools/clinic/mypy.ini b/Tools/clinic/mypy.ini index 3c5643e789be37..672911dc19abda 100644 --- a/Tools/clinic/mypy.ini +++ b/Tools/clinic/mypy.ini @@ -8,4 +8,5 @@ strict_concatenate = True warn_redundant_casts = True warn_unused_ignores = True warn_unused_configs = True +warn_unreachable = True files = Tools/clinic/ diff --git a/Tools/msi/bundle/packagegroups/postinstall.wxs b/Tools/msi/bundle/packagegroups/postinstall.wxs index 64f42dd30e8ba0..24c72e6357ab08 100644 --- a/Tools/msi/bundle/packagegroups/postinstall.wxs +++ b/Tools/msi/bundle/packagegroups/postinstall.wxs @@ -42,7 +42,7 @@ - + - - - - diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props index 06aa0b8bbca277..cfb3ca9e76e24c 100644 --- a/Tools/msi/msi.props +++ b/Tools/msi/msi.props @@ -156,9 +156,6 @@ <_Uuid Include="PythonwExeComponentGuid"> pythonw.exe - <_Uuid Include="RemoveLib2to3PickleComponentGuid"> - lib2to3/pickles - <_Uuid Include="CommonPythonRegComponentGuid"> registry @@ -187,4 +184,4 @@ $(DefineConstants);@(_UuidValue,';'); - \ No newline at end of file + diff --git a/Tools/peg_generator/Makefile b/Tools/peg_generator/Makefile index 084da154919e3e..eef2d807e5c5ce 100644 --- a/Tools/peg_generator/Makefile +++ b/Tools/peg_generator/Makefile @@ -87,8 +87,7 @@ time_stdlib: $(CPYTHON) venv $(VENVPYTHON) scripts/test_parse_directory.py \ -d $(CPYTHON) \ $(TESTFLAGS) \ - --exclude "*/bad*" \ - --exclude "*/test/test_lib2to3/data/*" + --exclude "*/bad*" mypy: regen-metaparser $(MYPY) # For list of files, see mypy.ini diff --git a/Tools/peg_generator/scripts/benchmark.py b/Tools/peg_generator/scripts/benchmark.py index 053f8ef06d42c5..6354e1a17167af 100644 --- a/Tools/peg_generator/scripts/benchmark.py +++ b/Tools/peg_generator/scripts/benchmark.py @@ -78,7 +78,6 @@ def run_benchmark_stdlib(subcommand): verbose=False, excluded_files=[ "*/bad*", - "*/test/test_lib2to3/data/*", ], short=True, mode=modes[subcommand], diff --git a/Tools/scripts/2to3 b/Tools/scripts/2to3 deleted file mode 100755 index f27d18ecf67086..00000000000000 --- a/Tools/scripts/2to3 +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python3 -import sys -from lib2to3.main import main - -sys.exit(main("lib2to3.fixes")) diff --git a/Tools/scripts/README b/Tools/scripts/README index 9dbb89a8dae633..a078bfbf662a37 100644 --- a/Tools/scripts/README +++ b/Tools/scripts/README @@ -1,7 +1,6 @@ This directory contains a collection of executable Python scripts that are useful while building, extending or managing Python. -2to3 Main script for running the 2to3 conversion tool checkpip.py Checks the version of the projects bundled in ensurepip are the latest available combinerefs.py A helper for analyzing PYTHONDUMPREFS output diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index 1fc97fd5e70a10..fcd99405ee0d8e 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -41,8 +41,6 @@ # package management "ensurepip/", "venv/", - # build system - "lib2to3/", # deprecated "uu.py", "xdrlib.py", @@ -78,7 +76,6 @@ "poplib.py", "smtplib.py", "socketserver.py", - "telnetlib.py", # keep urllib.parse for pydoc "urllib/error.py", "urllib/request.py", diff --git a/configure b/configure index 7aad4fe89e3cbf..bcf2a5c7c7f73c 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for python 3.12. +# Generated by GNU Autoconf 2.69 for python 3.13. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='python' PACKAGE_TARNAME='python' -PACKAGE_VERSION='3.12' -PACKAGE_STRING='python 3.12' +PACKAGE_VERSION='3.13' +PACKAGE_STRING='python 3.13' PACKAGE_BUGREPORT='https://github.com/python/cpython/issues/' PACKAGE_URL='' @@ -883,10 +883,11 @@ CFLAGS_NODIST BASECFLAGS CFLAGS_ALIASING OPT +BOLT_APPLY_FLAGS +BOLT_INSTRUMENT_FLAGS +BOLT_BINARIES MERGE_FDATA LLVM_BOLT -ac_ct_READELF -READELF PREBOLT_RULE LLVM_PROF_FOUND LLVM_PROFDATA @@ -1105,6 +1106,8 @@ CPPFLAGS CPP HOSTRUNNER PROFILE_TASK +BOLT_INSTRUMENT_FLAGS +BOLT_APPLY_FLAGS LIBUUID_CFLAGS LIBUUID_LIBS LIBFFI_CFLAGS @@ -1687,7 +1690,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures python 3.12 to adapt to many kinds of systems. +\`configure' configures python 3.13 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1753,7 +1756,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of python 3.12:";; + short | recursive ) echo "Configuration of python 3.13:";; esac cat <<\_ACEOF @@ -1797,9 +1800,9 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-build-python=python3.12 + --with-build-python=python3.13 path to build python binary for cross compiling - (default: _bootstrap_python or python3.12) + (default: _bootstrap_python or python3.13) --with-pkg-config=[yes|no|check] use pkg-config to detect build options (default is check) @@ -1916,6 +1919,10 @@ Some influential environment variables: HOSTRUNNER Program to run CPython for the host platform PROFILE_TASK Python args for PGO generation task + BOLT_INSTRUMENT_FLAGS + Arguments to llvm-bolt when instrumenting binaries + BOLT_APPLY_FLAGS + Arguments to llvm-bolt when creating a BOLT optimized binary LIBUUID_CFLAGS C compiler flags for LIBUUID, overriding pkg-config LIBUUID_LIBS @@ -2034,7 +2041,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -python configure 3.12 +python configure 3.13 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2743,7 +2750,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by python $as_me 3.12, which was +It was created by python $as_me 3.13, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3359,7 +3366,7 @@ fi -for ac_prog in python$PACKAGE_VERSION python3.12 python3.11 python3.10 python3 python +for ac_prog in python$PACKAGE_VERSION python3.13 python3.12 python3.11 python3.10 python3 python do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -3429,7 +3436,7 @@ rm confdefs.h mv confdefs.h.new confdefs.h -VERSION=3.12 +VERSION=3.13 # Version number of Python's own shared library file. @@ -8106,112 +8113,6 @@ if test "$Py_BOLT" = 'true' ; then DEF_MAKE_ALL_RULE="bolt-opt" DEF_MAKE_RULE="build_all" - - if test -n "$ac_tool_prefix"; then - for ac_prog in readelf - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_READELF+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$READELF"; then - ac_cv_prog_READELF="$READELF" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_READELF="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -READELF=$ac_cv_prog_READELF -if test -n "$READELF"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READELF" >&5 -$as_echo "$READELF" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$READELF" && break - done -fi -if test -z "$READELF"; then - ac_ct_READELF=$READELF - for ac_prog in readelf -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_READELF+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_READELF"; then - ac_cv_prog_ac_ct_READELF="$ac_ct_READELF" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_READELF="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_READELF=$ac_cv_prog_ac_ct_READELF -if test -n "$ac_ct_READELF"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_READELF" >&5 -$as_echo "$ac_ct_READELF" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_READELF" && break -done - - if test "x$ac_ct_READELF" = x; then - READELF=""notfound"" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - READELF=$ac_ct_READELF - fi -fi - - if test "$READELF" == "notfound" - then - as_fn_error $? "readelf is required for a --enable-bolt build but could not be found." "$LINENO" 5 - fi - # -fno-reorder-blocks-and-partition is required for bolt to work. # Possibly GCC only. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -fno-reorder-blocks-and-partition" >&5 @@ -8474,6 +8375,36 @@ $as_echo "\"Found merge-fdata\"" >&6; } fi fi + +BOLT_BINARIES='$(BUILDPYTHON)' +if test "x$enable_shared" = xyes; then : + + BOLT_BINARIES="${BOLT_BINARIES} \$(INSTSONAME)" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking BOLT_INSTRUMENT_FLAGS" >&5 +$as_echo_n "checking BOLT_INSTRUMENT_FLAGS... " >&6; } +if test -z "${BOLT_INSTRUMENT_FLAGS}" +then + BOLT_INSTRUMENT_FLAGS= +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BOLT_INSTRUMENT_FLAGS" >&5 +$as_echo "$BOLT_INSTRUMENT_FLAGS" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking BOLT_APPLY_FLAGS" >&5 +$as_echo_n "checking BOLT_APPLY_FLAGS... " >&6; } +if test -z "${BOLT_APPLY_FLAGS}" +then + BOLT_APPLY_FLAGS=-update-debug-sections -reorder-blocks=ext-tsp -reorder-functions=hfsort+ -split-functions -icf=1 -inline-all -split-eh -reorder-functions-use-hot-size -peepholes=none -jump-tables=aggressive -inline-ap -indirect-call-promotion=all -dyno-stats -use-gnu-stack -frame-opt=hot + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $BOLT_APPLY_FLAGS" >&5 +$as_echo "$BOLT_APPLY_FLAGS" >&6; } + # XXX Shouldn't the code above that fiddles with BASECFLAGS and OPT be # merged with this chunk of code? @@ -29040,7 +28971,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by python $as_me 3.12, which was +This file was extended by python $as_me 3.13, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -29102,7 +29033,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -python config.status 3.12 +python config.status 3.13 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 115998e0753b26..d5cb822ae8cb6b 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ dnl Python's configure.ac file requires autoconf 2.69 and autoconf-archive. dnl # Set VERSION so we only need to edit in one place (i.e., here) -m4_define(PYTHON_VERSION, 3.12) +m4_define(PYTHON_VERSION, 3.13) AC_PREREQ([2.69]) @@ -202,7 +202,7 @@ AC_SUBST([FREEZE_MODULE_DEPS]) AC_SUBST([PYTHON_FOR_BUILD_DEPS]) AC_CHECK_PROGS([PYTHON_FOR_REGEN], - [python$PACKAGE_VERSION python3.12 python3.11 python3.10 python3 python], + [python$PACKAGE_VERSION python3.13 python3.12 python3.11 python3.10 python3 python], [python3]) AC_SUBST(PYTHON_FOR_REGEN) @@ -2028,13 +2028,6 @@ if test "$Py_BOLT" = 'true' ; then DEF_MAKE_ALL_RULE="bolt-opt" DEF_MAKE_RULE="build_all" - AC_SUBST(READELF) - AC_CHECK_TOOLS(READELF, [readelf], "notfound") - if test "$READELF" == "notfound" - then - AC_MSG_ERROR([readelf is required for a --enable-bolt build but could not be found.]) - fi - # -fno-reorder-blocks-and-partition is required for bolt to work. # Possibly GCC only. AX_CHECK_COMPILE_FLAG([-fno-reorder-blocks-and-partition],[ @@ -2067,6 +2060,54 @@ if test "$Py_BOLT" = 'true' ; then fi fi +dnl Enable BOLT of libpython if built. +AC_SUBST(BOLT_BINARIES) +BOLT_BINARIES='$(BUILDPYTHON)' +AS_VAR_IF([enable_shared], [yes], [ + BOLT_BINARIES="${BOLT_BINARIES} \$(INSTSONAME)" +]) + +AC_ARG_VAR( + [BOLT_INSTRUMENT_FLAGS], + [Arguments to llvm-bolt when instrumenting binaries] +) +AC_MSG_CHECKING([BOLT_INSTRUMENT_FLAGS]) +if test -z "${BOLT_INSTRUMENT_FLAGS}" +then + BOLT_INSTRUMENT_FLAGS= +fi +AC_MSG_RESULT([$BOLT_INSTRUMENT_FLAGS]) + +AC_ARG_VAR( + [BOLT_APPLY_FLAGS], + [Arguments to llvm-bolt when creating a BOLT optimized binary] +) +AC_MSG_CHECKING([BOLT_APPLY_FLAGS]) +if test -z "${BOLT_APPLY_FLAGS}" +then + AS_VAR_SET( + [BOLT_APPLY_FLAGS], + [m4_join([ ], + [-update-debug-sections], + [-reorder-blocks=ext-tsp], + [-reorder-functions=hfsort+], + [-split-functions], + [-icf=1], + [-inline-all], + [-split-eh], + [-reorder-functions-use-hot-size], + [-peepholes=none], + [-jump-tables=aggressive], + [-inline-ap], + [-indirect-call-promotion=all], + [-dyno-stats], + [-use-gnu-stack], + [-frame-opt=hot] + )] + ) +fi +AC_MSG_RESULT([$BOLT_APPLY_FLAGS]) + # XXX Shouldn't the code above that fiddles with BASECFLAGS and OPT be # merged with this chunk of code?