diff --git a/.editorconfig b/.editorconfig index 25bc5935258bd14..ab1f7ce8425769e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,11 +1,11 @@ root = true -[*.{py,c,cpp,h,js,rst,md,yml,yaml,gram}] +[*.{py,c,cpp,h,js,rst,md,yml,yaml,toml,gram}] trim_trailing_whitespace = true insert_final_newline = true indent_style = space -[*.{py,c,cpp,h,gram}] +[*.{py,c,cpp,h,toml,gram}] indent_size = 4 [*.rst] diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 6a8d4244d079897..5bf4b40947bea70 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -1,7 +1,7 @@ # Security Policy Python [provides a security policy and threat model](https://devguide.python.org/security/policy/) -in the Python Development Guide documenting what bugs are vulnerabilities, +in the Python Developer's Guide documenting what bugs are vulnerabilities, how to structure reports, and what versions of Python accept reports. Python Security Response Team (PSRT) members diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 47ea859c5fefbb9..43f8e0c010ed1bc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -278,14 +278,13 @@ jobs: # unsupported as it most resembles other 1.1.1-work-a-like ssl APIs # supported by important vendors such as AWS-LC. - { name: openssl, version: 1.1.1w } - - { name: openssl, version: 3.0.20 } - - { name: openssl, version: 3.3.7 } - - { name: openssl, version: 3.4.5 } - - { name: openssl, version: 3.5.6 } - - { name: openssl, version: 3.6.2 } - - { name: openssl, version: 4.0.0 } + - { name: openssl, version: 3.0.21 } + - { name: openssl, version: 3.4.6 } + - { name: openssl, version: 3.5.7 } + - { name: openssl, version: 3.6.3 } + - { name: openssl, version: 4.0.1 } ## AWS-LC - - { name: aws-lc, version: 1.72.1 } + - { name: aws-lc, version: 5.0.0 } env: SSLLIB_VER: ${{ matrix.ssllib.version }} MULTISSL_DIR: ${{ github.workspace }}/multissl @@ -399,7 +398,7 @@ jobs: needs: build-context if: needs.build-context.outputs.run-ubuntu == 'true' env: - OPENSSL_VER: 3.5.6 + OPENSSL_VER: 3.5.7 PYTHONSTRICTEXTENSIONBUILD: 1 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -507,7 +506,7 @@ jobs: matrix: os: [ubuntu-24.04] env: - OPENSSL_VER: 3.5.6 + OPENSSL_VER: 3.5.7 PYTHONSTRICTEXTENSIONBUILD: 1 ASAN_OPTIONS: detect_leaks=0:allocator_may_return_null=1:handle_segv=0 steps: diff --git a/.github/workflows/reusable-san.yml b/.github/workflows/reusable-san.yml index 33f6f0ef455fe02..ef36447964cf418 100644 --- a/.github/workflows/reusable-san.yml +++ b/.github/workflows/reusable-san.yml @@ -82,19 +82,16 @@ jobs: run: make -j4 - name: Display build info run: make pythoninfo - # test_{capi,faulthandler} are skipped under UBSan because - # they raise signals that UBSan with halt_on_error=1 intercepts. - name: Tests run: >- ./python -m test ${{ inputs.sanitizer == 'TSan' && '--tsan' || '' }} - ${{ inputs.sanitizer == 'UBSan' && '-x test_capi -x test_faulthandler' || '' }} - -j4 + -j4 -W --timeout=900 --slowest - name: Parallel tests if: >- inputs.sanitizer == 'TSan' && fromJSON(inputs.free-threading) - run: ./python -m test --tsan-parallel --parallel-threads=4 -j4 + run: ./python -m test --tsan-parallel --parallel-threads=4 -j4 -W --timeout=600 --slowest - name: Display logs if: always() run: find "${GITHUB_WORKSPACE}" -name 'san_log.*' | xargs head -n 1000 diff --git a/.github/workflows/reusable-ubuntu.yml b/.github/workflows/reusable-ubuntu.yml index a7e307848af670c..f4321cefa1b5985 100644 --- a/.github/workflows/reusable-ubuntu.yml +++ b/.github/workflows/reusable-ubuntu.yml @@ -35,7 +35,7 @@ jobs: runs-on: ${{ inputs.os }} timeout-minutes: 60 env: - OPENSSL_VER: 3.5.6 + OPENSSL_VER: 3.5.7 PYTHONSTRICTEXTENSIONBUILD: 1 TERM: linux steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6878a7d92e3beeb..6c7f1b93e66e879 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: e05c5c0818279e5ac248ac9e954431ba58865e61 # frozen: v0.15.7 + rev: 3b3f7c3f57fe9925356faf5fe6230835138be230 # frozen: v0.15.17 hooks: - id: ruff-check name: Run Ruff (lint) on Platforms/Apple/ @@ -10,6 +10,11 @@ repos: name: Run Ruff (lint) on Doc/ args: [--exit-non-zero-on-fix] files: ^Doc/ + - id: ruff-check + name: Run Ruff (lint) on Lib/ + args: [--exit-non-zero-on-fix] + files: ^Lib/ + exclude: ^Lib/test/ - id: ruff-check name: Run Ruff (lint) on Lib/test/ args: [--exit-non-zero-on-fix] @@ -18,6 +23,11 @@ repos: name: Run Ruff (lint) on Platforms/WASI/ args: [--exit-non-zero-on-fix, --config=Platforms/WASI/.ruff.toml] files: ^Platforms/WASI/ + - id: ruff-check + name: Run Ruff (lint) on Tools/ + args: [--exit-non-zero-on-fix] + files: ^Tools/ + exclude: ^Tools/(build|clinic|i18n|peg_generator|wasm)/ - id: ruff-check name: Run Ruff (lint) on Tools/build/ args: [--exit-non-zero-on-fix, --config=Tools/build/.ruff.toml] diff --git a/Doc/Makefile b/Doc/Makefile index 60970d50833f147..d77ece1e681bcfc 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -88,9 +88,9 @@ htmlhelp: build "build/htmlhelp/pydoc.hhp project file." .PHONY: latex -latex: _ensure-sphinxcontrib-svg2pdfconverter latex: BUILDER = latex -latex: build +latex: _ensure-sphinxcontrib-svg2pdfconverter + $(MAKE) build BUILDER=$(BUILDER) @echo "Build finished; the LaTeX files are in build/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." diff --git a/Doc/bugs.rst b/Doc/bugs.rst index 254a22f2622bd8e..a6ea0a72e76f9db 100644 --- a/Doc/bugs.rst +++ b/Doc/bugs.rst @@ -12,6 +12,9 @@ It can be sometimes faster to fix bugs yourself and contribute patches to Python as it streamlines the process and involves fewer people. Learn how to :ref:`contribute `. + +.. _reporting-documentation-bugs: + Documentation bugs ================== diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst index 629312bd771beb2..10f96c7cb75e882 100644 --- a/Doc/c-api/complex.rst +++ b/Doc/c-api/complex.rst @@ -130,7 +130,7 @@ rather than dereferencing them through pointers. Please note, that these functions are :term:`soft deprecated` since Python 3.15. Avoid using this API in a new code to do complex arithmetic: either use -the `Number Protocol `_ API or use native complex types, like +the :ref:`Number Protocol ` API or use native complex types, like :c:expr:`double complex`. diff --git a/Doc/c-api/coro.rst b/Doc/c-api/coro.rst index caa855a10d20ca9..06422fb63f34f1a 100644 --- a/Doc/c-api/coro.rst +++ b/Doc/c-api/coro.rst @@ -33,3 +33,9 @@ return. with ``__name__`` and ``__qualname__`` set to *name* and *qualname*. A reference to *frame* is stolen by this function. The *frame* argument must not be ``NULL``. + + .. deprecated-removed:: 3.16 3.18 + + This function has not been used since 3.10. + It is also impossible to construct a proper *frame* + object to call this function. diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index f3f408c400bed08..167fe3ba41f92b9 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -498,12 +498,13 @@ Querying the error indicator .. c:function:: void PyErr_SetRaisedException(PyObject *exc) - Set *exc* as the exception currently being raised, - clearing the existing exception if one is set. + Set *exc* as the exception currently being raised, clearing the existing + exception if one is set. *exc* may be ``NULL`` in which case any current + exception is cleared. - .. warning:: + .. note:: - This call steals a reference to *exc*, which must be a valid exception. + This function "steals" a reference to *exc*. .. versionadded:: 3.12 @@ -1038,7 +1039,7 @@ Properly implementing :c:member:`~PyTypeObject.tp_repr` for container types requ special recursion handling. In addition to protecting the stack, :c:member:`~PyTypeObject.tp_repr` also needs to track objects to prevent cycles. The following two functions facilitate this functionality. Effectively, -these are the C equivalent to :func:`reprlib.recursive_repr`. +these are the C equivalent to :deco:`reprlib.recursive_repr`. .. c:function:: int Py_ReprEnter(PyObject *object) diff --git a/Doc/c-api/gen.rst b/Doc/c-api/gen.rst index ed121726b89620c..7713ba2ee4f8047 100644 --- a/Doc/c-api/gen.rst +++ b/Doc/c-api/gen.rst @@ -38,6 +38,12 @@ than explicitly calling :c:func:`PyGen_New` or :c:func:`PyGen_NewWithQualName`. A reference to *frame* is stolen by this function. The argument must not be ``NULL``. + .. deprecated-removed:: 3.16 3.18 + + This function has not been used since 3.10. + It is also impossible to construct a proper *frame* + object to call this function. + .. c:function:: PyObject* PyGen_NewWithQualName(PyFrameObject *frame, PyObject *name, PyObject *qualname) Create and return a new generator object based on the *frame* object, @@ -45,6 +51,12 @@ than explicitly calling :c:func:`PyGen_New` or :c:func:`PyGen_NewWithQualName`. A reference to *frame* is stolen by this function. The *frame* argument must not be ``NULL``. + .. deprecated-removed:: 3.16 3.18 + + This function has not been used since 3.10. + It is also impossible to construct a proper *frame* + object to call this function. + .. c:function:: PyCodeObject* PyGen_GetCode(PyGenObject *gen) @@ -77,6 +89,12 @@ Asynchronous Generator Objects .. versionadded:: 3.6 + .. deprecated-removed:: 3.16 3.18 + + This function has not been used since 3.10. + It is also impossible to construct a proper *frame* + object to call this function. + .. c:function:: int PyAsyncGen_CheckExact(PyObject *op) Return true if *op* is an asynchronous generator object, false otherwise. diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 209e48767ccfd6c..d6b9837987a3999 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -623,6 +623,10 @@ Some options are read from the :mod:`sys` attributes. For example, the option .. versionadded:: 3.14 + .. versionchanged:: next + The function now replaces :data:`sys.flags` (create a new object), + instead of modifying :data:`sys.flags` in-place. + .. _pyconfig_api: diff --git a/Doc/c-api/interp-lifecycle.rst b/Doc/c-api/interp-lifecycle.rst index 8dee601d04876b8..46f5b1dd33963c0 100644 --- a/Doc/c-api/interp-lifecycle.rst +++ b/Doc/c-api/interp-lifecycle.rst @@ -104,7 +104,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-b` option. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_DebugFlag @@ -119,7 +119,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-d` option and the :envvar:`PYTHONDEBUG` environment variable. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_DontWriteBytecodeFlag @@ -134,7 +134,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-B` option and the :envvar:`PYTHONDONTWRITEBYTECODE` environment variable. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_FrozenFlag @@ -145,7 +145,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Private flag used by ``_freeze_module`` and ``frozenmain`` programs. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_HashRandomizationFlag @@ -161,7 +161,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. If the flag is non-zero, read the :envvar:`PYTHONHASHSEED` environment variable to initialize the secret hash seed. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_IgnoreEnvironmentFlag @@ -175,7 +175,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-E` and :option:`-I` options. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_InspectFlag @@ -191,7 +191,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-i` option and the :envvar:`PYTHONINSPECT` environment variable. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_InteractiveFlag @@ -202,7 +202,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-i` option. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_IsolatedFlag @@ -218,7 +218,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. .. versionadded:: 3.4 - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_LegacyWindowsFSEncodingFlag @@ -238,7 +238,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. .. availability:: Windows. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_LegacyWindowsStdioFlag @@ -257,7 +257,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. .. availability:: Windows. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_NoSiteFlag @@ -273,7 +273,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-S` option. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_NoUserSiteDirectory @@ -288,7 +288,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-s` and :option:`-I` options, and the :envvar:`PYTHONNOUSERSITE` environment variable. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_OptimizeFlag @@ -300,7 +300,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-O` option and the :envvar:`PYTHONOPTIMIZE` environment variable. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_QuietFlag @@ -315,7 +315,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. .. versionadded:: 3.2 - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_UnbufferedStdioFlag @@ -329,7 +329,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-u` option and the :envvar:`PYTHONUNBUFFERED` environment variable. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 .. c:var:: int Py_VerboseFlag @@ -346,7 +346,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. Set by the :option:`-v` option and the :envvar:`PYTHONVERBOSE` environment variable. - .. deprecated-removed:: 3.12 3.15 + .. deprecated-removed:: 3.12 3.16 Initializing and finalizing the interpreter @@ -804,7 +804,7 @@ Process-wide parameters Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a :c:expr:`wchar_t*` string. - .. deprecated-removed:: 3.11 3.15 + .. deprecated-removed:: 3.11 3.16 .. c:function:: const char* Py_GetVersion() @@ -929,7 +929,7 @@ Process-wide parameters .. versionadded:: 3.1.3 - .. deprecated-removed:: 3.11 3.15 + .. deprecated-removed:: 3.11 3.16 .. c:function:: void PySys_SetArgv(int argc, wchar_t **argv) @@ -950,7 +950,7 @@ Process-wide parameters .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. - .. deprecated-removed:: 3.11 3.15 + .. deprecated-removed:: 3.11 3.16 .. c:function:: void Py_SetPythonHome(const wchar_t *home) @@ -971,4 +971,4 @@ Process-wide parameters Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a :c:expr:`wchar_t*` string. - .. deprecated-removed:: 3.11 3.15 + .. deprecated-removed:: 3.11 3.16 diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 60e3ae4a064e729..874e422d4701dd8 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -71,6 +71,12 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. on failure. +.. c:function:: PyObject* PyLong_FromUnsignedLongLong(unsigned long long v) + + Return a new :c:type:`PyLongObject` object from a C :c:expr:`unsigned long long`, + or ``NULL`` on failure. + + .. c:function:: PyObject* PyLong_FromInt32(int32_t value) PyObject* PyLong_FromInt64(int64_t value) @@ -81,12 +87,6 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. .. versionadded:: 3.14 -.. c:function:: PyObject* PyLong_FromUnsignedLongLong(unsigned long long v) - - Return a new :c:type:`PyLongObject` object from a C :c:expr:`unsigned long long`, - or ``NULL`` on failure. - - .. c:function:: PyObject* PyLong_FromUInt32(uint32_t value) PyObject* PyLong_FromUInt64(uint64_t value) diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst index 9f84e4bc6dfd91d..73310670ac371c9 100644 --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -77,7 +77,7 @@ memory footprint as a whole. Consequently, under certain circumstances, the Python memory manager may or may not trigger appropriate actions, like garbage collection, memory compaction or other preventive procedures. Note that by using the C library allocator as shown in the previous example, the allocated memory -for the I/O buffer escapes completely the Python memory manager. +for the I/O buffer completely escapes the Python memory manager. .. seealso:: @@ -157,7 +157,7 @@ zero bytes. .. c:function:: void* PyMem_RawCalloc(size_t nelem, size_t elsize) - Allocates *nelem* elements each whose size in bytes is *elsize* and returns + Allocates *nelem* elements each of size *elsize* bytes and returns a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. The memory is initialized to zeros. @@ -235,7 +235,7 @@ In the GIL-enabled build (default build) the .. c:function:: void* PyMem_Calloc(size_t nelem, size_t elsize) - Allocates *nelem* elements each whose size in bytes is *elsize* and returns + Allocates *nelem* elements each of size *elsize* bytes and returns a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. The memory is initialized to zeros. @@ -368,7 +368,7 @@ The :ref:`default object allocator ` uses the .. c:function:: void* PyObject_Calloc(size_t nelem, size_t elsize) - Allocates *nelem* elements each whose size in bytes is *elsize* and returns + Allocates *nelem* elements each of size *elsize* bytes and returns a pointer of type :c:expr:`void*` to the allocated memory, or ``NULL`` if the request fails. The memory is initialized to zeros. diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 20fd66e35a0d4d6..9f68abba66bc5d6 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -247,6 +247,15 @@ Feature slots If ``Py_mod_multiple_interpreters`` is not specified, the import machinery defaults to ``Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED``. + For historical reasons, the values are declared as pointers (``void *``). + When using :c:type:`PySlot` arrays, use :c:macro:`PySlot_DATA` for + :c:macro:`!Py_mod_multiple_interpreters`: + + .. code-block:: c + + PySlot_DATA(Py_mod_multiple_interpreters, + Py_MOD_PER_INTERPRETER_GIL_SUPPORTED) + .. versionadded:: 3.12 .. c:macro:: Py_mod_gil @@ -272,6 +281,14 @@ Feature slots If ``Py_mod_gil`` is not specified, the import machinery defaults to ``Py_MOD_GIL_USED``. + For historical reasons, the values are declared as pointers (``void *``). + When using :c:type:`PySlot` arrays, use :c:macro:`PySlot_DATA` for + :c:macro:`!Py_mod_gil`: + + .. code-block:: c + + PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED) + .. versionadded:: 3.13 diff --git a/Doc/c-api/perfmaps.rst b/Doc/c-api/perfmaps.rst index bd05e628faaaa10..a962c4ee09ad77d 100644 --- a/Doc/c-api/perfmaps.rst +++ b/Doc/c-api/perfmaps.rst @@ -49,3 +49,43 @@ Note that holding an :term:`attached thread state` is not required for these API 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. + +.. c:function:: int PyUnstable_CopyPerfMapFile(const char *parent_filename) + + Open the ``/tmp/perf-$pid.map`` file and append the content of *parent_filename* + to it. + + This function is available on all platforms but only generates output on platforms + that support perf maps (currently only Linux). On other platforms, it does nothing. + + .. versionadded:: 3.13 + +.. c:function:: int PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *code) + + Compile the given code object using the current perf trampoline. + + The "current" trampoline is the one set by the runtime or the most recent + :c:func:`PyUnstable_PerfTrampoline_SetPersistAfterFork` call. + + If no trampoline is set, falls back to normal compilation (no perf map entry). + + :param code: The code object to compile. + :return: 0 on success, -1 on failure. + + .. versionadded:: 3.13 + +.. c:function:: int PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable) + + Set whether the perf trampoline should persist after a fork. + + * If ``enable`` is true (non-zero): perf map file remains open/valid post-fork. + Child process inherits all existing perf map entries. + * If ``enable`` is false (zero): perf map closes post-fork. + Child process gets empty perf map. + + Default: false (clears on fork). + + :param enable: 1 to enable, 0 to disable. + :return: 0 on success, -1 on failure. + + .. versionadded:: 3.13 diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index aeca412610317fe..1ddde5d136b3bb1 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -454,8 +454,8 @@ method. The method will be passed the type object as the first parameter rather than an instance of the type. This is used to create *class methods*, - similar to what is created when using the :func:`classmethod` built-in - function. + similar to what is created when using the :deco:`classmethod` built-in + decorator. .. c:macro:: METH_STATIC @@ -464,7 +464,7 @@ method. The method will be passed ``NULL`` as the first parameter rather than an instance of the type. This is used to create *static methods*, similar to - what is created when using the :func:`staticmethod` built-in function. + what is created when using the :deco:`staticmethod` built-in decorator. One other constant controls whether a method is loaded in place of another definition with the same method name. diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 4771d0a7781bd60..48eb16bd90834ba 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -563,10 +563,10 @@ but need extra remarks for use as slots: :c:member:`Slot ID ` for the name of the type, used to set :c:member:`PyTypeObject.tp_name`. - This slot (or :c:func:`PyType_Spec.name`) is required to create a type. + This slot (or :c:member:`PyType_Spec.name`) is required to create a type. This may not be used in :c:member:`PyType_Spec.slots`. - Use :c:func:`PyType_Spec.name` instead. + Use :c:member:`PyType_Spec.name` instead. .. impl-detail:: @@ -585,7 +585,7 @@ but need extra remarks for use as slots: The value must be positive. This may not be used in :c:member:`PyType_Spec.slots`. - Use :c:func:`PyType_Spec.basicsize` instead. + Use :c:member:`PyType_Spec.basicsize` instead. This slot may not be used with :c:func:`PyType_GetSlot`. Use :c:member:`PyTypeObject.tp_basicsize` instead if needed, but be aware @@ -616,7 +616,7 @@ but need extra remarks for use as slots: :c:macro:`!Py_tp_extra_basicsize` is an error. This may not be used in :c:member:`PyType_Spec.slots`. - Use negative :c:func:`PyType_Spec.basicsize` instead. + Use negative :c:member:`PyType_Spec.basicsize` instead. This slot may not be used with :c:func:`PyType_GetSlot`. @@ -648,7 +648,7 @@ but need extra remarks for use as slots: - With the :c:macro:`Py_TPFLAGS_ITEMS_AT_END` flag. This may not be used in :c:member:`PyType_Spec.slots`. - Use :c:func:`PyType_Spec.itemsize` instead. + Use :c:member:`PyType_Spec.itemsize` instead. This slot may not be used with :c:func:`PyType_GetSlot`. @@ -663,13 +663,44 @@ but need extra remarks for use as slots: :c:func:`PyType_FromSpecWithBases` sets it automatically. This may not be used in :c:member:`PyType_Spec.slots`. - Use negative :c:func:`PyType_Spec.basicsize` instead. + Use negative :c:member:`PyType_Spec.basicsize` instead. This slot may not be used with :c:func:`PyType_GetSlot`. Use :c:func:`PyType_GetFlags` instead. .. versionadded:: 3.15 +.. c:macro:: Py_tp_bases + + :c:member:`Slot ID ` for type flags, used to set + :c:member:`PyTypeObject.tp_bases`. + + The slot can be set to a tuple of type objects which the newly created + type should inherit from, like the "positional arguments" of + a Python :ref:`class definition `. + + Alternately, the slot can be set to a single type object to specify + a single base. + The effect is the same as specifying a one-element tuple. + + .. versionchanged:: 3.15 + + Previously, :c:macro:`!Py_tp_bases` required a tuple of types. + +.. c:macro:: Py_tp_base + + Equivalent to :c:macro:`Py_tp_bases` (with ``s`` at the end). + If both are specified, :c:macro:`!Py_tp_bases` takes priority and + this slot is ignored. + + .. versionchanged:: 3.15 + + Previously, :c:macro:`!Py_tp_base` required a single type, not a tuple. + + .. soft-deprecated:: 3.15 + + When not targetting older Python versions, pefer :c:macro:`!Py_tp_bases`. + The following slots do not correspond to public fields in the underlying structures: diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 38db69e5c6db96d..16dcb880712d244 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1936,12 +1936,12 @@ and :c:data:`PyType_Type` effectively act as defaults.) .. c:member:: PyTypeObject* PyTypeObject.tp_base - .. corresponding-type-slot:: Py_tp_base - An optional pointer to a base type from which type properties are inherited. At this level, only single inheritance is supported; multiple inheritance require dynamically creating a type object by calling the metatype. + For the corresponding slot ID, see :c:macro:`Py_tp_base`. + .. note:: .. from Modules/xxmodule.c @@ -2253,17 +2253,12 @@ and :c:data:`PyType_Type` effectively act as defaults.) .. c:member:: PyObject* PyTypeObject.tp_bases - .. corresponding-type-slot:: Py_tp_bases - Tuple of base types. This field should be set to ``NULL`` and treated as read-only. Python will fill it in when the type is :c:func:`initialized `. - For dynamically created classes, the :c:data:`Py_tp_bases` - :c:type:`slot ` can be used instead of the *bases* argument - of :c:func:`PyType_FromSpecWithBases`. - The argument form is preferred. + For the corresponding slot ID, see :c:macro:`Py_tp_bases`. .. warning:: @@ -2975,13 +2970,13 @@ Buffer Object Structures steps: (1) Check if the request can be met. If not, raise :exc:`BufferError`, - set :c:expr:`view->obj` to ``NULL`` and return ``-1``. + set ``view->obj`` to ``NULL`` and return ``-1``. (2) Fill in the requested fields. (3) Increment an internal counter for the number of exports. - (4) Set :c:expr:`view->obj` to *exporter* and increment :c:expr:`view->obj`. + (4) Set ``view->obj`` to *exporter* and increment ``view->obj``. (5) Return ``0``. @@ -3007,10 +3002,10 @@ Buffer Object Structures schemes can be used: * Re-export: Each member of the tree acts as the exporting object and - sets :c:expr:`view->obj` to a new reference to itself. + sets ``view->obj`` to a new reference to itself. * Redirect: The buffer request is redirected to the root object of the - tree. Here, :c:expr:`view->obj` will be a new reference to the root + tree. Here, ``view->obj`` will be a new reference to the root object. The individual fields of *view* are described in section @@ -3064,7 +3059,7 @@ Buffer Object Structures *view* argument. - This function MUST NOT decrement :c:expr:`view->obj`, since that is + This function MUST NOT decrement ``view->obj``, since that is done automatically in :c:func:`PyBuffer_Release` (this scheme is useful for breaking reference cycles). diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index 401c99ebeb0fec6..634dcbce7a57915 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -1953,7 +1953,7 @@ The following API is deprecated. whether you selected a "narrow" or "wide" Unicode version of Python at build time. - .. deprecated-removed:: 3.13 3.15 + .. deprecated-removed:: 3.13 3.16 .. c:function:: int PyUnicode_READY(PyObject *unicode) diff --git a/Doc/c-api/weakref.rst b/Doc/c-api/weakref.rst index db6ae0a9d4ea3d7..8762a003c5218d3 100644 --- a/Doc/c-api/weakref.rst +++ b/Doc/c-api/weakref.rst @@ -43,7 +43,11 @@ as much as it can. should accept a single parameter, which will be the weak reference object itself. *callback* may also be ``None`` or ``NULL``. If *ob* is not a weakly referenceable object, or if *callback* is not callable, ``None``, or - ``NULL``, this will return ``NULL`` and raise :exc:`TypeError`. + ``NULL``, this will raise :exc:`TypeError` and return ``NULL``. + + .. versionchanged:: next + Raise :exc:`!TypeError` if *callback* is not callable, ``None``, or + ``NULL``. .. seealso:: :c:func:`PyType_SUPPORTS_WEAKREFS` for checking if *ob* is weakly @@ -59,7 +63,11 @@ as much as it can. collected; it should accept a single parameter, which will be the weak reference object itself. *callback* may also be ``None`` or ``NULL``. If *ob* is not a weakly referenceable object, or if *callback* is not callable, - ``None``, or ``NULL``, this will return ``NULL`` and raise :exc:`TypeError`. + ``NULL``, this will raise :exc:`TypeError` and return ``NULL``. + + .. versionchanged:: next + Raise :exc:`!TypeError` if *callback* is not callable, ``None``, or + ``NULL``. .. seealso:: :c:func:`PyType_SUPPORTS_WEAKREFS` for checking if *ob* is weakly diff --git a/Doc/conf.py b/Doc/conf.py index 3856f4fe9b375c4..9b103a594b235cf 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -8,15 +8,13 @@ import os import sys -from importlib import import_module from importlib.util import find_spec # Make our custom extensions available to Sphinx sys.path.append(os.path.abspath('tools/extensions')) sys.path.append(os.path.abspath('includes')) -# Python specific content from Doc/Tools/extensions/pyspecific.py -from pyspecific import SOURCE_URI +from patchlevel import get_header_version_info, get_version_info # General configuration # --------------------- @@ -78,7 +76,7 @@ # We look for the Include/patchlevel.h file in the current Python source tree # and replace the values accordingly. # See Doc/tools/extensions/patchlevel.py -version, release = import_module('patchlevel').get_version_info() +version, release = get_version_info() rst_epilog = f""" .. |python_version_literal| replace:: ``Python {version}`` @@ -555,16 +553,20 @@ r'https://unix.org/version2/whatsnew/lp64_wp.html', ] + # Options for sphinx.ext.extlinks # ------------------------------- +v = get_header_version_info() +branch = "main" if v.releaselevel == "alpha" else f"{v.major}.{v.minor}" + # This config is a dictionary of external sites, # mapping unique short aliases to a base URL and a prefix. # https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html extlinks = { "oss-fuzz": ("https://issues.oss-fuzz.com/issues/%s", "#%s"), "pypi": ("https://pypi.org/project/%s/", "%s"), - "source": (SOURCE_URI, "%s"), + "source": (f"https://github.com/python/cpython/tree/{branch}/%s", "%s"), } extlinks_detect_hardcoded_links = True diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 2d4278c9d97c859..86080fac7163838 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -1,7 +1,7 @@ role,name,added,ifdef_note,struct_abi_kind macro,METH_CLASS,3.2,, macro,METH_COEXIST,3.2,, -macro,METH_FASTCALL,3.7,, +macro,METH_FASTCALL,3.10,, macro,METH_METHOD,3.7,, macro,METH_NOARGS,3.2,, macro,METH_O,3.2,, diff --git a/Doc/deprecations/c-api-pending-removal-in-3.15.rst b/Doc/deprecations/c-api-pending-removal-in-3.15.rst index 789ec83d2d957aa..6d0d47403ff2ed4 100644 --- a/Doc/deprecations/c-api-pending-removal-in-3.15.rst +++ b/Doc/deprecations/c-api-pending-removal-in-3.15.rst @@ -46,88 +46,3 @@ Pending removal in Python 3.15 The `pythoncapi-compat project `__ can be used to get :c:func:`PyConfig_Get` on Python 3.13 and older. - -* Functions to configure Python's initialization, deprecated in Python 3.11: - - * :c:func:`!PySys_SetArgvEx()`: - Set :c:member:`PyConfig.argv` instead. - * :c:func:`!PySys_SetArgv()`: - Set :c:member:`PyConfig.argv` instead. - * :c:func:`!Py_SetProgramName()`: - Set :c:member:`PyConfig.program_name` instead. - * :c:func:`!Py_SetPythonHome()`: - Set :c:member:`PyConfig.home` instead. - * :c:func:`!PySys_ResetWarnOptions`: - Clear :data:`sys.warnoptions` and :data:`!warnings.filters` instead. - - The :c:func:`Py_InitializeFromConfig` API should be used with - :c:type:`PyConfig` instead. - -* Global configuration variables: - - * :c:var:`Py_DebugFlag`: - Use :c:member:`PyConfig.parser_debug` or - :c:func:`PyConfig_Get("parser_debug") ` instead. - * :c:var:`Py_VerboseFlag`: - Use :c:member:`PyConfig.verbose` or - :c:func:`PyConfig_Get("verbose") ` instead. - * :c:var:`Py_QuietFlag`: - Use :c:member:`PyConfig.quiet` or - :c:func:`PyConfig_Get("quiet") ` instead. - * :c:var:`Py_InteractiveFlag`: - Use :c:member:`PyConfig.interactive` or - :c:func:`PyConfig_Get("interactive") ` instead. - * :c:var:`Py_InspectFlag`: - Use :c:member:`PyConfig.inspect` or - :c:func:`PyConfig_Get("inspect") ` instead. - * :c:var:`Py_OptimizeFlag`: - Use :c:member:`PyConfig.optimization_level` or - :c:func:`PyConfig_Get("optimization_level") ` instead. - * :c:var:`Py_NoSiteFlag`: - Use :c:member:`PyConfig.site_import` or - :c:func:`PyConfig_Get("site_import") ` instead. - * :c:var:`Py_BytesWarningFlag`: - Use :c:member:`PyConfig.bytes_warning` or - :c:func:`PyConfig_Get("bytes_warning") ` instead. - * :c:var:`Py_FrozenFlag`: - Use :c:member:`PyConfig.pathconfig_warnings` or - :c:func:`PyConfig_Get("pathconfig_warnings") ` instead. - * :c:var:`Py_IgnoreEnvironmentFlag`: - Use :c:member:`PyConfig.use_environment` or - :c:func:`PyConfig_Get("use_environment") ` instead. - * :c:var:`Py_DontWriteBytecodeFlag`: - Use :c:member:`PyConfig.write_bytecode` or - :c:func:`PyConfig_Get("write_bytecode") ` instead. - * :c:var:`Py_NoUserSiteDirectory`: - Use :c:member:`PyConfig.user_site_directory` or - :c:func:`PyConfig_Get("user_site_directory") ` instead. - * :c:var:`Py_UnbufferedStdioFlag`: - Use :c:member:`PyConfig.buffered_stdio` or - :c:func:`PyConfig_Get("buffered_stdio") ` instead. - * :c:var:`Py_HashRandomizationFlag`: - Use :c:member:`PyConfig.use_hash_seed` - and :c:member:`PyConfig.hash_seed` or - :c:func:`PyConfig_Get("hash_seed") ` instead. - * :c:var:`Py_IsolatedFlag`: - Use :c:member:`PyConfig.isolated` or - :c:func:`PyConfig_Get("isolated") ` instead. - * :c:var:`Py_LegacyWindowsFSEncodingFlag`: - Use :c:member:`PyPreConfig.legacy_windows_fs_encoding` or - :c:func:`PyConfig_Get("legacy_windows_fs_encoding") ` instead. - * :c:var:`Py_LegacyWindowsStdioFlag`: - Use :c:member:`PyConfig.legacy_windows_stdio` or - :c:func:`PyConfig_Get("legacy_windows_stdio") ` instead. - * :c:var:`!Py_FileSystemDefaultEncoding`, :c:var:`!Py_HasFileSystemDefaultEncoding`: - Use :c:member:`PyConfig.filesystem_encoding` or - :c:func:`PyConfig_Get("filesystem_encoding") ` instead. - * :c:var:`!Py_FileSystemDefaultEncodeErrors`: - Use :c:member:`PyConfig.filesystem_errors` or - :c:func:`PyConfig_Get("filesystem_errors") ` instead. - * :c:var:`!Py_UTF8Mode`: - Use :c:member:`PyPreConfig.utf8_mode` or - :c:func:`PyConfig_Get("utf8_mode") ` instead. - (see :c:func:`Py_PreInitialize`) - - The :c:func:`Py_InitializeFromConfig` API should be used with - :c:type:`PyConfig` to set these options. Or :c:func:`PyConfig_Get` can be - used to get these options at runtime. diff --git a/Doc/deprecations/c-api-pending-removal-in-3.16.rst b/Doc/deprecations/c-api-pending-removal-in-3.16.rst index 9453f83799c43d7..fe2d91cf316b18f 100644 --- a/Doc/deprecations/c-api-pending-removal-in-3.16.rst +++ b/Doc/deprecations/c-api-pending-removal-in-3.16.rst @@ -1,4 +1,87 @@ Pending removal in Python 3.16 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* The bundled copy of ``libmpdec``. +* Functions to configure Python's initialization, deprecated in Python 3.11: + + * :c:func:`!PySys_SetArgvEx()`: + Set :c:member:`PyConfig.argv` instead. + * :c:func:`!PySys_SetArgv()`: + Set :c:member:`PyConfig.argv` instead. + * :c:func:`!Py_SetProgramName()`: + Set :c:member:`PyConfig.program_name` instead. + * :c:func:`!Py_SetPythonHome()`: + Set :c:member:`PyConfig.home` instead. + + The :c:func:`Py_InitializeFromConfig` API should be used with + :c:type:`PyConfig` instead. + +* Global configuration variables: + + * :c:var:`Py_DebugFlag`: + Use :c:member:`PyConfig.parser_debug` or + :c:func:`PyConfig_Get("parser_debug") ` instead. + * :c:var:`Py_VerboseFlag`: + Use :c:member:`PyConfig.verbose` or + :c:func:`PyConfig_Get("verbose") ` instead. + * :c:var:`Py_QuietFlag`: + Use :c:member:`PyConfig.quiet` or + :c:func:`PyConfig_Get("quiet") ` instead. + * :c:var:`Py_InteractiveFlag`: + Use :c:member:`PyConfig.interactive` or + :c:func:`PyConfig_Get("interactive") ` instead. + * :c:var:`Py_InspectFlag`: + Use :c:member:`PyConfig.inspect` or + :c:func:`PyConfig_Get("inspect") ` instead. + * :c:var:`Py_OptimizeFlag`: + Use :c:member:`PyConfig.optimization_level` or + :c:func:`PyConfig_Get("optimization_level") ` instead. + * :c:var:`Py_NoSiteFlag`: + Use :c:member:`PyConfig.site_import` or + :c:func:`PyConfig_Get("site_import") ` instead. + * :c:var:`Py_BytesWarningFlag`: + Use :c:member:`PyConfig.bytes_warning` or + :c:func:`PyConfig_Get("bytes_warning") ` instead. + * :c:var:`Py_FrozenFlag`: + Use :c:member:`PyConfig.pathconfig_warnings` or + :c:func:`PyConfig_Get("pathconfig_warnings") ` instead. + * :c:var:`Py_IgnoreEnvironmentFlag`: + Use :c:member:`PyConfig.use_environment` or + :c:func:`PyConfig_Get("use_environment") ` instead. + * :c:var:`Py_DontWriteBytecodeFlag`: + Use :c:member:`PyConfig.write_bytecode` or + :c:func:`PyConfig_Get("write_bytecode") ` instead. + * :c:var:`Py_NoUserSiteDirectory`: + Use :c:member:`PyConfig.user_site_directory` or + :c:func:`PyConfig_Get("user_site_directory") ` instead. + * :c:var:`Py_UnbufferedStdioFlag`: + Use :c:member:`PyConfig.buffered_stdio` or + :c:func:`PyConfig_Get("buffered_stdio") ` instead. + * :c:var:`Py_HashRandomizationFlag`: + Use :c:member:`PyConfig.use_hash_seed` + and :c:member:`PyConfig.hash_seed` or + :c:func:`PyConfig_Get("hash_seed") ` instead. + * :c:var:`Py_IsolatedFlag`: + Use :c:member:`PyConfig.isolated` or + :c:func:`PyConfig_Get("isolated") ` instead. + * :c:var:`Py_LegacyWindowsFSEncodingFlag`: + Use :c:member:`PyPreConfig.legacy_windows_fs_encoding` or + :c:func:`PyConfig_Get("legacy_windows_fs_encoding") ` instead. + * :c:var:`Py_LegacyWindowsStdioFlag`: + Use :c:member:`PyConfig.legacy_windows_stdio` or + :c:func:`PyConfig_Get("legacy_windows_stdio") ` instead. + * :c:var:`!Py_FileSystemDefaultEncoding`, :c:var:`!Py_HasFileSystemDefaultEncoding`: + Use :c:member:`PyConfig.filesystem_encoding` or + :c:func:`PyConfig_Get("filesystem_encoding") ` instead. + * :c:var:`!Py_FileSystemDefaultEncodeErrors`: + Use :c:member:`PyConfig.filesystem_errors` or + :c:func:`PyConfig_Get("filesystem_errors") ` instead. + * :c:var:`!Py_UTF8Mode`: + Use :c:member:`PyPreConfig.utf8_mode` or + :c:func:`PyConfig_Get("utf8_mode") ` instead. + (see :c:func:`Py_PreInitialize`) + + The :c:func:`Py_InitializeFromConfig` API should be used with + :c:type:`PyConfig` to set these options. Or :c:func:`PyConfig_Get` can be + used to get these options at runtime. + +* :c:type:`Py_UNICODE` which was deprecated by :pep:`393`. diff --git a/Doc/deprecations/c-api-pending-removal-in-3.18.rst b/Doc/deprecations/c-api-pending-removal-in-3.18.rst index 022aee93aa70c47..820334ee43c82e4 100644 --- a/Doc/deprecations/c-api-pending-removal-in-3.18.rst +++ b/Doc/deprecations/c-api-pending-removal-in-3.18.rst @@ -40,6 +40,10 @@ Pending removal in Python 3.18 * :c:func:`!_PyUnicodeWriter_PrepareKind`: (no replacement). * :c:func:`!_Py_HashPointer`: use :c:func:`Py_HashPointer`. * :c:func:`!_Py_fopen_obj`: use :c:func:`Py_fopen`. + * :c:func:`PyGen_New`: (no replacement). + * :c:func:`PyGen_NewWithQualName`: (no replacement). + * :c:func:`PyCoro_New`: (no replacement). + * :c:func:`PyAsyncGen_New`: (no replacement). The `pythoncapi-compat project `__ can be used to get diff --git a/Doc/deprecations/index.rst b/Doc/deprecations/index.rst index 50e1b126fd1346d..0ac0a0289d5fd40 100644 --- a/Doc/deprecations/index.rst +++ b/Doc/deprecations/index.rst @@ -1,8 +1,6 @@ Deprecations ============ -.. include:: pending-removal-in-3.15.rst - .. include:: pending-removal-in-3.16.rst .. include:: pending-removal-in-3.17.rst @@ -22,8 +20,6 @@ Deprecations C API deprecations ------------------ -.. include:: c-api-pending-removal-in-3.15.rst - .. include:: c-api-pending-removal-in-3.16.rst .. include:: c-api-pending-removal-in-3.18.rst diff --git a/Doc/deprecations/pending-removal-in-3.15.rst b/Doc/deprecations/pending-removal-in-3.15.rst index 1d9a3095813a6de..5c0e592f4caeda1 100644 --- a/Doc/deprecations/pending-removal-in-3.15.rst +++ b/Doc/deprecations/pending-removal-in-3.15.rst @@ -8,11 +8,6 @@ Pending removal in Python 3.15 is deprecated. In Python 3.15, ``__cached__`` will cease to be set or take into consideration by the import system or standard library. (:gh:`97879`) - * Setting :attr:`~module.__package__` on a module while - failing to set :attr:`__spec__.parent ` - is deprecated. In Python 3.15, :attr:`!__package__` will cease to be set or - take into consideration by the import system or standard library. (:gh:`97879`) - * :mod:`ctypes`: * The undocumented :func:`!ctypes.SetPointerType` function @@ -82,7 +77,7 @@ Pending removal in Python 3.15 Use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})`` to create a TypedDict with zero field. - * The :func:`!typing.no_type_check_decorator` decorator function + * The :deco:`!typing.no_type_check_decorator` decorator function has been deprecated since Python 3.13. After eight years in the :mod:`typing` module, it has yet to be supported by any major type checker. diff --git a/Doc/deprecations/pending-removal-in-3.16.rst b/Doc/deprecations/pending-removal-in-3.16.rst index 7606daba16dcf82..5a28cc766a95961 100644 --- a/Doc/deprecations/pending-removal-in-3.16.rst +++ b/Doc/deprecations/pending-removal-in-3.16.rst @@ -8,6 +8,13 @@ Pending removal in Python 3.16 is deprecated. In Python 3.16, :attr:`!__loader__` will cease to be set or taken into consideration by the import system or the standard library. + * Setting :attr:`~module.__package__` on a module while + failing to set :attr:`__spec__.parent ` + is deprecated. In Python 3.16, :attr:`!__package__` will cease to be + taken into consideration by the import system or standard library. (:gh:`97879`) + +* The bundled copy of ``libmpdec``. + * :mod:`array`: * The ``'u'`` format code (:c:type:`wchar_t`) diff --git a/Doc/extending/first-extension-module.rst b/Doc/extending/first-extension-module.rst index 894f5bdbb8f09c2..55a772e2aca24f5 100644 --- a/Doc/extending/first-extension-module.rst +++ b/Doc/extending/first-extension-module.rst @@ -164,7 +164,7 @@ Then, create ``meson.build`` containing the following: .. note:: - See `meson-python documentation `_ for details on + See the `meson-python documentation `_ for details on configuration. Now, build install the *project in the current directory* (``.``) via ``pip``: diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 591565cbc013575..c2f8f72ee1f2c4b 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -2003,7 +2003,7 @@ How do I cache method calls? ---------------------------- The two principal tools for caching methods are -:func:`functools.cached_property` and :func:`functools.lru_cache`. The +:deco:`functools.cached_property` and :deco:`functools.lru_cache`. The former stores results at the instance level and the latter at the class level. diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 56bc799d945e7b0..3ac622709241717 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -413,7 +413,7 @@ Glossary decorator A function returning another function, usually applied as a function transformation using the ``@wrapper`` syntax. Common examples for - decorators are :func:`classmethod` and :func:`staticmethod`. + decorators are :deco:`classmethod` and :deco:`staticmethod`. The decorator syntax is merely syntactic sugar, the following two function definitions are semantically equivalent:: @@ -676,7 +676,7 @@ Glossary determined by the dispatch algorithm. See also the :term:`single dispatch` glossary entry, the - :func:`functools.singledispatch` decorator, and :pep:`443`. + :deco:`functools.singledispatch` decorator, and :pep:`443`. generic type A :term:`type` that can be parameterized; typically a diff --git a/Doc/howto/abi3t-migration.rst b/Doc/howto/abi3t-migration.rst new file mode 100644 index 000000000000000..ed7a324c4af6f0a --- /dev/null +++ b/Doc/howto/abi3t-migration.rst @@ -0,0 +1,614 @@ +.. highlight:: c + +.. _abi3t-migration-howto: + +****************************************************** +Migrating to Stable ABI for free threading (``abi3t``) +****************************************************** + +Starting with the 3.15 release, CPython supports a variant of the Stable ABI +that supports :term:`free-threaded ` Python: +Stable ABI for Free-Threaded Builds, or ``abi3t`` for short. +This document describes how to adapt C API extensions to support free threading. + +Why do this +=========== + +The typical reason to use Stable ABI is to reduce the number of artifacts that +you need to build and distribute for each version of your library. + +Without the Stable ABI, you must build a separate shared library, and typically +a *wheel* distribution, for each feature version of CPython you wish +to support. +For example, each tag in the following table represents a separate +library/wheel: + ++-----------------+-----------------------+------------------------+ +| CPython version | Non-free-threaded | Free-threaded | ++=================+=======================+========================+ +| 3.12 | ``cpython-312`` | --- | ++-----------------+-----------------------+------------------------+ +| 3.13 | ``cpython-313`` | ``cpython-313t`` | ++-----------------+-----------------------+------------------------+ +| 3.14 | ``cpython-314`` | ``cpython-314t`` | ++-----------------+-----------------------+------------------------+ +| 3.15 | ``cpython-315`` | ``cpython-315t`` | ++-----------------+-----------------------+------------------------+ +| 3.16 | ``cpython-316`` | ``cpython-316t`` | ++-----------------+-----------------------+------------------------+ +| Later versions | :samp:`cpython-3{XX}` | :samp:`cpython-3{XX}t` | ++-----------------+-----------------------+------------------------+ + +That's a lot of builds, especially when multiplied by the number +of supported platforms. + +With the Stable ABI (``abi3``, introduced in CPython 3.2), a single extension +(per platform) can cover all *non-free-threaded* builds of CPython: + ++-----------------+-------------------+------------------------+ +| CPython version | Non-free-threaded | Free-threaded | ++=================+===================+========================+ +| 3.12 | ``abi3`` | --- | ++-----------------+ +------------------------+ +| 3.13 | | ``cpython-313t`` | ++-----------------+ +------------------------+ +| 3.14 | | ``cpython-314t`` | ++-----------------+ +------------------------+ +| 3.15 | | ``cpython-315t`` | ++-----------------+ +------------------------+ +| 3.16 | | ``cpython-316t`` | ++-----------------+ +------------------------+ +| Later versions | | :samp:`cpython-3{XX}t` | ++-----------------+-------------------+------------------------+ + +The Stable ABI for free-threaded builds (``abi3t``), introduced in +CPython 3.15, does the same for free-threaded builds. +And it's compatible with non-free-threaded ones as well: + ++-----------------+-------------------+------------------+ +| CPython version | Non-free-threaded | Free-threaded | ++=================+===================+==================+ +| 3.12 | ``abi3`` * | --- | ++-----------------+ +------------------+ +| 3.13 | | ``cpython-313t`` | ++-----------------+ +------------------+ +| 3.14 | | ``cpython-314t`` | ++-----------------+-------------------+------------------+ +| 3.15 | ``abi3t`` | ++-----------------+ + +| 3.16 | | ++-----------------+ + +| Later versions | | ++-----------------+-------------------+------------------+ + +\* (As above, the ``abi3`` extension is compatible with all non-free-threaded +builds; even the 3.15+ ones that this table "attributes" to ``abi3t``.) + +Why *not* do this +----------------- + +There are two main downsides to Stable ABI. + +First, you extension may become slower, since Stable ABI prioritizes +compatibility over performance. +The difference is usually not noticeable, and often can be mitigated by +using the same source to build both a Stable ABI build and a few +version-specific ones for "tier 1" CPython versions. + +Second, not all of the C API is available. +Extensions need to be ported to build for Stable ABI, which may be difficult +or, in rare cases, impossible. + +Specifically, ``abi3t`` requires APIs added in CPython 3.15. +If you want to build your extension for older versions of CPython from the +same source, you have two main options: + +- Use preprocessor conditionals. + + When following this guide, use ``#ifdef Py_TARGET_ABI3T`` blocks whenever + you are told to do a change that breaks the build on CPython versions you + care about. Keep the pre-existing code in ``#else`` blocks. + + For hand-written C extensions, this approach is reasonable down to + CPython 3.12, due to additions introduced in :pep:`697`. + Keeping compatibility with 3.11 and below may be worth it for code + generators (for example, Cython). + +- Do not port to ``abi3t``, and continue building separate extensions for + each version of CPython, until you can drop support for the older versions. + + This is a valid approach. Not all extensions need to switch to ``abi3t`` + right now. + + +Prerequisites +============= + +This guide assumes that you have an extension written directly in C (or C++), +which you want to port to ``abi3t``. + +If your extenstion uses a code generator (like Cython) or language binding +(like PyO3), it's best to wait until that tool has support for ``abi3t``. +If you maintain such a tool, you might be able to adapt the instructions +here for your tool. + +Non-free-threaded Stable ABI +---------------------------- + +Your extension should support the Stable ABI (``abi3t``). +If not, either port it first, or follow this guide but be prepared to fix +issues it does not mention. + +Free-threading support +---------------------- + +While it's technically not a hard prerequisite, you will most likely want to +prepare your extension for free threading before you port it to ``abi3t``. +See :ref:`freethreading-extensions-howto` for instructions. + +.. seealso:: + + `Porting Extension Modules to Support Free-Threading + `__: + A community-maintained porting guide for extension authors. + +Isolating extension modules +--------------------------- + +Your module should use :ref:`multi-phase initialization `, +and it should either be isolated or limit itself to be loaded at most once +per process. +If it is not your case, follow :ref:`isolating-extensions-howto` first. +(See the :ref:`opt-out section ` for a shortcut.) + +Avoiding variable-sized types +----------------------------- + +If your extension defines variable-sized types (using :c:macro:`Py_tp_itemsize` +or :c:member:`PyTypeObject.tp_itemsize`), it cannot be ported to +``abi3t`` 3.15. + + +Setting up the build +==================== + +If you use a build tool (such as setuptools, meson-python, scikit-build-core), +search its documentation for a way to select ``abi3t``. +At the time of writing, not all of them have this; but if your tool does, +use it. +You may want to verify that it set the right flag by temporarily adding the +following just after ``#include ``:: + + #if Py_TARGET_ABI3T+0 <= 0x30f0000 + #error "abi3t define is not set!" + #endif + +This should result in a different error than "``abt3t`` define is not set". + +.. note:: + + If your build tool doesn't support ``abi3t`` yet, set the following macro + before including ``Python.h``:: + + #define Py_TARGET_ABI3T 0x30f0000 + + or specify it as a compiler flag, for example:: + + -DPy_TARGET_ABI3T=0x30f0000 + + Once your extension builds with this setting, it will be compatible with + CPython 3.15 and above. + + If you set this macro manually, you will later need to name and tag the + resulting extension manually as well. + This is covered in :ref:`abi3t-migration-tagging` below. + +This guide will ask you to make a series of changes. +After each one, verify that your extension still builds in the original +(non-``abi3t``) configuration, and ideally run tests on all Python +versions you support. +This will ensure that nothing breaks as you are porting. + + +Module export hook +================== + +Unless you've done this step already, your extension module defines a +:ref:`module initialization function ` +named :samp:`PyInit_{}`. +You will need to port it to a :ref:`module export hook `, +:samp:`PyModExport_{}`, a feature added in CPython 3.15 in +:pep:`793`. + +Your existing init function should look like this (with your own names +for ```` and ````): + +.. code-block:: + :class: bad + + PyMODINIT_FUNC + PyInit_(void) + { + return PyModuleDef_Init(&); + } + +If there is some code before the ``return``, move it to +a :c:macro:`Py_mod_create` or :c:macro:`Py_mod_exec` slot function. +See the :ref:`PyInit documentation ` for related information. + +The function references a ``PyModuleDef`` object (```` in the code +above). +Its definition should be similar to the following, with different values +and perhaps some fields unnnamed or left out: + +.. code-block:: + :class: bad + + static PyModuleDef = { + PyModuleDef_HEAD_INIT, + .m_name = "my_module", + .m_doc = "my docstring", + .m_size = sizeof(my_state_struct), + .m_methods = my_methods, + .m_slots = my_slots, + .m_traverse = my_traverse, + .m_clear = my_clear, + .m_free = my_free, + }; + +Remove this definition and the ``PyInit`` function (or put them in +an ``#ifndef Py_TARGET_ABI3T`` block, to retain backwards compatibility), +and replace them with the following: + +.. code-block:: + :class: good + + PyABIInfo_VAR(abi_info); + + static PySlot my_slot_array[] = { + PySlot_STATIC_DATA(Py_mod_abi, &abi_info), + PySlot_STATIC_DATA(Py_mod_name, "my_module"), + PySlot_STATIC_DATA(Py_mod_doc, "my docstring"), + PySlot_SIZE(Py_mod_state_size, sizeof(my_state_struct)), + PySlot_STATIC_DATA(Py_mod_methods, my_methods), + PySlot_STATIC_DATA(Py_mod_slots, my_slots), + PySlot_FUNC(Py_mod_state_traverse, my_traverse), + PySlot_FUNC(Py_mod_state_clear, my_clear), + PySlot_FUNC(Py_mod_state_free, my_free), + PySlot_END + }; + + PyMODEXPORT_FUNC + PyModExport_(void) + { + return my_slot_array; + } + +Leave out any fields that were missing (except the new :c:macro:`Py_mod_abi`), +and substitute your own values. + +See the :c:type:`PySlot` and :c:ref:`export hook ` +documentation for details on this API. + +Associated ``PyModuleDef`` +-------------------------- + +Since the new API does not use a :c:type:`!PyModuleDef` structure, a definition +will not be associated with the resulting module. +This changes the behavior of the following functions: + +- :c:func:`PyModule_GetDef` +- :c:func:`PyType_GetModuleByDef` + +Check your code for these. +If you do not use them, you can skip this section. + +These functions are typically used for two purposes: + +1. To get the definition the module was created with. + This is no longer possible using the new API. + Modules no longer keep a reference to the definition, so you will need to + figure out a different way to pass the relevant data around. + +.. _abi3t-migration-module-token: + +2. To check if a given module object is “yours”. + This use case is now served by :ref:`module tokens ` -- + opaque pointers that identify a module. + To use a token, declare (or reuse) a unique static variable, for example: + + .. code-block:: + :class: good + + static char my_token; + + and add a pointer to it in a new entry to your module's ``PySlot`` array: + + .. code-block:: + :class: good + :emphasize-lines: 3 + + static PySlot my_slot_array[] = { + ... + PySlot_STATIC_DATA(Py_mod_token, &my_token), + PySlot_END + } + + Then, switch from :c:func:`PyModule_GetDef` calls such as: + + .. code-block:: + :class: bad + + PyModuleDef *def = PyModule_GetDef(module); + + to :c:func:`PyModule_GetToken` (which uses an output argument and may fail + with an exception): + + .. code-block:: + :class: good + + void *token; + if (PyModule_GetToken(module, &token) < 0) { + /* handle error */ + } + + and from :c:func:`PyType_GetModuleByDef` calls such as: + + .. code-block:: + :class: bad + + PyObject *module = PyType_GetModuleByDef(type, my_def); + /* handle error; use module */ + + to :c:func:`PyType_GetModuleByToken` (which returns a strong reference): + + .. code-block:: + :class: good + + PyObject *module = PyType_GetModuleByToken(type, my_token); + /* handle error; use module */ + Py_XDECREF(module); + +``PyObject`` opaqueness +======================= + +The :c:type:`PyObject` and :c:type:`PyVarObject` structures are opaque +in ``abi3t``. + +Accessing their members is prohibited. +If you do this, switch to getter/setter functions mentioned in +their documentation: + +- :c:member:`PyObject.ob_type` +- :c:member:`PyObject.ob_refcnt` +- :c:member:`PyVarObject.ob_size` + +Also, the *size* of the :c:type:`PyObject` structures is +unknown to the compiler. +It can -- and *does* -- change between different CPython builds. + +.. note:: + + While the size is available at runtime (for example as + ``sys.getsizeof(object())`` in Python code), you should resist the + temptation to calculate pointer offsets from it. + The object memory layout is subject to change in future + ``abi3t`` implementations. + + +Custom type definitions +----------------------- + +Since :c:type:`!PyObject` is opaque, the traditional way of defining +custom types no longer works: + +.. code-block:: + :class: bad + + typedef struct { + PyObject_HEAD // expands to `PyObject ob_base;` which has unknown size + + int my_data; + } CustomObject; + + static PyType_Spec CustomType_spec = { + ... + .basicsize = sizeof(CustomObject), + ... + }; + +Most likely, all your class definitions, *and* all code that accesses +your classes' data, will need to be rewritten. +This will probably be the biggest change you need to support ``abi3t``. + +For each such type, instead of defining a ``struct`` for the entire instance, +define one with only the “additional” fields -- ones specific to your class, +not its superclasses: + +.. code-block:: + :class: good + + typedef struct { + int my_data; + } CustomObjectData; + +Change the name. +Almost all code that uses the struct will need to change +(notably, pointers to the new structure cannot be cast to/from ``PyObject*``), +and changing the name will highlight the usages as compiler errors. +(If you use ``typeof``, C++ ``auto``, or similar ways to avoid +typing the type name, this won't work. Be extra careful, and consider running +tools to detect undefined behavior.) + +Then, to create the class, use *negative* ``basicsize`` to indicate +“extra” storage space rather than *total* instance size: + +.. code-block:: + :class: good + + static PyType_Spec CustomType_spec = { + ... + .basicsize = -sizeof(CustomObjectData), /* note the minus sign */ + ... + }; + +If you use :c:macro:`Py_tp_members`, set the :c:macro:`Py_RELATIVE_OFFSET` +flag on each member and specify the :c:member:`~PyMemberDef.offset` +relative to your new struct. + + +Custom type data access +----------------------- + +Then comes the hard part: in all code that needs to access this struct, +you will need an additional :c:func:`PyObject_GetTypeData` call to +retrieve a ``CustomObjectData *`` pointer from ``PyObject *``: + +.. code-block:: + :class: good + + PyObject *obj = ...; + CustomObjectData *data = PyObject_GetTypeData(obj, cls); + +Note that this call requires the *type object* for your class (``cls``). + +If your class is not subclassable (that is, it does not use the +:c:macro:`Py_TPFLAGS_BASETYPE` flag), ``cls`` will be ``Py_TYPE(obj)``. +Otherwise, **DO NOT USE** ``Py_TYPE`` with :c:func:`!PyObject_GetTypeData`: +it might return memory reserved to an unrelated subclass! +For example, if a user makes a subclass like this: + +.. code-block:: python + + class Sub(YourCustomClass): + __slots__ = ('a', 'b') + +then ``Py_TYPE(obj)`` is ``YourCustomClass``, and the underlying memory may +look like this: + +.. code-block:: text + + ╭─ PyObject *obj + │ ╭─ the pointer you want + │ │ ╭─ PyObject_GetTypeData(obj, Py_TYPE(obj)) + ▼ ▼ ▼ + ┌──────────┬───┬────────────────┬───┬─────────────┬───┬─────────────┐ + │ PyObject │...│ CustomTypeData │...│ PyObject *a │...│ PyObject *b │ + └──────────┴───┴────────────────┴───┴─────────────┴───┴─────────────┘ + +(Ellipses indicate possible padding. +Note that this memory layout is not guaranteed: future versions of Python may +add different padding or even switch the order of the structures.) + +There are two main ways to get the right class: + +- In instance methods, your implementation may use the :c:type:`PyCMethod` + signature (and the :c:macro:`METH_METHOD` bit in + :c:member:`PyMethodDef.ml_flags`), + and get the class as the ``defining_class`` argument. +- Otherwise, give your class a unique static token using the + :c:macro:`Py_tp_token` slot, and use: + + .. code-block:: + :class: good + + PyTypeObject cls; + if (PyType_GetBaseByToken(Py_TYPE(obj), my_tp_token, &cls) < 0) { + /* handle error */ + } + CustomObjectData *data = PyObject_GetTypeData(obj, cls); + + Type tokens work similarly to module tokens covered :ref:`earlier in this + guide `. + + + +Avoid build-time conditionals +============================= + +Check your code for API that identifies the version of Python used to +*build* your extension. +This no longer corresponds to the Python your extension runs on, so code +that uses this information often needs changing. +The macros to check for are: + +- :c:macro:`PY_VERSION_HEX`, :c:macro:`PY_MAJOR_VERSION`, + :c:macro:`PY_MINOR_VERSION`: + + - to get the run-time version, use :c:data:`Py_Version`; + - to determine what C API is available, use :c:macro:`Py_TARGET_ABI3T`. + This macro is set to the minimum supported version. + +- :c:macro:`Py_GIL_DISABLED`: under ``abi3t``, this macro is always defined. + Code that works with free-threaded Python *should* also work with + the GIL enabled (since the GIL can be enabled at run time), + and usually *does* (unless it, for some reason, requires more than one + :term:`attached thread state ` at one time). + + +Further code changes +==================== + +If you are still left with compiler errors or warnings, find a way to fix them. +Alas, this guide is limited, and cannot cover all possible code +changes extensions may need. + +If you find a problem that other extension authors might run into, +consider :ref:`reporting an issue ` (or sending +a pull request) for this guide. + +It is possible your issue cannot be fixed for the current version of ``abi3t``. +In that case, reporting it may help it get prioritized for the next version +of CPython. + + +.. _abi3t-migration-tagging: + +Tagging and distribution +======================== + +If you are using a build tool with ``abi3t`` support, your extension is ready, +but you might want to check that it was built correctly. + +Extensions built with ``abi3t`` should have the following extension: + +- On Windows: ``.pyd`` (like any other extension); +- Linux, macOS, and other systems that use the ``.so`` suffix: ``.abi3t.so`` + (**not** ``.cpython-315t.so`` or ``.abi3.so``). + Note that both free-threaded and non-free-threaded builds will + load ``.abi3t.so`` extensions; +- Other systems: consult your distributor, and perhaps update this guide. + +If you distribute the extension as a *wheel*, use the following tags: + +* Python tag: :samp:`cp3{XX}`, where *XX* is the minimum Python version + the extension is built for. + (For example, ``cp315`` if you set ``Py_TARGET_ABI3T`` to ``0x30f0000``. + See :ref:`abi3-compiling` for more values.) +* ABI tag: ``abi3.abi3t``. This is a *compressed tag set* that indicates + support for both non-free-threaded and free-threaded builds. + +For example, the wheel filename may look like this: + +.. code-block:: text + + myproject-1.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl + +.. seealso:: `Platform Compatibility Tags `__ in the PyPA package distribution metadata. + +If the filename or tags are incorrect, fix them. + + +Testing +======= + +Note that when you build an extension compatible with multiple versions of +CPython, you should always *test* it with each version it supports (for +example, 3.15, 3.16, and so on). +Stable ABI only guarantees *ABI* compatibility; there may also be behavior +changes -- both intentional ones (covered by :pep:`387`) and bugs. + +Be sure to run tests on both free-threaded and non-free-threaded builds +of CPython. + +If they pass, congratulations! You have an ``abi3t`` extension. diff --git a/Doc/howto/annotations.rst b/Doc/howto/annotations.rst index d7deb6c6bc1768f..fcc4fe838c783ba 100644 --- a/Doc/howto/annotations.rst +++ b/Doc/howto/annotations.rst @@ -4,8 +4,6 @@ Annotations Best Practices ************************** -:author: Larry Hastings - .. topic:: Abstract This document is designed to encapsulate the best practices @@ -154,7 +152,7 @@ on an arbitrary object ``o``: as the ``globals``, and ``dict(vars(o))`` as the ``locals``, when calling :func:`eval`. * If ``o`` is a wrapped callable using :func:`functools.update_wrapper`, - :func:`functools.wraps`, or :func:`functools.partial`, iteratively + :deco:`functools.wraps`, or :func:`functools.partial`, iteratively unwrap it by accessing either ``o.__wrapped__`` or ``o.func`` as appropriate, until you have found the root unwrapped function. * If ``o`` is a callable (but not a class), use diff --git a/Doc/howto/argparse.rst b/Doc/howto/argparse.rst index 902c50de00803c5..0cb8c5cc3ebd369 100644 --- a/Doc/howto/argparse.rst +++ b/Doc/howto/argparse.rst @@ -4,8 +4,6 @@ Argparse Tutorial ***************** -:author: Tshepang Mbambo - .. currentmodule:: argparse This tutorial is intended to be a gentle introduction to :mod:`argparse`, the diff --git a/Doc/howto/curses.rst b/Doc/howto/curses.rst index 816639552d7cd6d..e5f85e0110321c8 100644 --- a/Doc/howto/curses.rst +++ b/Doc/howto/curses.rst @@ -6,9 +6,6 @@ .. currentmodule:: curses -:Author: A.M. Kuchling, Eric S. Raymond -:Release: 2.04 - .. topic:: Abstract diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index a7a68281860cb5d..7233898860ada14 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -4,9 +4,6 @@ Descriptor Guide ================ -:Author: Raymond Hettinger -:Contact: - .. Contents:: @@ -28,7 +25,7 @@ This guide has four major sections: 4) The last section has pure Python equivalents for built-in descriptors that are written in C. Read this if you're curious about how functions turn into bound methods or about the implementation of common tools like - :func:`classmethod`, :func:`staticmethod`, :func:`property`, and + :deco:`classmethod`, :deco:`staticmethod`, :deco:`property`, and :term:`__slots__`. @@ -317,8 +314,8 @@ Descriptors invert that relationship and allow the data being looked-up to have a say in the matter. Descriptors are used throughout the language. It is how functions turn into -bound methods. Common tools like :func:`classmethod`, :func:`staticmethod`, -:func:`property`, and :func:`functools.cached_property` are all implemented as +bound methods. Common tools like :deco:`classmethod`, :deco:`staticmethod`, +:deco:`property`, and :deco:`functools.cached_property` are all implemented as descriptors. @@ -1326,7 +1323,7 @@ example calls are unexciting: 30 Using the non-data descriptor protocol, a pure Python version of -:func:`staticmethod` would look like this: +:deco:`staticmethod` would look like this: .. testcode:: @@ -1466,7 +1463,7 @@ Now a new dictionary of unique keys can be constructed like this: {'a': None, 'b': None, 'r': None, 'c': None, 'd': None} Using the non-data descriptor protocol, a pure Python version of -:func:`classmethod` would look like this: +:deco:`classmethod` would look like this: .. testcode:: @@ -1604,7 +1601,7 @@ matters when a large number of instances are going to be created. 4. Improves speed. Reading instance variables is 35% faster with ``__slots__`` (as measured with Python 3.10 on an Apple M1 processor). -5. Blocks tools like :func:`functools.cached_property` which require an +5. Blocks tools like :deco:`functools.cached_property` which require an instance dictionary to function correctly: .. testcode:: diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index 2fe5814bb04a736..adb9dc9a4879eb5 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -256,7 +256,7 @@ Ensuring unique enumeration values ---------------------------------- By default, enumerations allow multiple names as aliases for the same value. -When this behavior isn't desired, you can use the :func:`unique` decorator:: +When this behavior isn't desired, you can use the :deco:`unique` decorator:: >>> from enum import Enum, unique >>> @unique @@ -509,7 +509,7 @@ to use the standard :func:`repr`. .. note:: - Adding :func:`~dataclasses.dataclass` decorator to :class:`Enum` + Adding :deco:`~dataclasses.dataclass` decorator to :class:`Enum` and its subclasses is not supported. It will not raise any errors, but it will produce very strange results at runtime, such as members being equal to each other:: diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst index 552514063c95ab2..a61fdaee27f6b18 100644 --- a/Doc/howto/functional.rst +++ b/Doc/howto/functional.rst @@ -4,9 +4,6 @@ Functional Programming HOWTO ******************************** -:Author: \A. M. Kuchling -:Release: 0.32 - In this document, we'll take a tour of Python's features suitable for implementing programs in a functional style. After an introduction to the concepts of functional programming, we'll look at language features such as @@ -1042,7 +1039,7 @@ first calculation. :: >>> functools.reduce(operator.concat, []) Traceback (most recent call last): ... - TypeError: reduce() of empty sequence with no initial value + TypeError: reduce() of empty iterable with no initial value >>> functools.reduce(operator.mul, [1, 2, 3], 1) 6 >>> functools.reduce(operator.mul, [], 1) @@ -1185,7 +1182,8 @@ about whether this lambda-free style is better. Revision History and Acknowledgements ===================================== -The author would like to thank the following people for offering suggestions, +This HOWTO was originally written by A. M. Kuchling. The author would like to +thank the following people for offering suggestions, corrections and assistance with various drafts of this article: Ian Bicking, Nick Coghlan, Nick Efford, Raymond Hettinger, Jim Jewett, Mike Krell, Leandro Lameiro, Jussi Salmela, Collin Winter, Blake Winton. @@ -1239,9 +1237,9 @@ Text Processing". Mertz also wrote a 3-part series of articles on functional programming for IBM's DeveloperWorks site; see -`part 1 `__, -`part 2 `__, and -`part 3 `__, +`part 1 `__, +`part 2 `__, and +`part 3 `__. Python documentation diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst index 81fc7e63f35bd79..57e2d6e0752447f 100644 --- a/Doc/howto/index.rst +++ b/Doc/howto/index.rst @@ -37,6 +37,7 @@ Python Library Reference. mro.rst free-threading-python.rst free-threading-extensions.rst + abi3t-migration.rst remote_debugging.rst General: @@ -61,6 +62,7 @@ Advanced development: * :ref:`freethreading-python-howto` * :ref:`freethreading-extensions-howto` * :ref:`isolating-extensions-howto` +* :ref:`abi3t-migration-howto` * :ref:`python_2.3_mro` * :ref:`socket-howto` * :ref:`timerfd-howto` diff --git a/Doc/howto/instrumentation.rst b/Doc/howto/instrumentation.rst index 06c1ae40da5e67e..8f0b0c41ea48617 100644 --- a/Doc/howto/instrumentation.rst +++ b/Doc/howto/instrumentation.rst @@ -6,9 +6,6 @@ Instrumenting CPython with DTrace and SystemTap =============================================== -:author: David Malcolm -:author: Łukasz Langa - DTrace and SystemTap are monitoring tools, each providing a way to inspect what the processes on a computer system are doing. They both use domain-specific languages allowing a user to write scripts which: diff --git a/Doc/howto/ipaddress.rst b/Doc/howto/ipaddress.rst index e852db98156facc..646c4c4d9e7ab14 100644 --- a/Doc/howto/ipaddress.rst +++ b/Doc/howto/ipaddress.rst @@ -8,9 +8,6 @@ An introduction to the ipaddress module *************************************** -:author: Peter Moody -:author: Nick Coghlan - .. topic:: Overview This document aims to provide a gentle introduction to the diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index 0ee4c0086dd98ce..87025814aafb9ab 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -4,8 +4,6 @@ Logging Cookbook ================ -:Author: Vinay Sajip - This page contains a number of recipes related to logging, which have been found useful in the past. For links to tutorial and reference information, please see :ref:`cookbook-ref-links`. diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index 454e2f4930e724d..c8ce0df9e937f8c 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -4,8 +4,6 @@ Logging HOWTO ============= -:Author: Vinay Sajip - .. _logging-basic-tutorial: .. currentmodule:: logging diff --git a/Doc/howto/perf_profiling.rst b/Doc/howto/perf_profiling.rst index 657cb287ad3d605..5565f99b244f11b 100644 --- a/Doc/howto/perf_profiling.rst +++ b/Doc/howto/perf_profiling.rst @@ -6,8 +6,6 @@ Python support for the ``perf map`` compatible profilers ======================================================== -:author: Pablo Galindo - `The Linux perf profiler `_ and `samply `_ are powerful tools that allow you to profile and obtain information about the performance of your application. diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 9f73c811cfcbc0d..f19f6006dbac9e7 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -6,8 +6,6 @@ How to port Python 2 Code to Python 3 ************************************* -:author: Brett Cannon - Python 2 reached its official end-of-life at the start of 2020. This means that no new bug reports, fixes, or changes will be made to Python 2 - it's no longer supported: see :pep:`373` and diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index 6fc087c3f1c3673..ecdb35136a99f3b 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -4,8 +4,6 @@ Regular expression HOWTO **************************** -:Author: A.M. Kuchling - .. TODO: Document lookbehind assertions Better way of displaying a RE, a string, and what it matches diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst index cbc49d15a0771b9..b17ab3f4391dad0 100644 --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -4,9 +4,6 @@ Socket Programming HOWTO **************************** -:Author: Gordon McMillan - - .. topic:: Abstract Sockets are used nearly everywhere, but are one of the most severely diff --git a/Doc/howto/sorting.rst b/Doc/howto/sorting.rst index 70c34cde8a06592..b511aa4e59fe1e7 100644 --- a/Doc/howto/sorting.rst +++ b/Doc/howto/sorting.rst @@ -3,9 +3,6 @@ Sorting Techniques ****************** -:Author: Andrew Dalke and Raymond Hettinger - - Python lists have a built-in :meth:`list.sort` method that modifies the list in-place. There is also a :func:`sorted` built-in function that builds a new sorted list from an iterable. @@ -375,7 +372,7 @@ Odds and Ends :meth:`~object.__lt__` is not implemented (see :func:`object.__lt__` for details on the mechanics). To avoid surprises, :pep:`8` recommends that all six comparison methods be implemented. - The :func:`~functools.total_ordering` decorator is provided to make that + The :deco:`~functools.total_ordering` decorator is provided to make that task easier. * Key functions need not depend directly on the objects being sorted. A key diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst index 243cc27bac7025d..cbd53d5b619f5a3 100644 --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -4,8 +4,6 @@ Unicode HOWTO ***************** -:Release: 1.12 - This HOWTO discusses Python's support for the Unicode specification for representing textual data, and explains various problems that people commonly encounter when trying to work with Unicode. diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index 4e77d2cb407f726..e4f218f088ba89d 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -4,9 +4,6 @@ HOWTO Fetch Internet Resources Using The urllib Package *********************************************************** -:Author: `Michael Foord `_ - - Introduction ============ diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst index 904eff2e31e6ac2..be25a94e7e94f6f 100644 --- a/Doc/library/abc.rst +++ b/Doc/library/abc.rst @@ -166,17 +166,17 @@ The :mod:`!abc` module also provides the following decorator: or is derived from it. A class that has a metaclass derived from :class:`!ABCMeta` cannot be instantiated unless all of its abstract methods and properties are overridden. The abstract methods can be called using any - of the normal 'super' call mechanisms. :func:`!abstractmethod` may be used + of the normal 'super' call mechanisms. :deco:`!abstractmethod` may be used to declare abstract methods for properties and descriptors. Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are only supported using the :func:`update_abstractmethods` function. The - :func:`!abstractmethod` only affects subclasses derived using regular + :deco:`!abstractmethod` only affects subclasses derived using regular inheritance; "virtual subclasses" registered with the ABC's :meth:`~ABCMeta.register` method are not affected. - When :func:`!abstractmethod` is applied in combination with other method + When :deco:`!abstractmethod` is applied in combination with other method descriptors, it should be applied as the innermost decorator, as shown in the following usage examples:: @@ -214,7 +214,7 @@ The :mod:`!abc` module also provides the following decorator: the descriptor must identify itself as abstract using :attr:`!__isabstractmethod__`. In general, this attribute should be ``True`` if any of the methods used to compose the descriptor are abstract. For - example, Python's built-in :class:`property` does the equivalent of:: + example, Python's built-in :deco:`property` does the equivalent of:: class Descriptor: ... @@ -238,13 +238,13 @@ The :mod:`!abc` module also supports the following legacy decorators: .. versionadded:: 3.2 .. deprecated-removed:: 3.3 3.21 - It is now possible to use :class:`classmethod` with - :func:`abstractmethod`, making this decorator redundant. + It is now possible to use :deco:`classmethod` with + :deco:`abstractmethod`, making this decorator redundant. - A subclass of the built-in :func:`classmethod`, indicating an abstract - classmethod. Otherwise it is similar to :func:`abstractmethod`. + A subclass of the built-in :class:`classmethod`, indicating an abstract + classmethod. Otherwise it is similar to :deco:`abstractmethod`. - This special case is deprecated, as the :func:`classmethod` decorator + This special case is deprecated, as the :deco:`classmethod` decorator is now correctly identified as abstract when applied to an abstract method:: @@ -259,13 +259,13 @@ The :mod:`!abc` module also supports the following legacy decorators: .. versionadded:: 3.2 .. deprecated-removed:: 3.3 3.21 - It is now possible to use :class:`staticmethod` with - :func:`abstractmethod`, making this decorator redundant. + It is now possible to use :deco:`staticmethod` with + :deco:`abstractmethod`, making this decorator redundant. - A subclass of the built-in :func:`staticmethod`, indicating an abstract - staticmethod. Otherwise it is similar to :func:`abstractmethod`. + A subclass of the built-in :class:`staticmethod`, indicating an abstract + staticmethod. Otherwise it is similar to :deco:`abstractmethod`. - This special case is deprecated, as the :func:`staticmethod` decorator + This special case is deprecated, as the :deco:`staticmethod` decorator is now correctly identified as abstract when applied to an abstract method:: @@ -279,14 +279,14 @@ The :mod:`!abc` module also supports the following legacy decorators: .. decorator:: abstractproperty .. deprecated-removed:: 3.3 3.21 - It is now possible to use :class:`property`, :meth:`property.getter`, - :meth:`property.setter` and :meth:`property.deleter` with - :func:`abstractmethod`, making this decorator redundant. + It is now possible to use :deco:`property`, :deco:`property.getter`, + :deco:`property.setter` and :deco:`property.deleter` with + :deco:`abstractmethod`, making this decorator redundant. - A subclass of the built-in :func:`property`, indicating an abstract + A subclass of the built-in :class:`property`, indicating an abstract property. - This special case is deprecated, as the :func:`property` decorator + This special case is deprecated, as the :deco:`property` decorator is now correctly identified as abstract when applied to an abstract method:: diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index db5fae2006678a2..e4a5f4d109b4992 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -442,9 +442,8 @@ is considered equivalent to the expression ``['-f', 'foo', '-f', 'bar']``. .. note:: - Empty lines are treated as empty strings (``''``), which are allowed as values but - not as arguments. Empty lines that are read as arguments will result in an - "unrecognized arguments" error. + Each line is treated as a single argument, so an empty line is read as an + empty string (``''``). :class:`ArgumentParser` uses :term:`filesystem encoding and error handler` to read the file containing arguments. @@ -1052,6 +1051,10 @@ is used when no command-line argument was present:: >>> parser.parse_args([]) Namespace(foo=42) +Because ``nargs='*'`` gathers any supplied values into a list, an absent +positional argument yields an empty list (``[]``). Only a non-``None`` +*default* overrides this (so ``default=None`` still gives ``[]``). + For required_ arguments, the ``default`` value is ignored. For example, this applies to positional arguments with nargs_ values other than ``?`` or ``*``, or optional arguments marked as ``required=True``. @@ -1369,6 +1372,11 @@ behavior:: >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') +Multiple arguments may share the same ``dest``. By default, the value from the +last such argument given on the command line wins. Use ``action='append'`` to +collect values from all of them into a list instead. For conflicting *option +strings* rather than ``dest`` names, see conflict_handler_. + .. versionchanged:: 3.15 Single-dash long option now takes precedence over short options. @@ -1777,6 +1785,11 @@ Subcommands present, and when the ``b`` command is specified, only the ``foo`` and ``baz`` attributes are present. + If a subparser defines an argument with the same ``dest`` as the parent + parser, the two share a single namespace attribute, so the parent's value + won't be retained. Users should give them distinct ``dest`` values to + keep both. + Similarly, when a help message is requested from a subparser, only the help for that particular parser will be printed. The help message will not include parent parser or sibling parser messages. (A help message for each @@ -2232,6 +2245,9 @@ Customizing file parsing def convert_arg_line_to_args(self, arg_line): return arg_line.split() + Note that with this override an argument can no longer contain spaces, since + each space-separated word becomes a separate argument. + Exiting methods ^^^^^^^^^^^^^^^ diff --git a/Doc/library/asyncio-threading.rst b/Doc/library/asyncio-threading.rst new file mode 100644 index 000000000000000..526901a2e7eb206 --- /dev/null +++ b/Doc/library/asyncio-threading.rst @@ -0,0 +1,154 @@ +.. currentmodule:: asyncio + +.. _asyncio-threading: + +asyncio and free-threaded Python +================================ + +asyncio uses an event loop as a scheduler to enable highly efficient +concurrency by switching between tasks to allow non-blocking I/O +operations. This results in better performance for I/O-bound use +cases. It also allows off-loading CPU-bound work to a thread or +process pool, but that is still limited by the :term:`global +interpreter lock` in CPython. + +However, in :ref:`free-threaded Python `, +the GIL is disabled and Python can run true multi-threaded code. This +means that asyncio can now take advantage of multiple CPU cores without +the limitations imposed by the GIL. + +Since Python 3.14, asyncio has first-class support for free-threaded +Python, and the implementation of asyncio is safe to use in a +multi-threaded environment. + +A single event loop on one core can handle many connections +concurrently, but the Python code that runs to handle each one still +executes serially. Once requests involve a non-trivial amount of +per-request computation, that handling becomes the bottleneck, and a +single core can no longer keep up. Combining asyncio with threads is +most useful here: by running an event loop per thread, the handling of +different requests can run in parallel across multiple CPU cores. It is +also useful when you need to run blocking or CPU-bound code from an +asyncio application. + + +.. seealso:: + + `Scaling asyncio on Free-Threaded Python + `__, + a blog post by Kumar Aditya which explains the internal changes + that make asyncio safe and efficient under free-threaded Python, + together with benchmarks of the resulting improvements. + + +Thread safety considerations +---------------------------- + +While asyncio is designed to be thread-safe in a free-threaded Python +environment, there are still some considerations to keep in mind when +using asyncio with threads: + +1. **Event loop**: Each thread should have its own event loop which + should not be shared across threads. This ensures that the event loop + can manage its own tasks and callbacks without interference from + other threads. + +2. **Task management**: Tasks and futures created in one thread should + not be awaited or manipulated from another thread. + +3. **Thread-safe APIs**: When interacting with asyncio from multiple + threads, it's important to use thread-safe APIs provided by asyncio, + such as :func:`asyncio.run_coroutine_threadsafe` for submitting + coroutines to an event loop from another thread. If you need to + call a callback from a different thread, you can use + :meth:`loop.call_soon_threadsafe` to schedule it safely. + +4. **Synchronization**: The synchronization primitives provided by + asyncio (like :class:`asyncio.Lock` and :class:`asyncio.Event`) + are not designed to be used across threads. If you need to + synchronize between threads, you should use the synchronization + primitives from the :mod:`threading` module instead. + + +Using asyncio with threads +-------------------------- + +asyncio supports running one event loop per thread, which allows you to +take advantage of multiple CPU cores in a free-threaded Python +environment. Each thread can run its own event loop, and tasks can be +scheduled on those loops independently. + +Here's an example of how to use asyncio with threads:: + + import asyncio + import threading + + async def worker(name: str) -> None: + print(f"Worker {name} starting") + await asyncio.sleep(1) + print(f"Worker {name} done") + + def run_loop(name: str) -> None: + asyncio.run(worker(name)) + + threads = [ + threading.Thread(target=run_loop, args=(f"T{i}",)) + for i in range(4) + ] + for t in threads: + t.start() + for t in threads: + t.join() + +In this example, each thread creates its own event loop with +:func:`asyncio.run` and runs a coroutine on it. The threads execute +concurrently, and in a free-threaded build they can run on separate +CPU cores in parallel. + + +Producer/consumer across threads +-------------------------------- + +When a regular (non-asyncio) thread needs to hand work to an asyncio +event loop running in another thread, use a thread-safe primitive such +as :class:`queue.Queue` rather than :class:`asyncio.Queue`, which is +only safe within a single event loop.:: + + import asyncio + import queue + import threading + + def producer(q: queue.Queue[int]) -> None: + for i in range(5): + print(f"Producing {i}") + q.put(i) + q.shutdown() + + async def consumer(q: queue.Queue[int]) -> None: + while True: + try: + item = q.get_nowait() + except queue.Empty: + await asyncio.sleep(0.1) + continue + except queue.ShutDown: + break + print(f"Consumed {item}") + await asyncio.sleep(item) + + q: queue.Queue[int] = queue.Queue() + consumer_thread = threading.Thread( + target=lambda: asyncio.run(consumer(q)) + ) + consumer_thread.start() + producer(q) + consumer_thread.join() + +The producer runs on the main thread while the consumer runs inside an +event loop on its own thread, yet they communicate safely through +``queue.Queue``. When the queue is empty the consumer sleeps briefly +and tries again. When the producer is done it calls +:meth:`~queue.Queue.shutdown`, which causes subsequent +:meth:`~queue.Queue.get_nowait` calls to raise :exc:`queue.ShutDown` +so the consumer can exit cleanly. + diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst index 0f72e31dee5f1d1..90a465f3e1d3af4 100644 --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -128,6 +128,7 @@ for full functionality and the latest features. asyncio-api-index.rst asyncio-llapi-index.rst asyncio-dev.rst + asyncio-threading.rst .. note:: The source code for asyncio can be found in :source:`Lib/asyncio/`. diff --git a/Doc/library/bisect.rst b/Doc/library/bisect.rst index 2c29a5ec992737e..39ab75c0904df9c 100644 --- a/Doc/library/bisect.rst +++ b/Doc/library/bisect.rst @@ -129,7 +129,7 @@ thoughts in mind: they are used. Consequently, if the search functions are used in a loop, the key function may be called again and again on the same array elements. If the key function isn't fast, consider wrapping it with - :py:func:`functools.cache` to avoid duplicate computations. Alternatively, + :py:deco:`functools.cache` to avoid duplicate computations. Alternatively, consider searching an array of precomputed keys to locate the insertion point (as shown in the examples section below). @@ -200,7 +200,7 @@ example uses :py:func:`~bisect.bisect` to look up a letter grade for an exam sco based on a set of ordered numeric breakpoints: 90 and up is an 'A', 80 to 89 is a 'B', and so on:: - >>> def grade(score) + >>> def grade(score): ... i = bisect([60, 70, 80, 90], score) ... return "FDCBA"[i] ... diff --git a/Doc/library/collections.abc.rst b/Doc/library/collections.abc.rst index 51853725b1b297c..10e3790717ed6ed 100644 --- a/Doc/library/collections.abc.rst +++ b/Doc/library/collections.abc.rst @@ -456,7 +456,7 @@ Notes on using :class:`Set` and :class:`MutableSet` as a mixin: The :class:`Set` mixin provides a :meth:`!_hash` method to compute a hash value for the set; however, :meth:`~object.__hash__` is not defined because not all sets are :term:`hashable` or immutable. To add set hashability using mixins, - inherit from both :meth:`Set` and :meth:`Hashable`, then define + inherit from both :class:`Set` and :class:`Hashable`, then define ``__hash__ = Set._hash``. .. seealso:: diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 25e4a71b03c6c85..d09a6c92bbd37dc 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -1228,12 +1228,12 @@ original insertion position is changed and moved to the end:: self.move_to_end(key) An :class:`OrderedDict` would also be useful for implementing -variants of :func:`functools.lru_cache`: +variants of :deco:`functools.lru_cache`: .. testcode:: from collections import OrderedDict - from time import time + from time import monotonic class TimeBoundedLRU: "LRU Cache that invalidates and refreshes old entries." @@ -1248,10 +1248,10 @@ variants of :func:`functools.lru_cache`: if args in self.cache: self.cache.move_to_end(args) timestamp, result = self.cache[args] - if time() - timestamp <= self.maxage: + if monotonic() - timestamp <= self.maxage: return result result = self.func(*args) - self.cache[args] = time(), result + self.cache[args] = monotonic(), result if len(self.cache) > self.maxsize: self.cache.popitem(last=False) return result diff --git a/Doc/library/contextlib.rst b/Doc/library/contextlib.rst index 02be00f575e725b..666f85997448881 100644 --- a/Doc/library/contextlib.rst +++ b/Doc/library/contextlib.rst @@ -88,11 +88,11 @@ Functions and classes provided: the exception has been handled, and execution will resume with the statement immediately following the :keyword:`!with` statement. - :func:`contextmanager` uses :class:`ContextDecorator` so the context managers + :deco:`contextmanager` uses :class:`ContextDecorator` so the context managers it creates can be used as decorators as well as in :keyword:`with` statements. When used as a decorator, a new generator instance is implicitly created on each function call (this allows the otherwise "one-shot" context managers - created by :func:`contextmanager` to meet the requirement that context + created by :deco:`contextmanager` to meet the requirement that context managers support multiple invocations in order to be used as decorators). .. versionchanged:: 3.2 @@ -101,7 +101,7 @@ Functions and classes provided: .. decorator:: asynccontextmanager - Similar to :func:`~contextlib.contextmanager`, but creates an + Similar to :deco:`~contextlib.contextmanager`, but creates an :ref:`asynchronous context manager `. This function is a :term:`decorator` that can be used to define a factory @@ -128,7 +128,7 @@ Functions and classes provided: .. versionadded:: 3.7 - Context managers defined with :func:`asynccontextmanager` can be used + Context managers defined with :deco:`asynccontextmanager` can be used either as decorators or with :keyword:`async with` statements:: import time @@ -148,11 +148,11 @@ Functions and classes provided: When used as a decorator, a new generator instance is implicitly created on each function call. This allows the otherwise "one-shot" context managers - created by :func:`asynccontextmanager` to meet the requirement that context + created by :deco:`asynccontextmanager` to meet the requirement that context managers support multiple invocations in order to be used as decorators. .. versionchanged:: 3.10 - Async context managers created with :func:`asynccontextmanager` can + Async context managers created with :deco:`asynccontextmanager` can be used as decorators. @@ -400,7 +400,7 @@ Functions and classes provided: ``__exit__`` retains its optional exception handling even when used as a decorator. - ``ContextDecorator`` is used by :func:`contextmanager`, so you get this + ``ContextDecorator`` is used by :deco:`contextmanager`, so you get this functionality automatically. Example of ``ContextDecorator``:: @@ -702,7 +702,7 @@ Functions and classes provided: Similar to :meth:`ExitStack.close` but properly handles awaitables. - Continuing the example for :func:`asynccontextmanager`:: + Continuing the example for :deco:`asynccontextmanager`:: async with AsyncExitStack() as stack: connections = [await stack.enter_async_context(get_connection()) @@ -960,7 +960,7 @@ Files are an example of effectively single use context managers, since the first :keyword:`with` statement will close the file, preventing any further IO operations using that file object. -Context managers created using :func:`contextmanager` are also single use +Context managers created using :deco:`contextmanager` are also single use context managers, and will complain about the underlying generator failing to yield if an attempt is made to use them a second time:: diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index d6e704825924d95..51f08fdc0544c96 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -551,7 +551,7 @@ object with an :attr:`!_as_parameter_` attribute:: >>> If you don't want to store the instance's data in the :attr:`!_as_parameter_` -instance variable, you could define a :class:`property` which makes the +instance variable, you could define a :deco:`property` which makes the attribute available on request. diff --git a/Doc/library/curses.ascii.rst b/Doc/library/curses.ascii.rst index 9ae82c144655383..8f8e3ddda8ef52a 100644 --- a/Doc/library/curses.ascii.rst +++ b/Doc/library/curses.ascii.rst @@ -130,7 +130,7 @@ C library: .. function:: isgraph(c) - Checks for ASCII any printable character except space. + Checks for any ASCII printable character except space. .. function:: islower(c) @@ -145,7 +145,7 @@ C library: .. function:: ispunct(c) - Checks for any printable ASCII character which is not a space or an alphanumeric + Checks for any ASCII printable character which is not a space or an alphanumeric character. diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 954edc4506df1a3..ce59d89843e761d 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -100,12 +100,25 @@ Module contents ignored. - *eq*: If true (the default), an :meth:`~object.__eq__` method will be - generated. This method compares the class as if it were a tuple - of its fields, in order. Both instances in the comparison must - be of the identical type. + generated. - If the class already defines :meth:`!__eq__`, this parameter is - ignored. + This method compares the class by comparing each field in order. Both + instances in the comparison must be of the identical type. + + If the class already defines :meth:`!__eq__`, this parameter is ignored. + + .. versionchanged:: 3.13 + The generated ``__eq__`` method now compares each field individually + (for example, ``self.a == other.a and self.b == other.b``), rather than + comparing tuples of fields as in previous versions. + + This change makes the comparison faster but it may alter results in cases + where attributes compare equal by identity but not by value (such as + ``float('nan')``). + + In Python 3.12 and earlier, the comparison was performed by creating + tuples of the fields and comparing them (for example, + ``(self.a, self.b) == (other.a, other.b)``). - *order*: If true (the default is ``False``), :meth:`~object.__lt__`, :meth:`~object.__le__`, :meth:`~object.__gt__`, and :meth:`~object.__ge__` methods will be diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index 8b812c173b59536..25edb40e35a630a 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -724,7 +724,7 @@ Finally, we compare the two: >>> result = list(d.compare(text1, text2)) -``result`` is a list of strings, so let's pretty-print it: +``result`` is a list of strings, so let's pretty-print it:: >>> from pprint import pprint >>> pprint(result) @@ -739,7 +739,7 @@ Finally, we compare the two: '? ++++ ^ ^\n', '+ 5. Flat is better than nested.\n'] -As a single multi-line string it looks like this: +As a single multi-line string it looks like this:: >>> import sys >>> sys.stdout.writelines(result) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 04b41ad6eadf38c..559a76bb3963e09 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -115,30 +115,30 @@ Module contents :class:`StrEnum` defaults to the lower-cased version of the member name, while other Enums default to 1 and increase from there. - :func:`~enum.property` + :deco:`~enum.property` Allows :class:`Enum` members to have attributes without conflicting with member names. The ``value`` and ``name`` attributes are implemented this way. - :func:`unique` + :deco:`unique` Enum class decorator that ensures only one name is bound to any one value. - :func:`verify` + :deco:`verify` Enum class decorator that checks user-selectable constraints on an enumeration. - :func:`member` + :deco:`member` Make ``obj`` a member. Can be used as a decorator. - :func:`nonmember` + :deco:`nonmember` Do not make ``obj`` a member. Can be used as a decorator. - :func:`global_enum` + :deco:`global_enum` Modify the :class:`str() ` and :func:`repr` of an enum to show its members as belonging to the module instead of its class, @@ -629,7 +629,7 @@ Data types >>> white in purple False - .. method:: __iter__(self): + .. method:: __iter__(self) Returns all contained non-alias members:: @@ -640,7 +640,7 @@ Data types .. versionadded:: 3.11 - .. method:: __len__(self): + .. method:: __len__(self) Returns number of members in flag:: @@ -651,7 +651,7 @@ Data types .. versionadded:: 3.11 - .. method:: __bool__(self): + .. method:: __bool__(self) Returns *True* if any members in flag, *False* otherwise:: @@ -688,7 +688,7 @@ Data types >>> purple ^ Color.GREEN - .. method:: __invert__(self): + .. method:: __invert__(self) Returns all the flags in *type(self)* that are not in *self*:: @@ -1006,7 +1006,7 @@ Utilities and decorators .. decorator:: property - A decorator similar to the built-in *property*, but specifically for + A decorator similar to the built-in :deco:`property`, but specifically for enumerations. It allows member attributes to have the same names as members themselves. diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst index a213679e4e2dd76..fc99b7fd1e7523a 100644 --- a/Doc/library/fnmatch.rst +++ b/Doc/library/fnmatch.rst @@ -51,7 +51,7 @@ Unless stated otherwise, "filename string" and "pattern string" either refer to functions documented below do not allow to mix a :class:`!bytes` pattern with a :class:`!str` filename, and vice-versa. -Finally, note that :func:`functools.lru_cache` with a *maxsize* of 32768 +Finally, note that :deco:`functools.lru_cache` with a *maxsize* of 32768 is used to cache the (typed) compiled regex patterns in the following functions: :func:`fnmatch`, :func:`fnmatchcase`, :func:`.filter`, :func:`.filterfalse`. diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index def2a211d1b3b4d..a4d37beb436899a 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -485,7 +485,7 @@ are always available. They are listed here in alphabetical order. :noindex: Create a new dictionary. The :class:`dict` object is the dictionary class. - See :class:`dict` and :ref:`typesmapping` for documentation about this class. + See also :ref:`typesmapping` for documentation about this class. For other containers see the built-in :class:`frozendict`, :class:`list`, :class:`set`, and :class:`tuple` classes, as well as the :mod:`collections` module. @@ -873,7 +873,7 @@ are always available. They are listed here in alphabetical order. :noindex: Create a new frozen dictionary. The :class:`frozendict` object is a built-in class. - See :class:`frozendict` and :ref:`typesmapping` for documentation about this class. + See also :ref:`typesmapping` for documentation about this class. For other containers see the built-in :class:`dict`, :class:`list`, :class:`set`, and :class:`tuple` classes, as well as the :mod:`collections` module. @@ -886,7 +886,7 @@ are always available. They are listed here in alphabetical order. :noindex: Return a new :class:`frozenset` object, optionally with elements taken from - *iterable*. ``frozenset`` is a built-in class. See :class:`frozenset` and + *iterable*. :class:`frozenset` is a built-in class. See also :ref:`types-set` for documentation about this class. For other containers see the built-in :class:`set`, :class:`list`, @@ -1680,7 +1680,7 @@ are always available. They are listed here in alphabetical order. If given, *doc* will be the docstring of the property attribute. Otherwise, the property will copy *fget*'s docstring (if it exists). This makes it possible to - create read-only properties easily using :func:`property` as a :term:`decorator`:: + create read-only properties easily using :deco:`property` as a :term:`decorator`:: class Parrot: def __init__(self): @@ -1814,7 +1814,7 @@ are always available. They are listed here in alphabetical order. :noindex: Return a new :class:`set` object, optionally with elements taken from - *iterable*. ``set`` is a built-in class. See :class:`set` and + *iterable*. :class:`set` is a built-in class. See also :ref:`types-set` for documentation about this class. For other containers see the built-in :class:`frozenset`, :class:`list`, @@ -1984,7 +1984,7 @@ are always available. They are listed here in alphabetical order. be used in the class definition (such as ``f()``). Static methods in Python are similar to those found in Java or C++. Also, see - :func:`classmethod` for a variant that is useful for creating alternate class + :deco:`classmethod` for a variant that is useful for creating alternate class constructors. Like all decorators, it is also possible to call ``staticmethod`` as diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 7da59cba5170b35..2b46978f058102b 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -27,7 +27,7 @@ The :mod:`!functools` module defines the following functions: Returns the same as ``lru_cache(maxsize=None)``, creating a thin wrapper around a dictionary lookup for the function arguments. Because it never needs to evict old values, this is smaller and faster than - :func:`lru_cache` with a size limit. + :deco:`lru_cache` with a size limit. For example:: @@ -61,7 +61,7 @@ The :mod:`!functools` module defines the following functions: Transform a method of a class into a property whose value is computed once and then cached as a normal attribute for the life of the instance. Similar - to :func:`property`, with the addition of caching. Useful for expensive + to :deco:`property`, with the addition of caching. Useful for expensive computed properties of instances that are otherwise effectively immutable. Example:: @@ -75,8 +75,8 @@ The :mod:`!functools` module defines the following functions: def stdev(self): return statistics.stdev(self._data) - The mechanics of :func:`cached_property` are somewhat different from - :func:`property`. A regular property blocks attribute writes unless a + The mechanics of :deco:`cached_property` are somewhat different from + :deco:`property`. A regular property blocks attribute writes unless a setter is defined. In contrast, a *cached_property* allows writes. The *cached_property* decorator only runs on lookups and only when an @@ -108,14 +108,14 @@ The :mod:`!functools` module defines the following functions: (as such classes don't provide a ``__dict__`` attribute at all). If a mutable mapping is not available or if space-efficient key sharing is - desired, an effect similar to :func:`cached_property` can also be achieved by - stacking :func:`property` on top of :func:`lru_cache`. See - :ref:`faq-cache-method-calls` for more details on how this differs from :func:`cached_property`. + desired, an effect similar to :deco:`cached_property` can also be achieved by + stacking :deco:`property` on top of :deco:`lru_cache`. See + :ref:`faq-cache-method-calls` for more details on how this differs from :deco:`cached_property`. .. versionadded:: 3.8 .. versionchanged:: 3.12 - Prior to Python 3.12, ``cached_property`` included an undocumented lock to + Prior to Python 3.12, :deco:`!cached_property` included an undocumented lock to ensure that in multi-threaded usage the getter function was guaranteed to run only once per instance. However, the lock was per-property, not per-instance, which could result in unacceptably high lock contention. In @@ -732,7 +732,7 @@ The :mod:`!functools` module defines the following functions: function's :attr:`~function.__dict__`, i.e. the instance dictionary). To allow access to the original function for introspection and other purposes - (e.g. bypassing a caching decorator such as :func:`lru_cache`), this function + (e.g. bypassing a caching decorator such as :deco:`lru_cache`), this function automatically adds a ``__wrapped__`` attribute to the wrapper that refers to the function being wrapped. diff --git a/Doc/library/getpass.rst b/Doc/library/getpass.rst index fd96f3bbf6a574f..f60cc63414f764d 100644 --- a/Doc/library/getpass.rst +++ b/Doc/library/getpass.rst @@ -18,7 +18,7 @@ The :mod:`!getpass` module provides two functions: the string *prompt*, which defaults to ``'Password: '``. On Unix, the prompt is written to the file-like object *stream* using the replace error handler if needed. *stream* defaults to the controlling terminal - (:file:`/dev/tty`) or if that is unavailable to ``sys.stderr`` (this + (:file:`/dev/tty`) or if that is unavailable to :data:`sys.stderr` (this argument is ignored on Windows). The *echo_char* argument controls how user input is displayed while typing. @@ -27,12 +27,12 @@ The :mod:`!getpass` module provides two functions: typed character is replaced by it. For example, ``echo_char='*'`` will display asterisks instead of the actual input. - If echo free input is unavailable getpass() falls back to printing - a warning message to *stream* and reading from ``sys.stdin`` and + If echo-free input is unavailable, :func:`getpass` falls back to printing + a warning message to *stream* and reading from :data:`sys.stdin` and issuing a :exc:`GetPassWarning`. .. note:: - If you call getpass from within IDLE, the input may be done in the + If you call :func:`getpass` from within IDLE, the input may be done in the terminal you launched IDLE from rather than the idle window itself. .. note:: diff --git a/Doc/library/importlib.resources.rst b/Doc/library/importlib.resources.rst index 653fa61420be869..72db66f9f06f890 100644 --- a/Doc/library/importlib.resources.rst +++ b/Doc/library/importlib.resources.rst @@ -240,7 +240,6 @@ For all the following functions: .. versionchanged:: 3.13 Multiple *path_names* are accepted. - *encoding* and *errors* must be given as keyword arguments. .. function:: is_resource(anchor, *path_names) diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 8c0eed592dd49ed..d47b74efe22de9d 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -38,6 +38,7 @@ will raise a :exc:`TypeError`. So will giving a :class:`bytes` object to the Operations that used to raise :exc:`IOError` now raise :exc:`OSError`, since :exc:`IOError` is now an alias of :exc:`OSError`. +.. _text-io: Text I/O ^^^^^^^^ @@ -65,6 +66,7 @@ In-memory text streams are also available as :class:`StringIO` objects:: The text stream API is described in detail in the documentation of :class:`TextIOBase`. +.. _binary-io: Binary I/O ^^^^^^^^^^ @@ -103,6 +105,13 @@ stream by opening a file in binary mode with buffering disabled:: The raw stream API is described in detail in the docs of :class:`RawIOBase`. +.. warning:: + Raw I/O is a low-level interface and methods generally must have their return + values checked and be explicitly retried to ensure an operation completes. + For instance :meth:`~RawIOBase.write` returns the number of bytes written + which may be less than the number of bytes provided (a partial write). + High-level I/O objects like :ref:`binary-io` and :ref:`text-io` implement + retry behavior. .. _io-text-encoding: @@ -478,8 +487,11 @@ I/O Base Classes Read up to *size* bytes from the object and return them. As a convenience, if *size* is unspecified or -1, all bytes until EOF are returned. - Otherwise, only one system call is ever made. Fewer than *size* bytes may - be returned if the operating system call returns fewer than *size* bytes. + + Attempts to make only one system call but will retry if interrupted and + the signal handler does not raise an exception (see :pep:`475` for the + rationale). This means fewer than *size* bytes may be returned if the + operating system call returns fewer than *size* bytes. If 0 bytes are returned, and *size* was not 0, this indicates end of file. If the object is in non-blocking mode and no bytes are available, @@ -493,13 +505,19 @@ I/O Base Classes Read and return all the bytes from the stream until EOF, using multiple calls to the stream if necessary. + If ``0`` bytes are returned this indicates end of file. If the object is in + non-blocking mode and the underlying :meth:`read` returns ``None`` + indicating no bytes are available, ``None`` is returned. + .. method:: readinto(b, /) Read bytes into a pre-allocated, writable :term:`bytes-like object` *b*, and return the number of bytes read. For example, *b* might be a :class:`bytearray`. - If the object is in non-blocking mode and no bytes - are available, ``None`` is returned. + + If ``0`` is returned and ``len(b)`` is not ``0``, this indicates end of file. If + the object is in non-blocking mode and no bytes are available, ``None`` is + returned. .. method:: write(b, /) @@ -513,6 +531,13 @@ I/O Base Classes this method returns, so the implementation should only access *b* during the method call. + .. warning:: + + This function does not ensure all bytes are written or an exception is + thrown. Callers may implement that behavior by checking the return + value and, if it is less than the length of *b*, looping with additional + write calls until all unwritten bytes are written. High-level I/O + objects like :ref:`binary-io` and :ref:`text-io` implement retry behavior. .. class:: BufferedIOBase @@ -641,7 +666,11 @@ Raw File I/O .. class:: FileIO(name, mode='r', closefd=True, opener=None) A raw binary stream representing an OS-level file containing bytes data. It - inherits from :class:`RawIOBase`. + inherits from :class:`RawIOBase` and implements its low-level access design. + This means :meth:`~RawIOBase.write` does not guarantee all bytes are written + and :meth:`~RawIOBase.read` may read less bytes than requested even when more + bytes may be present in the underlying file. To get "write all" and + "read at least" behavior, use :ref:`binary-io`. The *name* can be one of two things: @@ -661,10 +690,6 @@ Raw File I/O implies writing, so this mode behaves in a similar way to ``'w'``. Add a ``'+'`` to the mode to allow simultaneous reading and writing. - The :meth:`~RawIOBase.read` (when called with a positive argument), - :meth:`~RawIOBase.readinto` and :meth:`~RawIOBase.write` methods on this - class will only make one system call. - A custom opener can be used by passing a callable as *opener*. The underlying file descriptor for the file object is then obtained by calling *opener* with (*name*, *flags*). *opener* must return an open file descriptor (passing @@ -676,6 +701,13 @@ Raw File I/O See the :func:`open` built-in function for examples on using the *opener* parameter. + .. warning:: + :class:`FileIO` is a low-level I/O object and members, such as + :meth:`~RawIOBase.read` and :meth:`~RawIOBase.write`, need to have their + return values checked explicitly in a retry loop to implement "write all" + and "read at least" behavior. High-level I/O objects :ref:`binary-io` and + :ref:`text-io` implement retry behavior. + .. versionchanged:: 3.3 The *opener* parameter was added. The ``'x'`` mode was added. diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 714db5fa12af0aa..5152c7561fa1f26 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -402,7 +402,8 @@ timed intervals. rollover interval. When computing the next rollover time for the first time (when the handler - is created), the last modification time of an existing log file, or else + is created), the creation time (if supported by the OS and file system) + or the last modification of an existing log file, or else the current time, is used to compute when the next rotation will occur. If the *utc* argument is true, times in UTC will be used; otherwise @@ -449,6 +450,10 @@ timed intervals. .. versionchanged:: 3.9 The *errors* parameter was added. + .. versionchanged:: next + Use the creation time instead of the last modification time, if supported by the OS and file system. + + .. method:: doRollover() Does a rollover, as described above. diff --git a/Doc/library/math.rst b/Doc/library/math.rst index 41a9a0ab55d8fab..efe411e5a43f27d 100644 --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -83,13 +83,20 @@ noted otherwise, all return values are floats. **Trigonometric functions** -------------------------------------------------------------------------------------------------- -:func:`acos(x) ` Arc cosine of *x* -:func:`asin(x) ` Arc sine of *x* -:func:`atan(x) ` Arc tangent of *x* -:func:`atan2(y, x) ` ``atan(y / x)`` -:func:`cos(x) ` Cosine of *x* -:func:`sin(x) ` Sine of *x* -:func:`tan(x) ` Tangent of *x* +:func:`acos(x) ` Arc cosine of *x*, in radians +:func:`acospi(x) ` Arc cosine of *x*, in half-turns +:func:`asin(x) ` Arc sine of *x*, in radians +:func:`asinpi(x) ` Arc sine of *x*, in half-turns +:func:`atan(x) ` Arc tangent of *x*, in radians +:func:`atanpi(x) ` Arc tangent of *x*, in half-turns +:func:`atan2(y, x) ` ``atan(y / x)``, in radians +:func:`atan2pi(y, x) ` ``atan(y / x)``, in half-turns +:func:`cos(x) ` Cosine of *x* radians +:func:`cospi(x) ` Cosine of *x⋅π* radians +:func:`sin(x) ` Sine of *x* radians +:func:`sinpi(x) ` Sine of *x⋅π* radians +:func:`tan(x) ` Tangent of *x* radians +:func:`tanpi(x) ` Tangent of *x⋅π* radians **Hyperbolic functions** -------------------------------------------------------------------------------------------------- @@ -599,18 +606,42 @@ Trigonometric functions ``pi``. +.. function:: acospi(x) + + Return the arc cosine of *x*, in half-turns. The result is between ``0`` and + ``1``. + + .. versionadded:: next + + .. function:: asin(x) Return the arc sine of *x*, in radians. The result is between ``-pi/2`` and ``pi/2``. +.. function:: asinpi(x) + + Return the arc sine of *x*, in half-turns. The result is between ``-0.5`` and + ``0.5``. + + .. versionadded:: next + + .. function:: atan(x) Return the arc tangent of *x*, in radians. The result is between ``-pi/2`` and ``pi/2``. +.. function:: atanpi(x) + + Return the arc tangent of *x*, in half-turns. The result is between ``-0.5`` and + ``0.5``. + + .. versionadded:: next + + .. function:: atan2(y, x) Return ``atan(y / x)``, in radians. The result is between ``-pi`` and ``pi``. @@ -621,21 +652,54 @@ Trigonometric functions -1)`` is ``-3*pi/4``. +.. function:: atan2pi(y, x) + + Return ``atanpi(y / x)``, in half-turns. The result is between ``-1`` and ``1``. + The vector in the plane from the origin to point ``(x, y)`` makes this angle + with the positive X axis. The point of :func:`atan2pi` is that the signs of both + inputs are known to it, so it can compute the correct quadrant for the angle. + For example, ``atanpi(1)`` and ``atan2pi(1, 1)`` are both ``0.25``, but + ``atan2pi(-1, -1)`` is ``-0.75``. + + .. versionadded:: next + + .. function:: cos(x) Return the cosine of *x* radians. +.. function:: cospi(x) + + Return the cosine of *x* half-turns (*x⋅π* radians). + + .. versionadded:: next + + .. function:: sin(x) Return the sine of *x* radians. +.. function:: sinpi(x) + + Return the sine of *x* half-turns (*x⋅π* radians). + + .. versionadded:: next + + .. function:: tan(x) Return the tangent of *x* radians. +.. function:: tanpi(x) + + Return the tangent of *x* half-turns (*x⋅π* radians). + + .. versionadded:: next + + Hyperbolic functions -------------------- diff --git a/Doc/library/mimetypes.rst b/Doc/library/mimetypes.rst index f33098faf7d8a77..5c29fff146eef00 100644 --- a/Doc/library/mimetypes.rst +++ b/Doc/library/mimetypes.rst @@ -39,8 +39,8 @@ the information :func:`init` sets up. (e.g. :program:`compress` or :program:`gzip`). The encoding is suitable for use as a :mailheader:`Content-Encoding` header, **not** as a :mailheader:`Content-Transfer-Encoding` header. The mappings are table driven. - Encoding suffixes are case sensitive; type suffixes are first tried case - sensitively, then case insensitively. + Encoding suffixes are case-sensitive. Suffix mappings and type suffixes are + first tried case-sensitively, then case-insensitively. The optional *strict* argument is a flag specifying whether the list of known MIME types is limited to only the official types `registered with IANA @@ -131,6 +131,8 @@ behavior of the module. is already known the extension will be added to the list of known extensions. Valid extensions are empty or start with a ``'.'``. + Registered lower-case extensions are matched case-insensitively. + When *strict* is ``True`` (the default), the mapping will be added to the official MIME types, otherwise to the non-standard ones. @@ -312,6 +314,8 @@ than one MIME-type database; it provides an interface similar to the one of the extension is already known, the new type will replace the old one. When the type is already known the extension will be added to the list of known extensions. + Registered lower-case extensions are matched case-insensitively. + When *strict* is ``True`` (the default), the mapping will be added to the official MIME types, otherwise to the non-standard ones. diff --git a/Doc/library/operator.rst b/Doc/library/operator.rst index c0dab83977e427f..3d1c8cda13be381 100644 --- a/Doc/library/operator.rst +++ b/Doc/library/operator.rst @@ -110,7 +110,7 @@ The mathematical and bitwise operations are the most numerous: .. function:: and_(a, b) __and__(a, b) - Return the bitwise and of *a* and *b*. + Return ``a & b``. .. function:: floordiv(a, b) @@ -134,13 +134,13 @@ The mathematical and bitwise operations are the most numerous: __inv__(obj) __invert__(obj) - Return the bitwise inverse of the number *obj*. This is equivalent to ``~obj``. + Return ``~obj``. .. function:: lshift(a, b) __lshift__(a, b) - Return *a* shifted left by *b*. + Return ``a << b``. .. function:: mod(a, b) @@ -152,7 +152,7 @@ The mathematical and bitwise operations are the most numerous: .. function:: mul(a, b) __mul__(a, b) - Return ``a * b``, for *a* and *b* numbers. + Return ``a * b``. .. function:: matmul(a, b) @@ -172,25 +172,25 @@ The mathematical and bitwise operations are the most numerous: .. function:: or_(a, b) __or__(a, b) - Return the bitwise or of *a* and *b*. + Return ``a | b``. .. function:: pos(obj) __pos__(obj) - Return *obj* positive (``+obj``). + Return ``+obj``. .. function:: pow(a, b) __pow__(a, b) - Return ``a ** b``, for *a* and *b* numbers. + Return ``a ** b``. .. function:: rshift(a, b) __rshift__(a, b) - Return *a* shifted right by *b*. + Return ``a >> b``. .. function:: sub(a, b) @@ -209,7 +209,7 @@ The mathematical and bitwise operations are the most numerous: .. function:: xor(a, b) __xor__(a, b) - Return the bitwise exclusive or of *a* and *b*. + Return ``a ^ b``. Operations which work with sequences (some of them with mappings too) include: @@ -403,13 +403,18 @@ Python syntax and the functions in the :mod:`!operator` module. +-----------------------+-------------------------+---------------------------------------+ | Division | ``a // b`` | ``floordiv(a, b)`` | +-----------------------+-------------------------+---------------------------------------+ -| Bitwise And | ``a & b`` | ``and_(a, b)`` | +| Bitwise And, or | ``a & b`` | ``and_(a, b)`` | +| Intersection | | | +-----------------------+-------------------------+---------------------------------------+ -| Bitwise Exclusive Or | ``a ^ b`` | ``xor(a, b)`` | +| Bitwise Exclusive Or, | ``a ^ b`` | ``xor(a, b)`` | +| or Symmetric | | | +| Difference | | | +-----------------------+-------------------------+---------------------------------------+ -| Bitwise Inversion | ``~ a`` | ``invert(a)`` | +| Bitwise Inversion, or | ``~ a`` | ``invert(a)`` | +| Complement | | | +-----------------------+-------------------------+---------------------------------------+ -| Bitwise Or | ``a | b`` | ``or_(a, b)`` | +| Bitwise Or, or | ``a | b`` | ``or_(a, b)`` | +| Union | | | +-----------------------+-------------------------+---------------------------------------+ | Exponentiation | ``a ** b`` | ``pow(a, b)`` | +-----------------------+-------------------------+---------------------------------------+ diff --git a/Doc/library/profiling.sampling.rst b/Doc/library/profiling.sampling.rst index 39b6ea4e31cde72..aeb1a429b58515a 100644 --- a/Doc/library/profiling.sampling.rst +++ b/Doc/library/profiling.sampling.rst @@ -387,11 +387,6 @@ This requires one of: On Windows, the profiler requires administrative privileges or the ``SeDebugPrivilege`` privilege to read another process's memory. -*Note*: On Windows, ``python -m profiling.sampling`` fails inside a virtual -environment because the venv's ``python.exe`` is just a launcher shim that -re-executes the base interpreter as a child process. The shim itself isn't -a Python process and has no ``PyRuntime`` section to attach to. Instead, -run it from the global Python installation. Version compatibility --------------------- diff --git a/Doc/library/shlex.rst b/Doc/library/shlex.rst index 2ab12f2f6f9169e..2dfb0246d5d90c0 100644 --- a/Doc/library/shlex.rst +++ b/Doc/library/shlex.rst @@ -44,12 +44,15 @@ The :mod:`!shlex` module defines the following functions: .. versionadded:: 3.8 -.. function:: quote(s) +.. function:: quote(s, *, force=False) Return a shell-escaped version of the string *s*. The returned value is a string that can safely be used as one token in a shell command line, for cases where you cannot use a list. + If *force* is :const:`True`, then *s* is unconditionally quoted, + even if it is already safe for a shell without being quoted. + .. _shlex-quote-warning: .. warning:: @@ -91,8 +94,23 @@ The :mod:`!shlex` module defines the following functions: >>> command ['ls', '-l', 'somefile; rm -rf ~'] + The *force* keyword can be used to produce consistent behavior when + escaping multiple strings: + + >>> from shlex import quote + >>> filenames = ['my first file', 'file2', 'file 3'] + >>> filenames_some_escaped = [quote(f) for f in filenames] + >>> filenames_some_escaped + ["'my first file'", 'file2', "'file 3'"] + >>> filenames_all_escaped = [quote(f, force=True) for f in filenames] + >>> filenames_all_escaped + ["'my first file'", "'file2'", "'file 3'"] + .. versionadded:: 3.3 + .. versionchanged:: next + The *force* keyword was added. + The :mod:`!shlex` module defines the following class: diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 96bc9e7a0d61e3d..836aa91bb0885b1 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -842,65 +842,8 @@ Creating sockets The following functions all create :ref:`socket objects `. -.. class:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) - - Create a new socket using the given address family, socket type and protocol - number. The address family should be :const:`AF_INET` (the default), - :const:`AF_INET6`, :const:`AF_UNIX`, :const:`AF_CAN`, :const:`AF_PACKET`, - or :const:`AF_RDS`. The socket type should be :const:`SOCK_STREAM` (the - default), :const:`SOCK_DGRAM`, :const:`SOCK_RAW` or perhaps one of the other - ``SOCK_`` constants. The protocol number is usually zero and may be omitted - or in the case where the address family is :const:`AF_CAN` the protocol - should be one of :const:`CAN_RAW`, :const:`CAN_BCM`, :const:`CAN_ISOTP` or - :const:`CAN_J1939`. - - If *fileno* is specified, the values for *family*, *type*, and *proto* are - auto-detected from the specified file descriptor. Auto-detection can be - overruled by calling the function with explicit *family*, *type*, or *proto* - arguments. This only affects how Python represents e.g. the return value - of :meth:`socket.getpeername` but not the actual OS resource. Unlike - :func:`socket.fromfd`, *fileno* will return the same socket and not a - duplicate. This may help close a detached socket using - :meth:`socket.close`. - - The newly created socket is :ref:`non-inheritable `. - - .. audit-event:: socket.__new__ self,family,type,protocol socket.socket - - .. versionchanged:: 3.3 - The AF_CAN family was added. - The AF_RDS family was added. - - .. versionchanged:: 3.4 - The CAN_BCM protocol was added. - - .. versionchanged:: 3.4 - The returned socket is now non-inheritable. - - .. versionchanged:: 3.7 - The CAN_ISOTP protocol was added. - - .. versionchanged:: 3.7 - When :const:`SOCK_NONBLOCK` or :const:`SOCK_CLOEXEC` - bit flags are applied to *type* they are cleared, and - :attr:`socket.type` will not reflect them. They are still passed - to the underlying system ``socket()`` call. Therefore, - - :: - - sock = socket.socket( - socket.AF_INET, - socket.SOCK_STREAM | socket.SOCK_NONBLOCK) - - will still create a non-blocking socket on OSes that support - ``SOCK_NONBLOCK``, but ``sock.type`` will be set to - ``socket.SOCK_STREAM``. - - .. versionchanged:: 3.9 - The CAN_J1939 protocol was added. - - .. versionchanged:: 3.10 - The IPPROTO_MPTCP protocol was added. +The :class:`socket ` class constructor creates a new socket +directly; see :ref:`socket-objects` for its parameters and full description. .. function:: socketpair([family[, type[, proto]]]) @@ -1025,12 +968,6 @@ The following functions all create :ref:`socket objects `. .. versionadded:: 3.3 -.. data:: SocketType - - This is a Python type object that represents the socket object type. It is the - same as ``type(socket(...))``. - - Other functions ''''''''''''''' @@ -1538,642 +1475,709 @@ The :mod:`!socket` module also offers various network-related services: Socket Objects -------------- -Socket objects have the following methods. Except for -:meth:`~socket.makefile`, these correspond to Unix system calls applicable -to sockets. +.. class:: socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) -.. versionchanged:: 3.2 - Support for the :term:`context manager` protocol was added. Exiting the - context manager is equivalent to calling :meth:`~socket.close`. + Create a new socket using the given address family, socket type and protocol + number. The address family should be :const:`AF_INET` (the default), + :const:`AF_INET6`, :const:`AF_UNIX`, :const:`AF_CAN`, :const:`AF_PACKET`, + or :const:`AF_RDS`. The socket type should be :const:`SOCK_STREAM` (the + default), :const:`SOCK_DGRAM`, :const:`SOCK_RAW` or perhaps one of the other + ``SOCK_`` constants. The protocol number is usually zero and may be omitted + or in the case where the address family is :const:`AF_CAN` the protocol + should be one of :const:`CAN_RAW`, :const:`CAN_BCM`, :const:`CAN_ISOTP` or + :const:`CAN_J1939`. + If *fileno* is specified, the values for *family*, *type*, and *proto* are + auto-detected from the specified file descriptor. Auto-detection can be + overruled by calling the function with explicit *family*, *type*, or *proto* + arguments. This only affects how Python represents e.g. the return value + of :meth:`socket.getpeername` but not the actual OS resource. Unlike + :func:`socket.fromfd`, *fileno* will return the same socket and not a + duplicate. This may help close a detached socket using + :meth:`socket.close`. -.. method:: socket.accept() + The newly created socket is :ref:`non-inheritable `. - Accept a connection. The socket must be bound to an address and listening for - connections. The return value is a pair ``(conn, address)`` where *conn* is a - *new* socket object usable to send and receive data on the connection, and - *address* is the address bound to the socket on the other end of the connection. + .. audit-event:: socket.__new__ self,family,type,protocol socket.socket - The newly created socket is :ref:`non-inheritable `. + .. versionchanged:: 3.3 + The AF_CAN family was added. + The AF_RDS family was added. .. versionchanged:: 3.4 - The socket is now non-inheritable. + The CAN_BCM protocol was added. - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. versionchanged:: 3.4 + The returned socket is now non-inheritable. + .. versionchanged:: 3.7 + The CAN_ISOTP protocol was added. -.. method:: socket.bind(address) + .. versionchanged:: 3.7 + When :const:`SOCK_NONBLOCK` or :const:`SOCK_CLOEXEC` + bit flags are applied to *type* they are cleared, and + :attr:`socket.type` will not reflect them. They are still passed + to the underlying system ``socket()`` call. Therefore, - Bind the socket to *address*. The socket must not already be bound. The format - of *address* depends on the address family --- see :ref:`socket-addresses`. + :: - .. audit-event:: socket.bind self,address socket.socket.bind + sock = socket.socket( + socket.AF_INET, + socket.SOCK_STREAM | socket.SOCK_NONBLOCK) - .. availability:: not WASI. + will still create a non-blocking socket on OSes that support + ``SOCK_NONBLOCK``, but ``sock.type`` will be set to + ``socket.SOCK_STREAM``. + .. versionchanged:: 3.9 + The CAN_J1939 protocol was added. -.. method:: socket.close() + .. versionchanged:: 3.10 + The IPPROTO_MPTCP protocol was added. - Mark the socket closed. The underlying system resource (e.g. a file - descriptor) is also closed when all file objects from :meth:`makefile` - are closed. Once that happens, all future operations on the socket - object will fail. The remote end will receive no more data (after - queued data is flushed). + Socket objects have the following methods. Except for + :meth:`~socket.makefile`, these correspond to Unix system calls applicable + to sockets. - Sockets are automatically closed when they are garbage-collected, but - it is recommended to :meth:`close` them explicitly, or to use a - :keyword:`with` statement around them. + .. versionchanged:: 3.2 + Support for the :term:`context manager` protocol was added. Exiting the + context manager is equivalent to calling :meth:`~socket.close`. - .. versionchanged:: 3.6 - :exc:`OSError` is now raised if an error occurs when the underlying - :c:func:`close` call is made. - .. note:: + .. method:: accept() - :meth:`close` releases the resource associated with a connection but - does not necessarily close the connection immediately. If you want - to close the connection in a timely fashion, call :meth:`shutdown` - before :meth:`close`. + Accept a connection. The socket must be bound to an address and listening for + connections. The return value is a pair ``(conn, address)`` where *conn* is a + *new* socket object usable to send and receive data on the connection, and + *address* is the address bound to the socket on the other end of the connection. + The newly created socket is :ref:`non-inheritable `. -.. method:: socket.connect(address) + .. versionchanged:: 3.4 + The socket is now non-inheritable. - Connect to a remote socket at *address*. The format of *address* depends on the - address family --- see :ref:`socket-addresses`. + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - If the connection is interrupted by a signal, the method waits until the - connection completes, or raises a :exc:`TimeoutError` on timeout, if the - signal handler doesn't raise an exception and the socket is blocking or has - a timeout. For non-blocking sockets, the method raises an - :exc:`InterruptedError` exception if the connection is interrupted by a - signal (or the exception raised by the signal handler). - .. audit-event:: socket.connect self,address socket.socket.connect + .. method:: bind(address) - .. versionchanged:: 3.5 - The method now waits until the connection completes instead of raising an + Bind the socket to *address*. The socket must not already be bound. The format + of *address* depends on the address family --- see :ref:`socket-addresses`. + + .. audit-event:: socket.bind self,address socket.socket.bind + + .. availability:: not WASI. + + + .. method:: close() + + Mark the socket closed. The underlying system resource (e.g. a file + descriptor) is also closed when all file objects from :meth:`makefile` + are closed. Once that happens, all future operations on the socket + object will fail. The remote end will receive no more data (after + queued data is flushed). + + Sockets are automatically closed when they are garbage-collected, but + it is recommended to :meth:`close` them explicitly, or to use a + :keyword:`with` statement around them. + + .. versionchanged:: 3.6 + :exc:`OSError` is now raised if an error occurs when the underlying + :c:func:`!close` call is made. + + .. note:: + + :meth:`close` releases the resource associated with a connection but + does not necessarily close the connection immediately. If you want + to close the connection in a timely fashion, call :meth:`shutdown` + before :meth:`close`. + + + .. method:: connect(address) + + Connect to a remote socket at *address*. The format of *address* depends on the + address family --- see :ref:`socket-addresses`. + + If the connection is interrupted by a signal, the method waits until the + connection completes, or raises a :exc:`TimeoutError` on timeout, if the + signal handler doesn't raise an exception and the socket is blocking or has + a timeout. For non-blocking sockets, the method raises an :exc:`InterruptedError` exception if the connection is interrupted by a - signal, the signal handler doesn't raise an exception and the socket is - blocking or has a timeout (see the :pep:`475` for the rationale). + signal (or the exception raised by the signal handler). - .. availability:: not WASI. + .. audit-event:: socket.connect self,address socket.socket.connect + .. versionchanged:: 3.5 + The method now waits until the connection completes instead of raising an + :exc:`InterruptedError` exception if the connection is interrupted by a + signal, the signal handler doesn't raise an exception and the socket is + blocking or has a timeout (see the :pep:`475` for the rationale). -.. method:: socket.connect_ex(address) + .. availability:: not WASI. - Like ``connect(address)``, but return an error indicator instead of raising an - exception for errors returned by the C-level :c:func:`connect` call (other - problems, such as "host not found," can still raise exceptions). The error - indicator is ``0`` if the operation succeeded, otherwise the value of the - :c:data:`errno` variable. This is useful to support, for example, asynchronous - connects. - .. audit-event:: socket.connect self,address socket.socket.connect_ex + .. method:: connect_ex(address) - .. availability:: not WASI. + Like ``connect(address)``, but return an error indicator instead of raising an + exception for errors returned by the C-level :c:func:`!connect` call (other + problems, such as "host not found," can still raise exceptions). The error + indicator is ``0`` if the operation succeeded, otherwise the value of the + :c:data:`errno` variable. This is useful to support, for example, asynchronous + connects. -.. method:: socket.detach() + .. audit-event:: socket.connect self,address socket.socket.connect_ex - Put the socket object into closed state without actually closing the - underlying file descriptor. The file descriptor is returned, and can - be reused for other purposes. + .. availability:: not WASI. - .. versionadded:: 3.2 + .. method:: detach() + Put the socket object into closed state without actually closing the + underlying file descriptor. The file descriptor is returned, and can + be reused for other purposes. -.. method:: socket.dup() + .. versionadded:: 3.2 - Duplicate the socket. - The newly created socket is :ref:`non-inheritable `. + .. method:: dup() - .. versionchanged:: 3.4 - The socket is now non-inheritable. + Duplicate the socket. - .. availability:: not WASI. + The newly created socket is :ref:`non-inheritable `. + .. versionchanged:: 3.4 + The socket is now non-inheritable. -.. method:: socket.fileno() + .. availability:: not WASI. - Return the socket's file descriptor (a small integer), or -1 on failure. This - is useful with :func:`select.select`. - Under Windows the small integer returned by this method cannot be used where a - file descriptor can be used (such as :func:`os.fdopen`). Unix does not have - this limitation. + .. method:: fileno() -.. method:: socket.get_inheritable() + Return the socket's file descriptor (a small integer), or -1 on failure. This + is useful with :func:`select.select`. - Get the :ref:`inheritable flag ` of the socket's file - descriptor or socket's handle: ``True`` if the socket can be inherited in - child processes, ``False`` if it cannot. + Under Windows the small integer returned by this method cannot be used where a + file descriptor can be used (such as :func:`os.fdopen`). Unix does not have + this limitation. - .. versionadded:: 3.4 + .. method:: get_inheritable() + Get the :ref:`inheritable flag ` of the socket's file + descriptor or socket's handle: ``True`` if the socket can be inherited in + child processes, ``False`` if it cannot. -.. method:: socket.getpeername() + .. versionadded:: 3.4 - Return the remote address to which the socket is connected. This is useful to - find out the port number of a remote IPv4/v6 socket, for instance. The format - of the address returned depends on the address family --- see :ref:`socket-addresses`. - On some systems this function is not supported. + .. method:: getpeername() -.. method:: socket.getsockname() + Return the remote address to which the socket is connected. This is useful to + find out the port number of a remote IPv4/v6 socket, for instance. The format + of the address returned depends on the address family --- see :ref:`socket-addresses`. + On some systems this function is not supported. - Return the socket's own address. This is useful to find out the port number of - an IPv4/v6 socket, for instance. The format of the address returned depends on - the address family --- see :ref:`socket-addresses`. + .. method:: getsockname() -.. method:: socket.getsockopt(level, optname[, buflen]) + Return the socket's own address. This is useful to find out the port number of + an IPv4/v6 socket, for instance. The format of the address returned depends on + the address family --- see :ref:`socket-addresses`. - Return the value of the given socket option (see the Unix man page - :manpage:`getsockopt(2)`). The needed symbolic constants (:ref:`SO_\* etc. `) - are defined in this module. If *buflen* is absent, an integer option is assumed - and its integer value is returned by the function. If *buflen* is present, it - specifies the maximum length of the buffer used to receive the option in, and - this buffer is returned as a bytes object. It is up to the caller to decode the - contents of the buffer (see the optional built-in module :mod:`struct` for a way - to decode C structures encoded as byte strings). - .. availability:: not WASI. + .. method:: getsockopt(level, optname[, buflen]) + Return the value of the given socket option (see the Unix man page + :manpage:`getsockopt(2)`). The needed symbolic constants (:ref:`SO_\* etc. `) + are defined in this module. If *buflen* is absent, an integer option is assumed + and its integer value is returned by the function. If *buflen* is present, it + specifies the maximum length of the buffer used to receive the option in, and + this buffer is returned as a bytes object. It is up to the caller to decode the + contents of the buffer (see the optional built-in module :mod:`struct` for a way + to decode C structures encoded as byte strings). -.. method:: socket.getblocking() + .. availability:: not WASI. - Return ``True`` if socket is in blocking mode, ``False`` if in - non-blocking. - This is equivalent to checking ``socket.gettimeout() != 0``. + .. method:: getblocking() - .. versionadded:: 3.7 + Return ``True`` if socket is in blocking mode, ``False`` if in + non-blocking. + This is equivalent to checking ``socket.gettimeout() != 0``. -.. method:: socket.gettimeout() + .. versionadded:: 3.7 - Return the timeout in seconds (float) associated with socket operations, - or ``None`` if no timeout is set. This reflects the last call to - :meth:`setblocking` or :meth:`settimeout`. + .. method:: gettimeout() -.. method:: socket.ioctl(control, option) + Return the timeout in seconds (float) associated with socket operations, + or ``None`` if no timeout is set. This reflects the last call to + :meth:`setblocking` or :meth:`settimeout`. - The :meth:`ioctl` method is a limited interface to the WSAIoctl system - interface. Please refer to the `Win32 documentation - `_ for more - information. - On other platforms, the generic :func:`fcntl.fcntl` and :func:`fcntl.ioctl` - functions may be used; they accept a socket object as their first argument. + .. method:: ioctl(control, option) - Currently only the following control codes are supported: - ``SIO_RCVALL``, ``SIO_KEEPALIVE_VALS``, and ``SIO_LOOPBACK_FAST_PATH``. + The :meth:`ioctl` method is a limited interface to the WSAIoctl system + interface. Please refer to the `Win32 documentation + `_ for more + information. - .. availability:: Windows + On other platforms, the generic :func:`fcntl.fcntl` and :func:`fcntl.ioctl` + functions may be used; they accept a socket object as their first argument. - .. versionchanged:: 3.6 - ``SIO_LOOPBACK_FAST_PATH`` was added. + Currently only the following control codes are supported: + ``SIO_RCVALL``, ``SIO_KEEPALIVE_VALS``, and ``SIO_LOOPBACK_FAST_PATH``. + .. availability:: Windows -.. method:: socket.listen([backlog]) + .. versionchanged:: 3.6 + ``SIO_LOOPBACK_FAST_PATH`` was added. - Enable a server to accept connections. If *backlog* is specified, it must - be at least 0 (if it is lower, it is set to 0); it specifies the number of - unaccepted connections that the system will allow before refusing new - connections. If not specified, a default reasonable value is chosen. - .. availability:: not WASI. + .. method:: listen([backlog]) - .. versionchanged:: 3.5 - The *backlog* parameter is now optional. + Enable a server to accept connections. If *backlog* is specified, it must + be at least 0 (if it is lower, it is set to 0); it specifies the number of + unaccepted connections that the system will allow before refusing new + connections. If not specified, a default reasonable value is chosen. + .. availability:: not WASI. -.. method:: socket.makefile(mode='r', buffering=None, *, encoding=None, \ - errors=None, newline=None) + .. versionchanged:: 3.5 + The *backlog* parameter is now optional. - .. index:: single: I/O control; buffering - Return a :term:`file object` associated with the socket. The exact returned - type depends on the arguments given to :meth:`makefile`. These arguments are - interpreted the same way as by the built-in :func:`open` function, except - the only supported *mode* values are ``'r'`` (default), ``'w'``, ``'b'``, or - a combination of those. + .. method:: makefile(mode='r', buffering=None, *, encoding=None, \ + errors=None, newline=None) - The socket must be in blocking mode; it can have a timeout, but the file - object's internal buffer may end up in an inconsistent state if a timeout - occurs. + .. index:: single: I/O control; buffering - Closing the file object returned by :meth:`makefile` won't close the - original socket unless all other file objects have been closed and - :meth:`socket.close` has been called on the socket object. + Return a :term:`file object` associated with the socket. The exact returned + type depends on the arguments given to :meth:`makefile`. These arguments are + interpreted the same way as by the built-in :func:`open` function, except + the only supported *mode* values are ``'r'`` (default), ``'w'``, ``'b'``, or + a combination of those. - .. note:: + The socket must be in blocking mode; it can have a timeout, but the file + object's internal buffer may end up in an inconsistent state if a timeout + occurs. - On Windows, the file-like object created by :meth:`makefile` cannot be - used where a file object with a file descriptor is expected, such as the - stream arguments of :meth:`subprocess.Popen`. + Closing the file object returned by :meth:`makefile` won't close the + original socket unless all other file objects have been closed and + :meth:`socket.close` has been called on the socket object. + .. note:: -.. method:: socket.recv(bufsize[, flags]) + On Windows, the file-like object created by :meth:`makefile` cannot be + used where a file object with a file descriptor is expected, such as the + stream arguments of :meth:`subprocess.Popen`. - Receive data from the socket. The return value is a bytes object representing the - data received. The maximum amount of data to be received at once is specified - by *bufsize*. A returned empty bytes object indicates that the client has disconnected. - See the Unix manual page :manpage:`recv(2)` for the meaning of the optional argument - *flags*; it defaults to zero. - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: recv(bufsize[, flags]) + Receive data from the socket. The return value is a bytes object representing the + data received. The maximum amount of data to be received at once is specified + by *bufsize*. A returned empty bytes object indicates that the client has disconnected. + See the Unix manual page :manpage:`recv(2)` for the meaning of the optional argument + *flags*; it defaults to zero. -.. method:: socket.recvfrom(bufsize[, flags]) + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - Receive data from the socket. The return value is a pair ``(bytes, address)`` - where *bytes* is a bytes object representing the data received and *address* is the - address of the socket sending the data. See the Unix manual page - :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults - to zero. The format of *address* depends on the address family --- see - :ref:`socket-addresses`. - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: recvfrom(bufsize[, flags]) - .. versionchanged:: 3.7 - For multicast IPv6 address, first item of *address* does not contain - ``%scope_id`` part anymore. In order to get full IPv6 address use - :func:`getnameinfo`. - -.. method:: socket.recvmsg(bufsize[, ancbufsize[, flags]]) - - Receive normal data (up to *bufsize* bytes) and ancillary data from - the socket. The *ancbufsize* argument sets the size in bytes of - the internal buffer used to receive the ancillary data; it defaults - to 0, meaning that no ancillary data will be received. Appropriate - buffer sizes for ancillary data can be calculated using - :func:`CMSG_SPACE` or :func:`CMSG_LEN`, and items which do not fit - into the buffer might be truncated or discarded. The *flags* - argument defaults to 0 and has the same meaning as for - :meth:`recv`. - - The return value is a 4-tuple: ``(data, ancdata, msg_flags, - address)``. The *data* item is a :class:`bytes` object holding the - non-ancillary data received. The *ancdata* item is a list of zero - or more tuples ``(cmsg_level, cmsg_type, cmsg_data)`` representing - the ancillary data (control messages) received: *cmsg_level* and - *cmsg_type* are integers specifying the protocol level and - protocol-specific type respectively, and *cmsg_data* is a - :class:`bytes` object holding the associated data. The *msg_flags* - item is the bitwise OR of various flags indicating conditions on - the received message; see your system documentation for details. - If the receiving socket is unconnected, *address* is the address of - the sending socket, if available; otherwise, its value is - unspecified. - - On some systems, :meth:`sendmsg` and :meth:`recvmsg` can be used to - pass file descriptors between processes over an :const:`AF_UNIX` - socket. When this facility is used (it is often restricted to - :const:`SOCK_STREAM` sockets), :meth:`recvmsg` will return, in its - ancillary data, items of the form ``(socket.SOL_SOCKET, - socket.SCM_RIGHTS, fds)``, where *fds* is a :class:`bytes` object - representing the new file descriptors as a binary array of the - native C :c:expr:`int` type. If :meth:`recvmsg` raises an - exception after the system call returns, it will first attempt to - close any file descriptors received via this mechanism. - - Some systems do not indicate the truncated length of ancillary data - items which have been only partially received. If an item appears - to extend beyond the end of the buffer, :meth:`recvmsg` will issue - a :exc:`RuntimeWarning`, and will return the part of it which is - inside the buffer provided it has not been truncated before the - start of its associated data. - - On systems which support the :const:`SCM_RIGHTS` mechanism, the - following function will receive up to *maxfds* file descriptors, - returning the message data and a list containing the descriptors - (while ignoring unexpected conditions such as unrelated control - messages being received). See also :meth:`sendmsg`. :: - - import socket, array - - def recv_fds(sock, msglen, maxfds): - fds = array.array("i") # Array of ints - msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize)) - for cmsg_level, cmsg_type, cmsg_data in ancdata: - if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: - # Append data, ignoring any truncated integers at the end. - fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) - return msg, list(fds) - - .. availability:: Unix. + Receive data from the socket. The return value is a pair ``(bytes, address)`` + where *bytes* is a bytes object representing the data received and *address* is the + address of the socket sending the data. See the Unix manual page + :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults + to zero. The format of *address* depends on the address family --- see + :ref:`socket-addresses`. - Most Unix platforms. + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - .. versionadded:: 3.3 + .. versionchanged:: 3.7 + For multicast IPv6 address, first item of *address* does not contain + ``%scope_id`` part anymore. In order to get full IPv6 address use + :func:`getnameinfo`. - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - - -.. method:: socket.recvmsg_into(buffers[, ancbufsize[, flags]]) - - Receive normal data and ancillary data from the socket, behaving as - :meth:`recvmsg` would, but scatter the non-ancillary data into a - series of buffers instead of returning a new bytes object. The - *buffers* argument must be an iterable of objects that export - writable buffers (e.g. :class:`bytearray` objects); these will be - filled with successive chunks of the non-ancillary data until it - has all been written or there are no more buffers. The operating - system may set a limit (:func:`~os.sysconf` value ``SC_IOV_MAX``) - on the number of buffers that can be used. The *ancbufsize* and - *flags* arguments have the same meaning as for :meth:`recvmsg`. - - The return value is a 4-tuple: ``(nbytes, ancdata, msg_flags, - address)``, where *nbytes* is the total number of bytes of - non-ancillary data written into the buffers, and *ancdata*, - *msg_flags* and *address* are the same as for :meth:`recvmsg`. - - Example:: - - >>> import socket - >>> s1, s2 = socket.socketpair() - >>> b1 = bytearray(b'----') - >>> b2 = bytearray(b'0123456789') - >>> b3 = bytearray(b'--------------') - >>> s1.send(b'Mary had a little lamb') - 22 - >>> s2.recvmsg_into([b1, memoryview(b2)[2:9], b3]) - (22, [], 0, None) - >>> [b1, b2, b3] - [bytearray(b'Mary'), bytearray(b'01 had a 9'), bytearray(b'little lamb---')] - - .. availability:: Unix. + .. method:: recvmsg(bufsize[, ancbufsize[, flags]]) + + Receive normal data (up to *bufsize* bytes) and ancillary data from + the socket. The *ancbufsize* argument sets the size in bytes of + the internal buffer used to receive the ancillary data; it defaults + to 0, meaning that no ancillary data will be received. Appropriate + buffer sizes for ancillary data can be calculated using + :func:`CMSG_SPACE` or :func:`CMSG_LEN`, and items which do not fit + into the buffer might be truncated or discarded. The *flags* + argument defaults to 0 and has the same meaning as for + :meth:`recv`. + + The return value is a 4-tuple: ``(data, ancdata, msg_flags, + address)``. The *data* item is a :class:`bytes` object holding the + non-ancillary data received. The *ancdata* item is a list of zero + or more tuples ``(cmsg_level, cmsg_type, cmsg_data)`` representing + the ancillary data (control messages) received: *cmsg_level* and + *cmsg_type* are integers specifying the protocol level and + protocol-specific type respectively, and *cmsg_data* is a + :class:`bytes` object holding the associated data. The *msg_flags* + item is the bitwise OR of various flags indicating conditions on + the received message; see your system documentation for details. + If the receiving socket is unconnected, *address* is the address of + the sending socket, if available; otherwise, its value is + unspecified. + + On some systems, :meth:`sendmsg` and :meth:`recvmsg` can be used to + pass file descriptors between processes over an :const:`AF_UNIX` + socket. When this facility is used (it is often restricted to + :const:`SOCK_STREAM` sockets), :meth:`recvmsg` will return, in its + ancillary data, items of the form ``(socket.SOL_SOCKET, + socket.SCM_RIGHTS, fds)``, where *fds* is a :class:`bytes` object + representing the new file descriptors as a binary array of the + native C :c:expr:`int` type. If :meth:`recvmsg` raises an + exception after the system call returns, it will first attempt to + close any file descriptors received via this mechanism. + + Some systems do not indicate the truncated length of ancillary data + items which have been only partially received. If an item appears + to extend beyond the end of the buffer, :meth:`recvmsg` will issue + a :exc:`RuntimeWarning`, and will return the part of it which is + inside the buffer provided it has not been truncated before the + start of its associated data. + + On systems which support the :const:`!SCM_RIGHTS` mechanism, the + following function will receive up to *maxfds* file descriptors, + returning the message data and a list containing the descriptors + (while ignoring unexpected conditions such as unrelated control + messages being received). See also :meth:`sendmsg`. :: + + import socket, array + + def recv_fds(sock, msglen, maxfds): + fds = array.array("i") # Array of ints + msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize)) + for cmsg_level, cmsg_type, cmsg_data in ancdata: + if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: + # Append data, ignoring any truncated integers at the end. + fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) + return msg, list(fds) + + .. availability:: Unix. + + Most Unix platforms. + + .. versionadded:: 3.3 + + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + + + .. method:: recvmsg_into(buffers[, ancbufsize[, flags]]) + + Receive normal data and ancillary data from the socket, behaving as + :meth:`recvmsg` would, but scatter the non-ancillary data into a + series of buffers instead of returning a new bytes object. The + *buffers* argument must be an iterable of objects that export + writable buffers (e.g. :class:`bytearray` objects); these will be + filled with successive chunks of the non-ancillary data until it + has all been written or there are no more buffers. The operating + system may set a limit (:func:`~os.sysconf` value ``SC_IOV_MAX``) + on the number of buffers that can be used. The *ancbufsize* and + *flags* arguments have the same meaning as for :meth:`recvmsg`. + + The return value is a 4-tuple: ``(nbytes, ancdata, msg_flags, + address)``, where *nbytes* is the total number of bytes of + non-ancillary data written into the buffers, and *ancdata*, + *msg_flags* and *address* are the same as for :meth:`recvmsg`. + + Example:: + + >>> import socket + >>> s1, s2 = socket.socketpair() + >>> b1 = bytearray(b'----') + >>> b2 = bytearray(b'0123456789') + >>> b3 = bytearray(b'--------------') + >>> s1.send(b'Mary had a little lamb') + 22 + >>> s2.recvmsg_into([b1, memoryview(b2)[2:9], b3]) + (22, [], 0, None) + >>> [b1, b2, b3] + [bytearray(b'Mary'), bytearray(b'01 had a 9'), bytearray(b'little lamb---')] + + .. availability:: Unix. + + Most Unix platforms. + + .. versionadded:: 3.3 + + + .. method:: recvfrom_into(buffer[, nbytes[, flags]]) + + Receive data from the socket, writing it into *buffer* instead of creating a + new bytestring. The return value is a pair ``(nbytes, address)`` where *nbytes* is + the number of bytes received and *address* is the address of the socket sending + the data. See the Unix manual page :manpage:`recv(2)` for the meaning of the + optional argument *flags*; it defaults to zero. The format of *address* + depends on the address family --- see :ref:`socket-addresses`. + + + .. method:: recv_into(buffer[, nbytes[, flags]]) + + Receive up to *nbytes* bytes from the socket, storing the data into a buffer + rather than creating a new bytestring. If *nbytes* is not specified (or 0), + receive up to the size available in the given buffer. Returns the number of + bytes received. See the Unix manual page :manpage:`recv(2)` for the meaning + of the optional argument *flags*; it defaults to zero. - Most Unix platforms. - .. versionadded:: 3.3 + .. method:: send(bytes[, flags]) + Send data to the socket. The socket must be connected to a remote socket. The + optional *flags* argument has the same meaning as for :meth:`recv`. + Returns the number of bytes sent. Applications are responsible for checking that + all data has been sent; if only some of the data was transmitted, the + application needs to attempt delivery of the remaining data. For further + information on this topic, consult the :ref:`socket-howto`. -.. method:: socket.recvfrom_into(buffer[, nbytes[, flags]]) + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - Receive data from the socket, writing it into *buffer* instead of creating a - new bytestring. The return value is a pair ``(nbytes, address)`` where *nbytes* is - the number of bytes received and *address* is the address of the socket sending - the data. See the Unix manual page :manpage:`recv(2)` for the meaning of the - optional argument *flags*; it defaults to zero. The format of *address* - depends on the address family --- see :ref:`socket-addresses`. + .. method:: sendall(bytes[, flags]) -.. method:: socket.recv_into(buffer[, nbytes[, flags]]) + Send data to the socket. The socket must be connected to a remote socket. The + optional *flags* argument has the same meaning as for :meth:`recv`. + Unlike :meth:`send`, this method continues to send data from *bytes* until + either all data has been sent or an error occurs. ``None`` is returned on + success. On error, an exception is raised, and there is no way to determine how + much data, if any, was successfully sent. - Receive up to *nbytes* bytes from the socket, storing the data into a buffer - rather than creating a new bytestring. If *nbytes* is not specified (or 0), - receive up to the size available in the given buffer. Returns the number of - bytes received. See the Unix manual page :manpage:`recv(2)` for the meaning - of the optional argument *flags*; it defaults to zero. + .. versionchanged:: 3.5 + The socket timeout is no longer reset each time data is sent successfully. + The socket timeout is now the maximum total duration to send all data. + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). -.. method:: socket.send(bytes[, flags]) - Send data to the socket. The socket must be connected to a remote socket. The - optional *flags* argument has the same meaning as for :meth:`recv`. - Returns the number of bytes sent. Applications are responsible for checking that - all data has been sent; if only some of the data was transmitted, the - application needs to attempt delivery of the remaining data. For further - information on this topic, consult the :ref:`socket-howto`. + .. method:: sendto(bytes, address) + sendto(bytes, flags, address) - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + Send data to the socket. The socket should not be connected to a remote socket, + since the destination socket is specified by *address*. The optional *flags* + argument has the same meaning as for :meth:`recv`. Return the number of + bytes sent. The format of *address* depends on the address family --- see + :ref:`socket-addresses`. + .. audit-event:: socket.sendto self,address socket.socket.sendto -.. method:: socket.sendall(bytes[, flags]) + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - Send data to the socket. The socket must be connected to a remote socket. The - optional *flags* argument has the same meaning as for :meth:`recv`. - Unlike :meth:`send`, this method continues to send data from *bytes* until - either all data has been sent or an error occurs. ``None`` is returned on - success. On error, an exception is raised, and there is no way to determine how - much data, if any, was successfully sent. - .. versionchanged:: 3.5 - The socket timeout is no longer reset each time data is sent successfully. - The socket timeout is now the maximum total duration to send all data. + .. method:: sendmsg(buffers[, ancdata[, flags[, address]]]) - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + Send normal and ancillary data to the socket, gathering the + non-ancillary data from a series of buffers and concatenating it + into a single message. The *buffers* argument specifies the + non-ancillary data as an iterable of + :term:`bytes-like objects ` + (e.g. :class:`bytes` objects); the operating system may set a limit + (:func:`~os.sysconf` value ``SC_IOV_MAX``) on the number of buffers + that can be used. The *ancdata* argument specifies the ancillary + data (control messages) as an iterable of zero or more tuples + ``(cmsg_level, cmsg_type, cmsg_data)``, where *cmsg_level* and + *cmsg_type* are integers specifying the protocol level and + protocol-specific type respectively, and *cmsg_data* is a + bytes-like object holding the associated data. Note that + some systems (in particular, systems without :func:`CMSG_SPACE`) + might support sending only one control message per call. The + *flags* argument defaults to 0 and has the same meaning as for + :meth:`send`. If *address* is supplied and not ``None``, it sets a + destination address for the message. The return value is the + number of bytes of non-ancillary data sent. + The following function sends the list of file descriptors *fds* + over an :const:`AF_UNIX` socket, on systems which support the + :const:`!SCM_RIGHTS` mechanism. See also :meth:`recvmsg`. :: -.. method:: socket.sendto(bytes, address) - socket.sendto(bytes, flags, address) + import socket, array - Send data to the socket. The socket should not be connected to a remote socket, - since the destination socket is specified by *address*. The optional *flags* - argument has the same meaning as for :meth:`recv`. Return the number of - bytes sent. The format of *address* depends on the address family --- see - :ref:`socket-addresses`. + def send_fds(sock, msg, fds): + return sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", fds))]) - .. audit-event:: socket.sendto self,address socket.socket.sendto + .. availability:: Unix, not WASI. - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - - -.. method:: socket.sendmsg(buffers[, ancdata[, flags[, address]]]) - - Send normal and ancillary data to the socket, gathering the - non-ancillary data from a series of buffers and concatenating it - into a single message. The *buffers* argument specifies the - non-ancillary data as an iterable of - :term:`bytes-like objects ` - (e.g. :class:`bytes` objects); the operating system may set a limit - (:func:`~os.sysconf` value ``SC_IOV_MAX``) on the number of buffers - that can be used. The *ancdata* argument specifies the ancillary - data (control messages) as an iterable of zero or more tuples - ``(cmsg_level, cmsg_type, cmsg_data)``, where *cmsg_level* and - *cmsg_type* are integers specifying the protocol level and - protocol-specific type respectively, and *cmsg_data* is a - bytes-like object holding the associated data. Note that - some systems (in particular, systems without :func:`CMSG_SPACE`) - might support sending only one control message per call. The - *flags* argument defaults to 0 and has the same meaning as for - :meth:`send`. If *address* is supplied and not ``None``, it sets a - destination address for the message. The return value is the - number of bytes of non-ancillary data sent. - - The following function sends the list of file descriptors *fds* - over an :const:`AF_UNIX` socket, on systems which support the - :const:`SCM_RIGHTS` mechanism. See also :meth:`recvmsg`. :: - - import socket, array - - def send_fds(sock, msg, fds): - return sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.array("i", fds))]) + Most Unix platforms. - .. availability:: Unix, not WASI. + .. audit-event:: socket.sendmsg self,address socket.socket.sendmsg - Most Unix platforms. + .. versionadded:: 3.3 - .. audit-event:: socket.sendmsg self,address socket.socket.sendmsg + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). - .. versionadded:: 3.3 + .. method:: sendmsg_afalg([msg], *, op[, iv[, assoclen[, flags]]]) - .. versionchanged:: 3.5 - If the system call is interrupted and the signal handler does not raise - an exception, the method now retries the system call instead of raising - an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + Specialized version of :meth:`~socket.sendmsg` for :const:`AF_ALG` socket. + Set mode, IV, AEAD associated data length and flags for :const:`AF_ALG` socket. -.. method:: socket.sendmsg_afalg([msg], *, op[, iv[, assoclen[, flags]]]) + .. availability:: Linux >= 2.6.38. - Specialized version of :meth:`~socket.sendmsg` for :const:`AF_ALG` socket. - Set mode, IV, AEAD associated data length and flags for :const:`AF_ALG` socket. + .. versionadded:: 3.6 - .. availability:: Linux >= 2.6.38. + .. method:: sendfile(file, offset=0, count=None) - .. versionadded:: 3.6 + Send a file until EOF is reached by using high-performance + :mod:`os.sendfile` and return the total number of bytes which were sent. + *file* must be a regular file object opened in binary mode. If + :mod:`os.sendfile` is not available (e.g. Windows) or *file* is not a + regular file :meth:`send` will be used instead. *offset* tells from where to + start reading the file. If specified, *count* is the total number of bytes + to transmit as opposed to sending the file until EOF is reached. File + position is updated on return or also in case of error in which case + :meth:`file.tell() ` can be used to figure out the number of + bytes which were sent. The socket must be of :const:`SOCK_STREAM` type. + Non-blocking sockets are not supported. -.. method:: socket.sendfile(file, offset=0, count=None) + .. versionadded:: 3.5 - Send a file until EOF is reached by using high-performance - :mod:`os.sendfile` and return the total number of bytes which were sent. - *file* must be a regular file object opened in binary mode. If - :mod:`os.sendfile` is not available (e.g. Windows) or *file* is not a - regular file :meth:`send` will be used instead. *offset* tells from where to - start reading the file. If specified, *count* is the total number of bytes - to transmit as opposed to sending the file until EOF is reached. File - position is updated on return or also in case of error in which case - :meth:`file.tell() ` can be used to figure out the number of - bytes which were sent. The socket must be of :const:`SOCK_STREAM` type. - Non-blocking sockets are not supported. + .. method:: set_inheritable(inheritable) - .. versionadded:: 3.5 + Set the :ref:`inheritable flag ` of the socket's file + descriptor or socket's handle. -.. method:: socket.set_inheritable(inheritable) + .. versionadded:: 3.4 - Set the :ref:`inheritable flag ` of the socket's file - descriptor or socket's handle. - .. versionadded:: 3.4 + .. method:: setblocking(flag) + Set blocking or non-blocking mode of the socket: if *flag* is false, the + socket is set to non-blocking, else to blocking mode. -.. method:: socket.setblocking(flag) + This method is a shorthand for certain :meth:`~socket.settimeout` calls: - Set blocking or non-blocking mode of the socket: if *flag* is false, the - socket is set to non-blocking, else to blocking mode. + * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` - This method is a shorthand for certain :meth:`~socket.settimeout` calls: + * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0.0)`` - * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` + .. versionchanged:: 3.7 + The method no longer applies :const:`SOCK_NONBLOCK` flag on + :attr:`socket.type`. - * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0.0)`` - .. versionchanged:: 3.7 - The method no longer applies :const:`SOCK_NONBLOCK` flag on - :attr:`socket.type`. + .. method:: settimeout(value) + Set a timeout on blocking socket operations. The *value* argument can be a + nonnegative real number expressing seconds, or ``None``. + If a non-zero value is given, subsequent socket operations will raise a + :exc:`timeout` exception if the timeout period *value* has elapsed before + the operation has completed. If zero is given, the socket is put in + non-blocking mode. If ``None`` is given, the socket is put in blocking mode. -.. method:: socket.settimeout(value) + For further information, please consult the :ref:`notes on socket timeouts `. - Set a timeout on blocking socket operations. The *value* argument can be a - nonnegative real number expressing seconds, or ``None``. - If a non-zero value is given, subsequent socket operations will raise a - :exc:`timeout` exception if the timeout period *value* has elapsed before - the operation has completed. If zero is given, the socket is put in - non-blocking mode. If ``None`` is given, the socket is put in blocking mode. + .. versionchanged:: 3.7 + The method no longer toggles :const:`SOCK_NONBLOCK` flag on + :attr:`socket.type`. - For further information, please consult the :ref:`notes on socket timeouts `. + .. versionchanged:: 3.15 + Accepts any real number, not only integer or float. - .. versionchanged:: 3.7 - The method no longer toggles :const:`SOCK_NONBLOCK` flag on - :attr:`socket.type`. - .. versionchanged:: 3.15 - Accepts any real number, not only integer or float. + .. method:: setsockopt(level, optname, value: int | Buffer) + setsockopt(level, optname, None, optlen: int) + .. index:: pair: module; struct -.. method:: socket.setsockopt(level, optname, value: int | Buffer) - socket.setsockopt(level, optname, None, optlen: int) + Set the value of the given socket option (see the Unix manual page + :manpage:`setsockopt(2)`). The needed symbolic constants are defined in this + module (:ref:`!SO_\* etc. `). The value can be an integer, + ``None`` or a :term:`bytes-like object` representing a buffer. In the latter + case it is up to the caller to ensure that the bytestring contains the + proper bits (see the optional built-in module :mod:`struct` for a way to + encode C structures as bytestrings). When *value* is set to ``None``, + *optlen* argument is required. It's equivalent to calling :c:func:`!setsockopt` C + function with ``optval=NULL`` and ``optlen=optlen``. - .. index:: pair: module; struct + .. versionchanged:: 3.5 + Writable :term:`bytes-like object` is now accepted. - Set the value of the given socket option (see the Unix manual page - :manpage:`setsockopt(2)`). The needed symbolic constants are defined in this - module (:ref:`!SO_\* etc. `). The value can be an integer, - ``None`` or a :term:`bytes-like object` representing a buffer. In the latter - case it is up to the caller to ensure that the bytestring contains the - proper bits (see the optional built-in module :mod:`struct` for a way to - encode C structures as bytestrings). When *value* is set to ``None``, - *optlen* argument is required. It's equivalent to calling :c:func:`setsockopt` C - function with ``optval=NULL`` and ``optlen=optlen``. + .. versionchanged:: 3.6 + setsockopt(level, optname, None, optlen: int) form added. - .. versionchanged:: 3.5 - Writable :term:`bytes-like object` is now accepted. + .. availability:: not WASI. - .. versionchanged:: 3.6 - setsockopt(level, optname, None, optlen: int) form added. - .. availability:: not WASI. + .. method:: shutdown(how) + Shut down one or both halves of the connection. If *how* is :const:`SHUT_RD`, + further receives are disallowed. If *how* is :const:`SHUT_WR`, further sends + are disallowed. If *how* is :const:`SHUT_RDWR`, further sends and receives are + disallowed. -.. method:: socket.shutdown(how) + .. availability:: not WASI. - Shut down one or both halves of the connection. If *how* is :const:`SHUT_RD`, - further receives are disallowed. If *how* is :const:`SHUT_WR`, further sends - are disallowed. If *how* is :const:`SHUT_RDWR`, further sends and receives are - disallowed. - .. availability:: not WASI. + .. method:: share(process_id) + Duplicate a socket and prepare it for sharing with a target process. The + target process must be provided with *process_id*. The resulting bytes object + can then be passed to the target process using some form of interprocess + communication and the socket can be recreated there using :func:`fromshare`. + Once this method has been called, it is safe to close the socket since + the operating system has already duplicated it for the target process. -.. method:: socket.share(process_id) + .. availability:: Windows. - Duplicate a socket and prepare it for sharing with a target process. The - target process must be provided with *process_id*. The resulting bytes object - can then be passed to the target process using some form of interprocess - communication and the socket can be recreated there using :func:`fromshare`. - Once this method has been called, it is safe to close the socket since - the operating system has already duplicated it for the target process. + .. versionadded:: 3.3 - .. availability:: Windows. - .. versionadded:: 3.3 + Note that there are no methods :meth:`!read` or :meth:`!write`; use + :meth:`~socket.recv` and :meth:`~socket.send` without *flags* argument instead. + Socket objects also have these (read-only) attributes that correspond to the + values given to the :class:`~socket.socket` constructor. -Note that there are no methods :meth:`read` or :meth:`write`; use -:meth:`~socket.recv` and :meth:`~socket.send` without *flags* argument instead. -Socket objects also have these (read-only) attributes that correspond to the -values given to the :class:`~socket.socket` constructor. + .. attribute:: family + The socket family. -.. attribute:: socket.family - The socket family. + .. attribute:: type + The socket type. -.. attribute:: socket.type - The socket type. + .. attribute:: proto + The socket protocol. -.. attribute:: socket.proto - The socket protocol. +.. class:: SocketType + The base class of the :class:`~socket.socket` type, re-exported from + :mod:`!_socket`. An instance check such as + ``isinstance(socket(...), SocketType)`` is true, but ``SocketType`` is not + the same as ``type(socket(...))``, which is :class:`~socket.socket` itself. .. _socket-timeouts: diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index c0f3757e583e95d..66fe6c7aee48626 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -146,9 +146,9 @@ purposes. *cadata* is given) or uses :meth:`SSLContext.load_default_certs` to load default CA certificates. - When :attr:`~SSLContext.keylog_filename` is supported and the environment - variable :envvar:`SSLKEYLOGFILE` is set, :func:`create_default_context` - enables key logging. + When the environment variable :envvar:`!SSLKEYLOGFILE` is set, + :func:`create_default_context` enables key logging by setting + :attr:`~SSLContext.keylog_filename` to the variable's value. The default settings for this context include :data:`VERIFY_X509_PARTIAL_CHAIN` and :data:`VERIFY_X509_STRICT`. @@ -1121,7 +1121,7 @@ SSL sockets :meth:`SSLContext.wrap_socket` to wrap a socket. .. versionchanged:: 3.7 - :class:`SSLSocket` instances must to created with + :class:`SSLSocket` instances must be created with :meth:`~SSLContext.wrap_socket`. In earlier versions, it was possible to create instances directly. This was never documented or officially supported. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index c8f2cca484ab311..a47e1ffb1a6afb1 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2174,9 +2174,25 @@ expression support in the :mod:`re` module). character, ``False`` otherwise. Digits include decimal characters and digits that need special handling, such as the compatibility superscript digits. This covers digits which cannot be used to form numbers in base 10, - like the Kharosthi numbers. Formally, a digit is a character that has the + like the `Kharosthi numbers `__. + Formally, a digit is a character that has the property value Numeric_Type=Digit or Numeric_Type=Decimal. + For example: + + .. doctest:: + + >>> '0123456789'.isdigit() + True + >>> '٠١٢٣٤٥٦٧٨٩'.isdigit() # Arabic-Indic digits zero to nine + True + >>> '⅕'.isdigit() # Vulgar fraction one fifth + False + >>> '²'.isdecimal(), '²'.isdigit(), '²'.isnumeric() + (False, True, True) + + See also :meth:`isdecimal` and :meth:`isnumeric`. + .. method:: str.isidentifier() @@ -2217,15 +2233,14 @@ expression support in the :mod:`re` module). >>> '0123456789'.isnumeric() True - >>> '٠١٢٣٤٥٦٧٨٩'.isnumeric() # Arabic-indic digit zero to nine + >>> '٠١٢٣٤٥٦٧٨٩'.isnumeric() # Arabic-Indic digits zero to nine True >>> '⅕'.isnumeric() # Vulgar fraction one fifth True >>> '²'.isdecimal(), '²'.isdigit(), '²'.isnumeric() (False, True, True) - See also :meth:`isdecimal` and :meth:`isdigit`. Numeric characters are - a superset of decimal numbers. + See also :meth:`isdecimal` and :meth:`isdigit`. .. method:: str.isprintable() @@ -2376,7 +2391,8 @@ expression support in the :mod:`re` module). Return a copy of the string with leading characters removed. The *chars* argument is a string specifying the set of characters to be removed. If omitted - or ``None``, the *chars* argument defaults to removing whitespace. The *chars* + or ``None``, the *chars* argument defaults to removing whitespace, that is + characters for which :meth:`str.isspace` is true. The *chars* argument is not a prefix; rather, all combinations of its values are stripped:: >>> ' spacious '.lstrip() @@ -2579,7 +2595,8 @@ expression support in the :mod:`re` module). Return a copy of the string with trailing characters removed. The *chars* argument is a string specifying the set of characters to be removed. If omitted - or ``None``, the *chars* argument defaults to removing whitespace. The *chars* + or ``None``, the *chars* argument defaults to removing whitespace, that is + characters for which :meth:`str.isspace` is true. The *chars* argument is not a suffix; rather, all combinations of its values are stripped. For example: @@ -2616,7 +2633,9 @@ expression support in the :mod:`re` module). :func:`re.split`). Splitting an empty string with a specified separator returns ``['']``. - For example:: + For example: + + .. doctest:: >>> '1,2,3'.split(',') ['1', '2', '3'] @@ -2634,7 +2653,9 @@ expression support in the :mod:`re` module). string or a string consisting of just whitespace with a ``None`` separator returns ``[]``. - For example:: + For example: + + .. doctest:: >>> '1 2 3'.split() ['1', '2', '3'] @@ -2646,7 +2667,9 @@ expression support in the :mod:`re` module). If *sep* is not specified or is ``None`` and *maxsplit* is ``0``, only leading runs of consecutive whitespace are considered. - For example:: + For example: + + .. doctest:: >>> "".split(None, 0) [] @@ -2655,7 +2678,7 @@ expression support in the :mod:`re` module). >>> " foo ".split(maxsplit=0) ['foo '] - See also :meth:`join`. + See also :meth:`join` and :meth:`rsplit`. .. index:: @@ -2749,11 +2772,9 @@ expression support in the :mod:`re` module). Return a copy of the string with the leading and trailing characters removed. The *chars* argument is a string specifying the set of characters to be removed. - If omitted or ``None``, the *chars* argument defaults to removing whitespace. - The *chars* argument is not a prefix or suffix; rather, all combinations of its - values are stripped. - - Whitespace characters are defined by :meth:`str.isspace`. + If omitted or ``None``, the *chars* argument defaults to removing whitespace, + that is characters for which :meth:`str.isspace` is true. The *chars* argument + is not a prefix or suffix; rather, all combinations of its values are stripped. For example: @@ -5927,6 +5948,15 @@ creation:: >>> type(l) + +Instances of ``GenericAlias`` are not classes at runtime, even though they behave like classes (they can be instantiated and subclassed):: + + >>> import inspect + >>> inspect.isclass(list[int]) + False + +This is true for :ref:`user-defined generics ` also. + Calling :func:`repr` or :func:`str` on a generic shows the parameterized type:: >>> repr(list[int]) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 9b9783d8e58013f..29a329fdfeab15b 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -670,7 +670,7 @@ be finalized; only the internally used file object will be closed. See the it is best practice to only do so in top-level applications or :mod:`site configuration `. To set a global default this way, a filter function needs to be wrapped in - :func:`staticmethod` to prevent injection of a ``self`` argument. + :deco:`staticmethod` to prevent injection of a ``self`` argument. .. versionchanged:: 3.14 diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 7ae3fabf1cec644..4e21e1ded82724c 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -718,7 +718,7 @@ The :mod:`!test.support` module defines the following functions: .. decorator:: anticipate_failure(condition) A decorator to conditionally mark tests with - :func:`unittest.expectedFailure`. Any use of this decorator should + :deco:`unittest.expectedFailure`. Any use of this decorator should have an associated comment identifying the relevant tracker issue. diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index ef6016d45c1f8bc..c909b8bad6d726c 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -2583,7 +2583,7 @@ types. func(C()) # Passes static type check See :pep:`544` for more details. Protocol classes decorated with - :func:`runtime_checkable` (described later) act as simple-minded runtime + :deco:`runtime_checkable` (described later) act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. Protocol classes without this decorator cannot be used as the second argument to :func:`isinstance` or :func:`issubclass`. @@ -2648,7 +2648,7 @@ types. .. note:: - :func:`!runtime_checkable` will check only the presence of the required + :deco:`!runtime_checkable` will check only the presence of the required methods or attributes, not their type signatures or types. For example, :class:`ssl.SSLObject` is a class, therefore it passes an :func:`issubclass` @@ -3154,7 +3154,7 @@ Functions and decorators Decorator to mark an object as providing :func:`dataclass `-like behavior. - ``dataclass_transform`` may be used to + ``@dataclass_transform`` may be used to decorate a class, metaclass, or a function that is itself a decorator. The presence of ``@dataclass_transform()`` tells a static type checker that the decorated object performs runtime "magic" that @@ -3209,7 +3209,7 @@ Functions and decorators ``kw_only``, and ``slots``. It must be possible for the value of these arguments (``True`` or ``False``) to be statically evaluated. - The arguments to the ``dataclass_transform`` decorator can be used to + The arguments to the ``@dataclass_transform`` decorator can be used to customize the default behaviors of the decorated class, metaclass, or function: @@ -3273,8 +3273,8 @@ Functions and decorators keyword-only. If ``True``, the field will be keyword-only. If ``False``, it will not be keyword-only. If unspecified, the value of the ``kw_only`` parameter on the object decorated with - ``dataclass_transform`` will be used, or if that is unspecified, the - value of ``kw_only_default`` on ``dataclass_transform`` will be used. + ``@dataclass_transform`` will be used, or if that is unspecified, the + value of ``kw_only_default`` on ``@dataclass_transform`` will be used. * - ``alias`` - Provides an alternative name for the field. This alternative name is used in the synthesized ``__init__`` method. diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index 2ff1015af7a86e0..5e28a8ada595ef1 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -2223,7 +2223,7 @@ return something else:: >>> mock == 3 True -The return value of :meth:`MagicMock.__iter__` can be any iterable object and isn't +The return value of :meth:`!__iter__` can be any iterable object and isn't required to be an iterator: >>> mock = MagicMock() @@ -2539,7 +2539,7 @@ Alternatively you can just use ``vars(my_mock)`` (instance members) and mock_open ~~~~~~~~~ -.. function:: mock_open(mock=None, read_data=None) +.. function:: mock_open(mock=None, read_data='') A helper function to create a mock to replace the use of :func:`open`. It works for :func:`open` called directly or used as a context manager. diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index ff619f979233251..7afcdb368a3562e 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -530,7 +530,7 @@ tests. In addition, it supports marking a test as an "expected failure," a test that is broken and will fail, but shouldn't be counted as a failure on a :class:`TestResult`. -Skipping a test is simply a matter of using the :func:`skip` :term:`decorator` +Skipping a test is simply a matter of using the :deco:`skip` :term:`decorator` or one of its conditional variants, calling :meth:`TestCase.skipTest` within a :meth:`~TestCase.setUp` or test method, or raising :exc:`SkipTest` directly. @@ -581,7 +581,7 @@ Classes can be skipped just like methods:: :meth:`TestCase.setUp` can also skip the test. This is useful when a resource that needs to be set up is not available. -Expected failures use the :func:`expectedFailure` decorator. :: +Expected failures use the :deco:`expectedFailure` decorator. :: class ExpectedFailureTestCase(unittest.TestCase): @unittest.expectedFailure @@ -763,7 +763,7 @@ Test cases A class method called before tests in an individual class are run. ``setUpClass`` is called with the class as the only argument - and must be decorated as a :func:`classmethod`:: + and must be decorated as a :deco:`classmethod`:: @classmethod def setUpClass(cls): @@ -778,7 +778,7 @@ Test cases A class method called after tests in an individual class have run. ``tearDownClass`` is called with the class as the only argument - and must be decorated as a :meth:`classmethod`:: + and must be decorated as a :deco:`classmethod`:: @classmethod def tearDownClass(cls): @@ -2156,7 +2156,7 @@ Loading and running tests .. versionchanged:: 3.4 Returns ``False`` if there were any :attr:`unexpectedSuccesses` - from tests marked with the :func:`expectedFailure` decorator. + from tests marked with the :deco:`expectedFailure` decorator. .. method:: stop() @@ -2239,7 +2239,7 @@ Loading and running tests .. method:: addExpectedFailure(test, err) Called when the test case *test* fails or errors, but was marked with - the :func:`expectedFailure` decorator. + the :deco:`expectedFailure` decorator. The default implementation appends a tuple ``(test, formatted_err)`` to the instance's :attr:`expectedFailures` attribute, where *formatted_err* @@ -2249,7 +2249,7 @@ Loading and running tests .. method:: addUnexpectedSuccess(test) Called when the test case *test* was marked with the - :func:`expectedFailure` decorator, but succeeded. + :deco:`expectedFailure` decorator, but succeeded. The default implementation appends the test to the instance's :attr:`unexpectedSuccesses` attribute. diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index b25384dbfce54bb..9063bea96ccb0ac 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -626,9 +626,28 @@ Available Context Managers If the *record* argument is :const:`False` (the default) the context manager returns :class:`None` on entry. If *record* is :const:`True`, a list is returned that is progressively populated with objects as seen by a custom - :func:`showwarning` function (which also suppresses output to ``sys.stdout``). - Each object in the list has attributes with the same names as the arguments to - :func:`showwarning`. + :func:`showwarning` function (which also suppresses output to ``sys.stderr``). + Each object in the list is guaranteed to have the following attributes: + + - ``message``: the warning message (an instance of :exc:`Warning`) + - ``category``: the warning category (a subclass of :exc:`Warning`) + - ``filename``: the file name where the warning occurred (:class:`str`) + - ``lineno``: the line number in the file (:class:`int`) + - ``file``: the file object used for output (if any), or ``None`` + - ``line``: the line of source code (if available), or ``None`` + - ``source``: the original object that generated the warning (if + available), or ``None`` + - ``module``: the module name where the warning occurred + (:class:`str`), or ``None`` + + .. versionchanged:: 3.6 + The ``source`` attribute was added. + + .. versionchanged:: 3.15 + The ``module`` attribute was added. + + The type of these objects is not specified and may change; only the + presence of these attributes is guaranteed. The *module* argument takes a module that will be used instead of the module returned when you import :mod:`!warnings` whose filter will be diff --git a/Doc/library/weakref.rst b/Doc/library/weakref.rst index fcb9e0199fad69e..952609c0e700e5e 100644 --- a/Doc/library/weakref.rst +++ b/Doc/library/weakref.rst @@ -132,6 +132,9 @@ See :ref:`__slots__ documentation ` for details. .. versionchanged:: 3.4 Added the :attr:`__callback__` attribute. + .. versionchanged:: next + Raise :exc:`!TypeError` if *callback* is not callable or ``None``. + .. function:: proxy(object[, callback]) @@ -151,6 +154,9 @@ See :ref:`__slots__ documentation ` for details. Extended the operator support on proxy objects to include the matrix multiplication operators ``@`` and ``@=``. + .. versionchanged:: next + Raise :exc:`!TypeError` if *callback* is not callable or ``None``. + .. function:: getweakrefcount(object) diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 63baefd33e88c50..6710c0acf77e350 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -2010,7 +2010,7 @@ Annotations are conventionally used for :term:`type hints `, but this is not enforced by the language, and in general annotations may contain arbitrary expressions. The presence of annotations does not change the runtime semantics of the code, except if some mechanism is used that introspects and uses the annotations -(such as :mod:`dataclasses` or :func:`functools.singledispatch`). +(such as :mod:`dataclasses` or :deco:`functools.singledispatch`). By default, annotations are lazily evaluated in an :ref:`annotation scope `. This means that they are not evaluated when the code containing the annotation is evaluated. diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index a8614128c85dada..2a961a062780f46 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1042,7 +1042,7 @@ this approach. Raise :exc:`DeprecationWarning` instead of :exc:`ImportWarning` when falling back to :attr:`!__package__` during import resolution. - .. deprecated-removed:: 3.13 3.15 + .. deprecated-removed:: 3.13 3.16 :attr:`!__package__` will cease to be set or taken into consideration by the import system or standard library. @@ -2197,7 +2197,7 @@ Basic customization :data:`!NotImplemented`. There are no other implied relationships among the comparison operators or default implementations; for example, the truth of ``(x`, except that they are enclosed in +parentheses instead of brackets. +For example:: -.. productionlist:: python-grammar - generator_expression: "(" `comprehension` ")" + >>> iterator = (x ** 2 for x in range(10)) + >>> iterator + at ...> + +At runtime, a generator expression evaluates to a :term:`generator iterator` +which yields the same values as the corresponding list comprehension:: + + >>> list(iterator) + [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] + +Thus, the example above is roughly equivalent to defining and calling +the following generator function:: -A generator expression yields a new generator object. Its syntax is the same as -for comprehensions, except that it is enclosed in parentheses instead of -brackets or curly braces. - -Variables used in the generator expression are evaluated lazily when the -:meth:`~generator.__next__` method is called for the generator object (in the same -fashion as normal generators). However, the iterable expression in the -leftmost :keyword:`!for` clause is immediately evaluated, and the -:term:`iterator` is immediately created for that iterable, so that an error -produced while creating the iterator will be emitted at the point where the generator expression -is defined, rather than at the point where the first value is retrieved. -Subsequent :keyword:`!for` clauses and any filter condition in the leftmost -:keyword:`!for` clause cannot be evaluated in the enclosing scope as they may -depend on the values obtained from the leftmost iterable. For example: -``(x*y for x in range(10) for y in range(x, x+10))``. - -The parentheses can be omitted on calls with only one argument. See section -:ref:`calls` for details. + def make_generator_of_squares(iterator): + for x in iterator: + yield x ** 2 + + make_generator_of_squares(iter(range(10))) + +The enclosing parentheses can be omitted in calls when the generator +expression is the only positional argument and there are no keyword +arguments. +See the :ref:`Calls section ` for details. +For example:: + + # The parentheses after `sum` are part of the call syntax: + >>> sum(x ** 2 for x in range(10)) + 285 + + # The generator needs its own parentheses if it's not the only argument: + >>> sum((x ** 2 for x in range(10)), start=1000) + 1285 + +The iterable expression in the leftmost :keyword:`!for` clause is +evaluated immediately, so that an error raised by this expression will be +emitted at the point where the generator expression is defined, +rather than at the point where the first value is retrieved:: + + >>> (x ** 2 for x in nonexistent_iterable) + Traceback (most recent call last): + ... + NameError: name 'nonexistent_iterable' is not defined + +After the expression is evaluated, an iterator is created +from the result, as if :py:func:`iter` was called on it. +Any error raised when creating the iterator is also emitted immediately:: + + >>> (x ** 2 for x in None) + Traceback (most recent call last): + ... + TypeError: 'NoneType' object is not iterable + +All other expressions are evaluated lazily, in the same fashion as normal +generators (that is, when the iterator is asked to yield a value):: + + >>> iterator = (nonexistent_value for x in range(10)) + >>> iterator + at ...> + >>> list(iterator) + Traceback (most recent call last): + ... + NameError: name 'nonexistent_value' is not defined + +:: + + >>> iterator = (x * y for x in range(10) for y in nonexistent_iterable) + >>> iterator + at ...> + >>> list(iterator) + Traceback (most recent call last): + ... + NameError: name 'nonexistent_iterable' is not defined To avoid interfering with the expected operation of the generator expression -itself, ``yield`` and ``yield from`` expressions are prohibited in the -implicitly defined generator. +itself, ``yield`` and ``yield from`` expressions are prohibited inside +the implicitly nested scope. If a generator expression contains either :keyword:`!async for` clauses or :keyword:`await` expressions it is called an -:dfn:`asynchronous generator expression`. An asynchronous generator -expression returns a new asynchronous generator object, -which is an asynchronous iterator (see :ref:`async-iterators`). +:dfn:`asynchronous generator expression`. +An asynchronous generator expression returns a new asynchronous generator +object, which is an asynchronous iterator (see :ref:`async-iterators`). + +The formal grammar for generator expressions is: + +.. grammar-snippet:: + :group: python-grammar + + generator_expression: "(" `comprehension` ")" .. versionadded:: 3.6 Asynchronous generator expressions were introduced. @@ -2344,7 +2405,7 @@ some consistency rules, if possible: The last two expressions apply to totally ordered collections (e.g. to sequences, but not to sets or mappings). See also the - :func:`~functools.total_ordering` decorator. + :deco:`~functools.total_ordering` decorator. * The :func:`hash` result should be consistent with equality. Objects that are equal should either have the same hash value, diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 0f134604b5d922b..a964b43ebee1746 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -181,7 +181,7 @@ Assignment of an object to a single target is recursively defined as follows. inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3 This description does not necessarily apply to descriptor attributes, such as - properties created with :func:`property`. + properties created with :deco:`property`. .. index:: pair: subscription; assignment diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index 189173a5f8a75f4..aa08f7acb99197a 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -5,7 +5,6 @@ Doc/c-api/init_config.rst Doc/c-api/intro.rst Doc/c-api/stable.rst -Doc/c-api/typeobj.rst Doc/library/ast.rst Doc/library/asyncio-extending.rst Doc/library/email.charset.rst @@ -30,7 +29,6 @@ Doc/library/test.rst Doc/library/tkinter.rst Doc/library/tkinter.scrolledtext.rst Doc/library/tkinter.ttk.rst -Doc/library/unittest.mock.rst Doc/library/urllib.parse.rst Doc/library/urllib.request.rst Doc/library/wsgiref.rst diff --git a/Doc/tools/extensions/c_annotations.py b/Doc/tools/extensions/c_annotations.py index 1409c77aed9c6bc..0e762042979c2b7 100644 --- a/Doc/tools/extensions/c_annotations.py +++ b/Doc/tools/extensions/c_annotations.py @@ -394,7 +394,7 @@ def run(self) -> list[nodes.Node]: current_minor = int(self.config.version.removeprefix('3.')) for minor in range(current_minor - 5, current_minor + 1): value = (3 << 24) | (minor << 16) - content.append(f' {value:#x} /* Py_PACK_VERSION(3.{minor}) */') + content.append(f' {value:#x} /* Py_PACK_VERSION(3,{minor}) */') node = nodes.paragraph() self.state.nested_parse(StringList(content), 0, node) return [node] diff --git a/Doc/tools/extensions/profiling_trace.py b/Doc/tools/extensions/profiling_trace.py index 7185ef351ddc7f2..183c6de48714a43 100644 --- a/Doc/tools/extensions/profiling_trace.py +++ b/Doc/tools/extensions/profiling_trace.py @@ -154,10 +154,15 @@ def inject_trace(app, exception): ) +def add_assets(app, pagename, templatename, context, doctree): + if pagename == 'library/profiling.sampling': + app.add_js_file('profiling-sampling-visualization.js') + app.add_css_file('profiling-sampling-visualization.css') + + def setup(app): app.connect('build-finished', inject_trace) - app.add_js_file('profiling-sampling-visualization.js') - app.add_css_file('profiling-sampling-visualization.css') + app.connect('html-page-context', add_assets) return { 'version': '1.0', diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index f9bf273e7624a04..9b335f2976a2fa3 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -10,19 +10,10 @@ """ import re -import io -from os import getenv, path -from docutils import nodes -from docutils.parsers.rst import directives -from docutils.utils import unescape from sphinx import addnodes -from sphinx.domains.python import PyFunction, PyMethod, PyModule -from sphinx.locale import _ as sphinx_gettext -from sphinx.util.docutils import SphinxDirective +from sphinx.domains.python import PyFunction, PyMethod -# Used in conf.py and updated here by python/release-tools/run_release.py -SOURCE_URI = 'https://github.com/python/cpython/tree/main/%s' class PyAwaitableMixin(object): def handle_signature(self, sig, signode): diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt index be00d48bf042f63..81c0f098e4c8a83 100644 --- a/Doc/tools/removed-ids.txt +++ b/Doc/tools/removed-ids.txt @@ -4,7 +4,10 @@ c-api/allocation.html: deprecated-aliases c-api/file.html: deprecated-api +# Removed sections library/asyncio-task.html: terminating-a-task-group +deprecations/index.html: pending-removal-in-python-3-15 +deprecations/index.html: c-api-pending-removal-in-python-3-15 # Removed libmpdec using/configure.html: cmdoption-with-system-libmpdec @@ -26,3 +29,7 @@ reference/expressions.html: grammar-token-python-grammar-enclosure reference/expressions.html: grammar-token-python-grammar-list_display reference/expressions.html: grammar-token-python-grammar-parenth_form reference/expressions.html: grammar-token-python-grammar-set_display + +# Moved to a different page +c-api/typeobj.html: c.Py_tp_base +c-api/typeobj.html: c.Py_tp_bases diff --git a/Doc/tutorial/venv.rst b/Doc/tutorial/venv.rst index f362e1943b666f7..6b6b8a768e3f58d 100644 --- a/Doc/tutorial/venv.rst +++ b/Doc/tutorial/venv.rst @@ -88,6 +88,11 @@ For example: '~/envs/tutorial-env/lib/python3.5/site-packages'] >>> +Note that the activated virtual environment does not alter the ``PYTHONPATH`` variable in any way. +This may lead to unexpected results if the path includes references to code which is incompatible with +the Python version the virtual environment is using. The best practice is to ``unset PYTHONPATH`` +in bash or the equivalent for the shell you are using. + To deactivate a virtual environment, type:: deactivate diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index eea1e2f64a468d0..5b715d4614dad8f 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -455,6 +455,12 @@ customization. Python runtimes, or false to prevent it. By default, true. + * - ``shebang_templates`` + - (none) + - Mapping from shebang line template to alternative command, such as + ``py -V:`` or a substitute string. + See :ref:`pymanager-shebang` for more details. + * - ``log_level`` - ``PYMANAGER_VERBOSE``, ``PYMANAGER_DEBUG`` - Set the default level of output (0-50). @@ -568,6 +574,30 @@ which the path to the script and any additional arguments will be appended. This functionality may be disabled by the ``shebang_can_run_anything`` configuration option. +Since version 26.3 of the Python install manager, custom shebang templates may +be added to your configuration file. Add the ``shebang_templates`` object with +one member for each template (the string to match) and the command to use when +the template is matched. Most commands should be ``py -V:`` (or ``pyw``) to +launch one of your installed runtimes. The ``py -3.`` form is also +allowed, as is a plain ``py`` to launch the default. No other arguments are +supported. + +.. code:: json5 + + { + "shebang_templates": { + "/usr/bin/python": "py", + "/usr/bin/my_custom_python": "py -V:MyCustomPython/3" + } + } + +If the substitute command is not ``py`` or ``pyw``, it will be written back into +the shebang and regular handling continues. If launching arbitrary executables +is permitted, then providing a full path will allow you to redirect from Python +to any executable. The template should match either the entire line (ignoring +leading and trailing whitespace), or up to the first space in the shebang line. + + .. note:: The behaviour of shebangs in the Python install manager is subtly different diff --git a/Doc/whatsnew/2.5.rst b/Doc/whatsnew/2.5.rst index 03e612fb651e71b..4b92ba82c991e44 100644 --- a/Doc/whatsnew/2.5.rst +++ b/Doc/whatsnew/2.5.rst @@ -745,7 +745,7 @@ The contextlib module The new :mod:`contextlib` module provides some functions and a decorator that are useful for writing objects for use with the ':keyword:`with`' statement. -The decorator is called :func:`contextmanager`, and lets you write a single +The decorator is called :deco:`~contextlib.contextmanager`, and lets you write a single generator function instead of defining a new class. The generator should yield exactly one value. The code up to the :keyword:`yield` will be executed as the :meth:`~object.__enter__` method, and the value yielded will be the method's return diff --git a/Doc/whatsnew/2.6.rst b/Doc/whatsnew/2.6.rst index 1215601a09d681c..e1f72b6c4a6c92c 100644 --- a/Doc/whatsnew/2.6.rst +++ b/Doc/whatsnew/2.6.rst @@ -431,7 +431,7 @@ The contextlib module The :mod:`contextlib` module provides some functions and a decorator that are useful when writing objects for use with the ':keyword:`with`' statement. -The decorator is called :func:`~contextlib.contextmanager`, and lets you write +The decorator is called :deco:`~contextlib.contextmanager`, and lets you write a single generator function instead of defining a new class. The generator should yield exactly one value. The code up to the :keyword:`yield` will be executed as the :meth:`~object.__enter__` method, and the value yielded will @@ -1557,8 +1557,9 @@ Some smaller changes made to the core Python language are: .. Revision 57619 -* Properties now have three attributes, :attr:`getter`, :attr:`setter` - and :attr:`deleter`, that are decorators providing useful shortcuts +* Properties now have three decorators, :deco:`~property.getter`, + :deco:`~property.setter` and :deco:`~property.deleter`, that are + decorators providing useful shortcuts for adding a getter, setter or deleter function to an existing property. You would use them like this:: diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 7296296d144803d..de90c37a38d38ff 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -1267,7 +1267,7 @@ changes, or look through the Subversion logs for all the details. uploads thanks to an added *rest* parameter (patch by Pablo Mouzo; :issue:`6845`.) -* New class decorator: :func:`~functools.total_ordering` in the :mod:`functools` +* New class decorator: :deco:`~functools.total_ordering` in the :mod:`functools` module takes a class that defines an :meth:`~object.__eq__` method and one of :meth:`~object.__lt__`, :meth:`~object.__le__`, :meth:`~object.__gt__`, or :meth:`~object.__ge__`, and generates the missing comparison methods. Since the diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index f687b6c85591fc8..390b82d5a1fdc1b 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -996,7 +996,7 @@ dataclasses __slots__ ~~~~~~~~~ -Added ``slots`` parameter in :func:`dataclasses.dataclass` decorator. +Added ``slots`` parameter in :deco:`dataclasses.dataclass` decorator. (Contributed by Yurii Karabas in :issue:`42269`) Keyword-only fields @@ -1485,9 +1485,9 @@ is a :class:`typing.TypedDict`. Subclasses of ``typing.Protocol`` which only have data variables declared will now raise a ``TypeError`` when checked with ``isinstance`` unless they -are decorated with :func:`~typing.runtime_checkable`. Previously, these checks +are decorated with :deco:`~typing.runtime_checkable`. Previously, these checks passed silently. Users should decorate their -subclasses with the :func:`!runtime_checkable` decorator +subclasses with the :deco:`!runtime_checkable` decorator if they want runtime protocols. (Contributed by Yurii Karabas in :issue:`38908`.) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index a095d887352127a..7b3475882063635 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -388,7 +388,7 @@ Kumar Srinivasan and Graham Bleaney.) PEP 681: Data class transforms ------------------------------ -:data:`~typing.dataclass_transform` may be used to +:deco:`~typing.dataclass_transform` may be used to decorate a class, metaclass, or a function that is itself a decorator. The presence of ``@dataclass_transform()`` tells a static type checker that the decorated object performs runtime "magic" that transforms a class, @@ -686,8 +686,8 @@ enum * Added the :func:`~enum.member` and :func:`~enum.nonmember` decorators, to ensure the decorated object is/is not converted to an enum member. -* Added the :func:`~enum.property` decorator, - which works like :func:`property` except for enums. +* Added the :deco:`~enum.property` decorator, + which works like :deco:`property` except for enums. Use this instead of :func:`types.DynamicClassAttribute`. * Added the :func:`~enum.global_enum` enum decorator, @@ -740,7 +740,7 @@ fractions functools --------- -* :func:`functools.singledispatch` now supports :class:`types.UnionType` +* :deco:`functools.singledispatch` now supports :class:`types.UnionType` and :class:`typing.Union` as annotations to the dispatch argument.:: >>> from functools import singledispatch @@ -1164,7 +1164,7 @@ For major changes, see :ref:`new-feat-related-type-hints-311`. type checker errors related to highly dynamic class, such as mocks. (Contributed by Shantanu Jain in :gh:`91154`.) -* The :func:`typing.final` decorator now sets the ``__final__`` attributed on +* The :deco:`typing.final` decorator now sets the ``__final__`` attributed on the decorated object. (Contributed by Jelle Zijlstra in :gh:`90500`.) @@ -1197,7 +1197,7 @@ For major changes, see :ref:`new-feat-related-type-hints-311`. :data:`~typing.ClassVar` annotations. (Contributed by Gregory Beauregard in :gh:`90711`.) -* :func:`typing.no_type_check` no longer modifies external classes and functions. +* :deco:`typing.no_type_check` no longer modifies external classes and functions. It also now correctly marks classmethods as not to be type checked. (Contributed by Nikita Sobolev in :gh:`90729`.) diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 0378ada72804c9e..9e48b3ab7393c87 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -146,7 +146,7 @@ New typing features: * :ref:`PEP 692 `, using :class:`~typing.TypedDict` to annotate :term:`**kwargs ` -* :ref:`PEP 698 `, :func:`typing.override` decorator +* :ref:`PEP 698 `, :deco:`typing.override` decorator Important deprecations, removals or restrictions: @@ -511,7 +511,7 @@ See :pep:`692` for more details. PEP 698: Override Decorator for Static Typing --------------------------------------------- -A new decorator :func:`typing.override` has been added to the :mod:`typing` +A new decorator :deco:`typing.override` has been added to the :mod:`typing` module. It indicates to type checkers that the method is intended to override a method in a superclass. This allows type checkers to catch mistakes where a method that is intended to override something in a base class @@ -1021,7 +1021,7 @@ typing ``__orig_bases__`` attribute. (Contributed by Adrian Garcia Badaracco in :gh:`103699`.) -* Add ``frozen_default`` parameter to :func:`typing.dataclass_transform`. +* Add ``frozen_default`` parameter to :deco:`typing.dataclass_transform`. (Contributed by Erik De Bonte in :gh:`99957`.) unicodedata @@ -1749,7 +1749,7 @@ Changes in the Python API around process-global resources, which are best managed from the main interpreter. (Contributed by Donghee Na in :gh:`99127`.) -* The undocumented locking behavior of :func:`~functools.cached_property` +* The undocumented locking behavior of :deco:`~functools.cached_property` is removed, because it locked across all instances of the class, leading to high lock contention. This means that a cached property getter function could now run more than once for a single instance, if two threads race. For most simple diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 0db8ec55e5c9f8e..d8845fe921ededa 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1994,7 +1994,7 @@ New Deprecations use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``. (Contributed by Alex Waygood in :gh:`105566` and :gh:`105570`.) - * Deprecate the :func:`!typing.no_type_check_decorator` decorator function, + * Deprecate the :deco:`!typing.no_type_check_decorator` decorator function, to be removed in Python 3.15. After eight years in the :mod:`typing` module, it has yet to be supported by any major type checker. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 0f76c66144d6899..db6903da9f63444 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -513,10 +513,6 @@ specifically: purpose in :pep:`793`, with a new :c:type:`PySlot` structure introduced in :pep:`820`. -The reference documentation for these features is complete, but currently -aimed at early adopters. -A migration guide is planned for an upcoming beta release. - Note that Stable ABI does not offer all the functionality that CPython has to offer. Extensions that cannot switch to ``abi3t`` should continue to build for @@ -532,6 +528,9 @@ If not using a build tool -- or when writing such a tool -- you can select ``abi3t`` by setting the macro :c:macro:`!Py_TARGET_ABI3T` as discussed in :ref:`abi3-compiling`. +A practical :ref:`migration guide ` for switching to +``abi3t`` is available. + .. seealso:: :pep:`803` for further details. @@ -2152,7 +2151,7 @@ typing or ``TD = TypedDict("TD", {})`` instead. (Contributed by Bénédikt Tran in :gh:`133823`.) -* Deprecated :func:`!typing.no_type_check_decorator` has been removed. +* Deprecated :deco:`!typing.no_type_check_decorator` has been removed. (Contributed by Nikita Sobolev in :gh:`133601`.) @@ -2477,6 +2476,12 @@ New features * :c:func:`PyModule_FromDefAndSpec2` * :c:func:`PyModule_ExecDef` + + The slots :c:macro:`Py_tp_bases` and :c:macro:`Py_tp_base` are now + equivalent: they can be set either to a single type or a tuple of types. + The :c:macro:`Py_tp_bases` slot is preferred; the other is ignored if both + are specified. + (Contributed by Petr Viktorin in :gh:`149044`.) * Add :c:func:`PyUnstable_ThreadState_SetStackProtection` and diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 0aff48dba61449c..8e4c4a1e9b1de02 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -102,6 +102,28 @@ lzma requires ``lzma`` 5.4.0 or newer while RISC-V requires 5.6.0 or newer. (Contributed by Chien Wong in :gh:`115988`.) +logging +------- + +* :class:`~logging.handlers.TimedRotatingFileHandler` now uses the creation + time instead of the last modification time of an existing log file as + the basis for the first rotation after handler creation, if supported by + the OS and file system. + This allows it to be used in short-running programs that start and end + before the rotation interval expires. + (Contributed by Iván Márton and Serhiy Storchaka in :gh:`84649`.) + +math +---- + +* Added trigonometric functions that work in units of half turns, rather than + radians. The new functions :func:`math.acospi`, :func:`math.asinpi`, + :func:`math.atanpi`, and :func:`math.atan2pi` return half-turn angles. The + new functions :func:`math.cospi`, :func:`math.sinpi`, and :func:`math.tanpi` + take half-turn angle arguments. These functions are recommended by IEEE + 754-2019 and standardized in C23. + (Contributed by Jeff Epler in :gh:`150534`.) + os -- @@ -109,6 +131,13 @@ os process via a pidfd. Available on Linux 5.6+. (Contributed by Maurycy Pawłowski-Wieroński in :gh:`149464`.) +shlex +----- + +* Add keyword-only parameter *force* to :func:`shlex.quote` to force quoting + a string, even if it is already safe for a shell without being quoted. + (Contributed by Jay Berry in :gh:`148846`.) + xml --- @@ -246,10 +275,14 @@ Deprecated .. include:: ../deprecations/pending-removal-in-3.17.rst +.. include:: ../deprecations/pending-removal-in-3.18.rst + .. include:: ../deprecations/pending-removal-in-3.19.rst .. include:: ../deprecations/pending-removal-in-3.20.rst +.. include:: ../deprecations/pending-removal-in-3.21.rst + .. include:: ../deprecations/pending-removal-in-future.rst @@ -297,9 +330,19 @@ Porting to Python 3.16 Deprecated C APIs ----------------- -* TODO +* :c:func:`PyGen_New`, :c:func:`PyGen_NewWithQualName`, :c:func:`PyCoro_New`, + and :c:func:`PyAsyncGen_New` are deprecated. + They are scheduled for removal in 3.18. .. Add C API deprecations above alphabetically, not here at the end. +.. include:: ../deprecations/c-api-pending-removal-in-3.18.rst + +.. include:: ../deprecations/c-api-pending-removal-in-3.19.rst + +.. include:: ../deprecations/c-api-pending-removal-in-3.20.rst + +.. include:: ../deprecations/c-api-pending-removal-in-future.rst + Removed C APIs -------------- diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index 48c461d891e8614..c61eb659ccc0f62 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -756,7 +756,7 @@ functools --------- * The :mod:`functools` module includes a new decorator for caching function - calls. :func:`functools.lru_cache` can save repeated queries to an external + calls. :deco:`functools.lru_cache` can save repeated queries to an external resource whenever the results are expected to be the same. For example, adding a caching decorator to a database query function can save @@ -789,7 +789,7 @@ functools `_\, :issue:`10586`, and :issue:`10593`.) -* The :func:`functools.wraps` decorator now adds a :attr:`__wrapped__` attribute +* The :deco:`functools.wraps` decorator now adds a :attr:`__wrapped__` attribute pointing to the original callable function. This allows wrapped functions to be introspected. It also copies :attr:`~function.__annotations__` if defined. And now it also gracefully skips over missing attributes such as @@ -805,11 +805,11 @@ functools :issue:`8814`.) * To help write classes with rich comparison methods, a new decorator - :func:`functools.total_ordering` will use existing equality and inequality + :deco:`functools.total_ordering` will use existing equality and inequality methods to fill in the remaining methods. For example, supplying *__eq__* and *__lt__* will enable - :func:`~functools.total_ordering` to fill-in *__le__*, *__gt__* and *__ge__*:: + :deco:`~functools.total_ordering` to fill-in *__le__*, *__gt__* and *__ge__*:: @total_ordering class Student: @@ -1097,11 +1097,11 @@ logarithm of the gamma function: abc --- -The :mod:`abc` module now supports :func:`~abc.abstractclassmethod` and -:func:`~abc.abstractstaticmethod`. +The :mod:`abc` module now supports :deco:`~abc.abstractclassmethod` and +:deco:`~abc.abstractstaticmethod`. These tools make it possible to define an :term:`abstract base class` that -requires a particular :func:`classmethod` or :func:`staticmethod` to be +requires a particular :deco:`classmethod` or :deco:`staticmethod` to be implemented:: class Temperature(metaclass=abc.ABCMeta): @@ -1155,7 +1155,7 @@ self-reference by displaying "..." in the recursive part of the representation string. To help write such :meth:`~object.__repr__` methods, the :mod:`reprlib` module has a new -decorator, :func:`~reprlib.recursive_repr`, for detecting recursive calls to +decorator, :deco:`~reprlib.recursive_repr`, for detecting recursive calls to :meth:`!__repr__` and substituting a placeholder string instead:: >>> class MyList(list): @@ -1241,7 +1241,7 @@ There is a new and slightly mind-blowing tool :term:`context manager` that does double duty as a function decorator. As a convenience, this new functionality is used by -:func:`~contextlib.contextmanager` so that no extra effort is needed to support +:deco:`~contextlib.contextmanager` so that no extra effort is needed to support both roles. The basic idea is that both context managers and function decorators can be used @@ -1253,7 +1253,7 @@ write a pre-action or post-action wrapper that can be used in either role. For example, it is sometimes useful to wrap functions or groups of statements with a logger that can track the time of entry and time of exit. Rather than writing both a function decorator and a context manager for the task, the -:func:`~contextlib.contextmanager` provides both capabilities in a single +:deco:`~contextlib.contextmanager` provides both capabilities in a single definition:: from contextlib import contextmanager diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index 1bb79bce2c3e972..02fd264e53e1b06 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -919,12 +919,12 @@ abstract methods. The recommended approach to declaring abstract descriptors is now to provide :attr:`!__isabstractmethod__` as a dynamically updated property. The built-in descriptors have been updated accordingly. -* :class:`abc.abstractproperty` has been deprecated, use :class:`property` - with :func:`abc.abstractmethod` instead. -* :class:`abc.abstractclassmethod` has been deprecated, use - :class:`classmethod` with :func:`abc.abstractmethod` instead. -* :class:`abc.abstractstaticmethod` has been deprecated, use - :class:`staticmethod` with :func:`abc.abstractmethod` instead. +* :deco:`abc.abstractproperty` has been deprecated, use :deco:`property` + with :deco:`abc.abstractmethod` instead. +* :deco:`abc.abstractclassmethod` has been deprecated, use + :deco:`classmethod` with :deco:`abc.abstractmethod` instead. +* :deco:`abc.abstractstaticmethod` has been deprecated, use + :deco:`staticmethod` with :deco:`abc.abstractmethod` instead. (Contributed by Darren Dale in :issue:`11610`.) @@ -1390,7 +1390,7 @@ ftplib functools --------- -The :func:`functools.lru_cache` decorator now accepts a ``typed`` keyword +The :deco:`functools.lru_cache` decorator now accepts a ``typed`` keyword argument (that defaults to ``False`` to ensure that it caches values of different types that compare equal in separate cache slots. (Contributed by Raymond Hettinger in :issue:`13227`.) @@ -2244,12 +2244,12 @@ Deprecated Python modules, functions and methods * The :func:`!os.stat_float_times` function is deprecated. * :mod:`abc` module: - * :class:`abc.abstractproperty` has been deprecated, use :class:`property` - with :func:`abc.abstractmethod` instead. - * :class:`abc.abstractclassmethod` has been deprecated, use - :class:`classmethod` with :func:`abc.abstractmethod` instead. - * :class:`abc.abstractstaticmethod` has been deprecated, use - :class:`staticmethod` with :func:`abc.abstractmethod` instead. + * :deco:`abc.abstractproperty` has been deprecated, use :deco:`property` + with :deco:`abc.abstractmethod` instead. + * :deco:`abc.abstractclassmethod` has been deprecated, use + :deco:`classmethod` with :deco:`abc.abstractmethod` instead. + * :deco:`abc.abstractstaticmethod` has been deprecated, use + :deco:`staticmethod` with :deco:`abc.abstractmethod` instead. * :mod:`importlib` package: diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst index a390211ddb50215..0067491c569cc05 100644 --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -858,7 +858,7 @@ to behave like normal instance methods when included in a class definition. .. _whatsnew-singledispatch: -The new :func:`~functools.singledispatch` decorator brings support for +The new :deco:`~functools.singledispatch` decorator brings support for single-dispatch generic functions to the Python standard library. Where object oriented programming focuses on grouping multiple operations on a common set of data into a class, a generic function focuses on grouping @@ -870,7 +870,7 @@ multiple implementations of an operation that allows it to work with :pep:`443` -- Single-dispatch generic functions PEP written and implemented by Łukasz Langa. -:func:`~functools.total_ordering` now supports a return value of +:deco:`~functools.total_ordering` now supports a return value of :data:`NotImplemented` from the underlying comparison function. (Contributed by Katie Miller in :issue:`10042`.) @@ -1029,7 +1029,7 @@ information for modules, classes and functions. (Contributed by Claudiu Popa and Nick Coghlan in :issue:`18626`.) :func:`~inspect.unwrap` makes it easy to unravel wrapper function chains -created by :func:`functools.wraps` (and any other API that sets the +created by :deco:`functools.wraps` (and any other API that sets the ``__wrapped__`` attribute on a wrapper function). (Contributed by Daniel Urban, Aaron Iles and Nick Coghlan in :issue:`13266`.) @@ -2317,7 +2317,7 @@ Changes in the Python API wish to continue to ignore syntax or decoding issues, catch all three exceptions now. -* :func:`functools.update_wrapper` and :func:`functools.wraps` now correctly +* :func:`functools.update_wrapper` and :deco:`functools.wraps` now correctly set the ``__wrapped__`` attribute to the function being wrapped, even if that function also had its ``__wrapped__`` attribute set. This means ``__wrapped__`` attributes now correctly link a stack of decorated diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index 6009dd8a71eea52..24a2ffbefd0cfba 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -121,7 +121,7 @@ Significant improvements in the standard library: :ref:`better and significantly faster way ` of directory traversal. -* :func:`functools.lru_cache` has been mostly +* :deco:`functools.lru_cache` has been mostly :ref:`reimplemented in C `, yielding much better performance. @@ -1148,7 +1148,7 @@ functools .. _whatsnew-lrucache: -Most of the :func:`~functools.lru_cache` machinery is now implemented in C, making +Most of the :deco:`~functools.lru_cache` machinery is now implemented in C, making it significantly faster. (Contributed by Matt Joiner, Alexey Kachayev, and Serhiy Storchaka in :issue:`14373`.) @@ -2158,7 +2158,7 @@ improvement in some benchmarks. Objects from the :mod:`random` module now use 50% less memory on 64-bit builds. (Contributed by Serhiy Storchaka in :issue:`23488`.) -The :func:`property` getter calls are up to 25% faster. +The :deco:`property` getter calls are up to 25% faster. (Contributed by Joe Jevnik in :issue:`23910`.) Instantiation of :class:`fractions.Fraction` is now up to 30% faster. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 5dd47cdac96a5c0..3af3e6ec9cac08f 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -571,7 +571,7 @@ decimal operations to work with the correct context in asynchronous code. dataclasses ----------- -The new :func:`~dataclasses.dataclass` decorator provides a way to declare +The new :deco:`~dataclasses.dataclass` decorator provides a way to declare *data classes*. A data class describes its attributes using class variable annotations. Its constructor and other magic methods, such as :meth:`~object.__repr__`, :meth:`~object.__eq__`, and @@ -830,7 +830,7 @@ The new :func:`~contextlib.nullcontext` is a simpler and faster no-op context manager than :class:`~contextlib.ExitStack`. (Contributed by Jesse-Bakker in :issue:`10049`.) -The new :func:`~contextlib.asynccontextmanager`, +The new :deco:`~contextlib.asynccontextmanager`, :class:`~contextlib.AbstractAsyncContextManager`, and :class:`~contextlib.AsyncExitStack` have been added to complement their synchronous counterparts. (Contributed @@ -921,7 +921,7 @@ return :const:`False` instead and are deprecated. functools --------- -:func:`functools.singledispatch` now supports registering implementations +:deco:`functools.singledispatch` now supports registering implementations using type annotations. (Contributed by Łukasz Langa in :issue:`32227`.) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 5078fc30ac111e4..42d98ff94ec0d1b 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -764,7 +764,7 @@ these are the inverse of each class's ``isocalendar`` method. functools --------- -:func:`functools.lru_cache` can now be used as a straight decorator rather +:deco:`functools.lru_cache` can now be used as a straight decorator rather than as a function returning a decorator. So both of these are now supported:: @lru_cache @@ -777,7 +777,7 @@ than as a function returning a decorator. So both of these are now supported:: (Contributed by Raymond Hettinger in :issue:`36772`.) -Added a new :func:`functools.cached_property` decorator, for computed properties +Added a new :deco:`functools.cached_property` decorator, for computed properties cached for the life of the instance. :: import functools @@ -893,7 +893,7 @@ inspect The :func:`inspect.getdoc` function can now find docstrings for ``__slots__`` if that attribute is a :class:`dict` where the values are docstrings. This provides documentation options similar to what we already have -for :func:`property`, :func:`classmethod`, and :func:`staticmethod`:: +for :deco:`property`, :deco:`classmethod`, and :deco:`staticmethod`:: class AudioClip: __slots__ = {'bit_rate': 'expressed in kilohertz to one decimal place', @@ -1333,14 +1333,14 @@ The :mod:`typing` module incorporates several new features: ... * "Final" variables, functions, methods and classes. See :pep:`591`, - :class:`typing.Final` and :func:`typing.final`. + :class:`typing.Final` and :deco:`typing.final`. The final qualifier instructs a static type checker to restrict subclassing, overriding, or reassignment:: pi: Final[float] = 3.1415926536 * Protocol definitions. See :pep:`544`, :class:`typing.Protocol` and - :func:`typing.runtime_checkable`. Simple ABCs like + :deco:`typing.runtime_checkable`. Simple ABCs like :class:`typing.SupportsInt` are now ``Protocol`` subclasses. * New protocol class :class:`typing.SupportsIndex`. diff --git a/Include/cpython/genobject.h b/Include/cpython/genobject.h index f75884e597e2c24..e14facd77edec53 100644 --- a/Include/cpython/genobject.h +++ b/Include/cpython/genobject.h @@ -16,8 +16,8 @@ PyAPI_DATA(PyTypeObject) PyGen_Type; #define PyGen_Check(op) PyObject_TypeCheck((op), &PyGen_Type) #define PyGen_CheckExact(op) Py_IS_TYPE((op), &PyGen_Type) -PyAPI_FUNC(PyObject *) PyGen_New(PyFrameObject *); -PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(PyFrameObject *, +Py_DEPRECATED(3.16) PyAPI_FUNC(PyObject *) PyGen_New(PyFrameObject *); +Py_DEPRECATED(3.16) PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(PyFrameObject *, PyObject *name, PyObject *qualname); PyAPI_FUNC(PyCodeObject *) PyGen_GetCode(PyGenObject *gen); @@ -29,7 +29,7 @@ typedef struct _PyCoroObject PyCoroObject; PyAPI_DATA(PyTypeObject) PyCoro_Type; #define PyCoro_CheckExact(op) Py_IS_TYPE((op), &PyCoro_Type) -PyAPI_FUNC(PyObject *) PyCoro_New(PyFrameObject *, +Py_DEPRECATED(3.16) PyAPI_FUNC(PyObject *) PyCoro_New(PyFrameObject *, PyObject *name, PyObject *qualname); @@ -40,7 +40,7 @@ typedef struct _PyAsyncGenObject PyAsyncGenObject; PyAPI_DATA(PyTypeObject) PyAsyncGen_Type; PyAPI_DATA(PyTypeObject) _PyAsyncGenASend_Type; -PyAPI_FUNC(PyObject *) PyAsyncGen_New(PyFrameObject *, +Py_DEPRECATED(3.16) PyAPI_FUNC(PyObject *) PyAsyncGen_New(PyFrameObject *, PyObject *name, PyObject *qualname); #define PyAsyncGen_CheckExact(op) Py_IS_TYPE((op), &PyAsyncGen_Type) diff --git a/Include/dynamic_annotations.h b/Include/dynamic_annotations.h index 4d4def9bf8983e2..5290319dd762c55 100644 --- a/Include/dynamic_annotations.h +++ b/Include/dynamic_annotations.h @@ -461,6 +461,7 @@ int RunningOnValgrind(void); #if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus) +extern "C++" { /* _Py_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads. Instead of doing @@ -476,6 +477,8 @@ int RunningOnValgrind(void); _Py_ANNOTATE_IGNORE_READS_END(); return res; } +} + /* Apply _Py_ANNOTATE_BENIGN_RACE_SIZED to a static variable. */ #define _Py_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \ namespace { \ diff --git a/Include/internal/pycore_critical_section.h b/Include/internal/pycore_critical_section.h index 2a2846b1296b901..51d99d74ca159f6 100644 --- a/Include/internal/pycore_critical_section.h +++ b/Include/internal/pycore_critical_section.h @@ -196,10 +196,9 @@ _PyCriticalSection2_Begin(PyThreadState *tstate, PyCriticalSection2 *c, PyObject static inline void _PyCriticalSection2_End(PyThreadState *tstate, PyCriticalSection2 *c) { - // if mutex1 is NULL, we used the fast path in - // _PyCriticalSection_BeginSlow for mutexes that are already held, - // which should only happen when mutex1 and mutex2 were the same mutex, - // and mutex2 should also be NULL. + // if mutex1 is NULL, we used the fast path in either + // _PyCriticalSection_BeginSlow or _PyCriticalSection2_BeginSlow for mutexes + // that are already held, and mutex2 should also be NULL. if (c->_cs_base._cs_mutex == NULL) { assert(c->_cs_mutex2 == NULL); return; diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index ff6588b3e9718c6..9e11c0bb546b685 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -90,6 +90,8 @@ typedef struct { } PyDictUnicodeEntry; extern PyDictKeysObject *_PyDict_NewKeysForClass(PyHeapTypeObject *); +extern void _PyDict_RemoveKeysForClass(PyHeapTypeObject *); +extern void _PyDict_SplitKeysInvalidated(PyDictKeysObject* keys); extern PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); /* Implementations of the `|` and `|=` operators for dict, used by the @@ -239,6 +241,17 @@ struct _dictkeysobject { see the DK_ENTRIES() / DK_UNICODE_ENTRIES() functions below */ }; +struct _instancekeysobject { + PyTypeObject* dsk_owning_type; + struct _dictkeysobject dsk_keys; +}; + +static inline struct _instancekeysobject *_PyDictKeys_AsSharedKeys(struct _dictkeysobject *keys) +{ + assert(keys->dk_kind == DICT_KEYS_SPLIT); + return _Py_CONTAINER_OF(keys, struct _instancekeysobject, dsk_keys); +} + /* This must be no more than 250, for the prefix size to fit in one byte. */ #define SHARED_KEYS_MAX_SIZE 30 #define NEXT_LOG2_SHARED_KEYS_MAX_SIZE 6 diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 99a1ffb8ad5229b..1cf766ddb382dd2 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -2153,6 +2153,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(updates)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uri)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(usedforsecurity)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(utcoffset)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(value)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(values)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(version)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index d5818402a508cb9..017d62e002fdff9 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -876,6 +876,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(updates) STRUCT_FOR_ID(uri) STRUCT_FOR_ID(usedforsecurity) + STRUCT_FOR_ID(utcoffset) STRUCT_FOR_ID(value) STRUCT_FOR_ID(values) STRUCT_FOR_ID(version) diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 956fa290f0ad0e7..5500c70a3b0aad9 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -308,8 +308,6 @@ struct _import_runtime_state { Modules are added there and looked up in _imp.find_extension(). */ struct _Py_hashtable_t *hashtable; } extensions; - /* Package context -- the full module name for package imports */ - const char * pkgcontext; }; struct _import_state { diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index c2c508c1a71c5c0..98880cd83780dca 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -266,12 +266,6 @@ _Py_REF_IS_MERGED(Py_ssize_t ob_ref_shared) return (ob_ref_shared & _Py_REF_SHARED_FLAG_MASK) == _Py_REF_MERGED; } -static inline int -_Py_REF_IS_QUEUED(Py_ssize_t ob_ref_shared) -{ - return (ob_ref_shared & _Py_REF_SHARED_FLAG_MASK) == _Py_REF_QUEUED; -} - // Merge the local and shared reference count fields and add `extra` to the // refcount when merging. Py_ssize_t _Py_ExplicitMergeRefcount(PyObject *op, Py_ssize_t extra); @@ -836,9 +830,14 @@ _PyObject_IS_GC(PyObject *obj) && (type->tp_is_gc == NULL || type->tp_is_gc(obj))); } -// Fast inlined version of PyObject_Hash() -static inline Py_hash_t -_PyObject_HashFast(PyObject *op) +// Fast inlined version of PyObject_Hash(). Dictionaries are very +// likely to include string keys (class and instance attributes, +// json, ...) so we include a fast path for strings. +// This function should not be used in a collection if str is not +// very likely, since it is slower than PyObject_Hash() on types +// other than str. See gh-137759. +static inline Py_ALWAYS_INLINE Py_hash_t +_PyObject_HashDictKey(PyObject *op) { if (PyUnicode_CheckExact(op)) { Py_hash_t hash = PyUnstable_Unicode_GET_CACHED_HASH(op); diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index d2e29a1b95ede2f..80ad440bac8293c 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1476,10 +1476,10 @@ _PyOpcode_macro_expansion[256] = { [LOAD_ATTR_INSTANCE_VALUE] = { .nuops = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_MANAGED_OBJECT_HAS_VALUES, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_INSTANCE_VALUE, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_METHOD_LAZY_DICT] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_ATTR_METHOD_LAZY_DICT, 1, 3 }, { _LOAD_ATTR_METHOD_LAZY_DICT, 4, 5 } } }, [LOAD_ATTR_METHOD_NO_DICT] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_METHOD_NO_DICT, 4, 5 } } }, - [LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, OPARG_SIMPLE, 3 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } }, + [LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } }, [LOAD_ATTR_MODULE] = { .nuops = 4, .uops = { { _LOAD_ATTR_MODULE, 2, 1 }, { _LOAD_ATTR_MODULE, OPERAND1_1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_NONDESCRIPTOR_NO_DICT, 4, 5 } } }, - [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, OPARG_SIMPLE, 3 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } }, + [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 4, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } }, [LOAD_ATTR_PROPERTY] = { .nuops = 7, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, 2, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, OPERAND1_4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_SLOT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_WITH_HINT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_WITH_HINT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 8227f3fa9eedcf5..75273243ef6df06 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -2151,6 +2151,7 @@ extern "C" { INIT_ID(updates), \ INIT_ID(uri), \ INIT_ID(usedforsecurity), \ + INIT_ID(utcoffset), \ INIT_ID(value), \ INIT_ID(values), \ INIT_ID(version), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index cb731e9a6888781..164d9d412ef5e95 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -3284,6 +3284,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(utcoffset); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(value); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 7c44c0a430b7311..9d28c8590afcd7b 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -199,55 +199,54 @@ extern "C" { #define _GUARD_IS_TRUE_POP 460 #define _GUARD_ITERATOR 461 #define _GUARD_ITER_VIRTUAL 462 -#define _GUARD_KEYS_VERSION 463 -#define _GUARD_LOAD_SUPER_ATTR_METHOD 464 -#define _GUARD_NOS_COMPACT_ASCII 465 -#define _GUARD_NOS_DICT_STORE_SUBSCRIPT 466 -#define _GUARD_NOS_DICT_SUBSCRIPT 467 -#define _GUARD_NOS_FLOAT 468 -#define _GUARD_NOS_INT 469 -#define _GUARD_NOS_ITER_VIRTUAL 470 -#define _GUARD_NOS_LIST 471 -#define _GUARD_NOS_NOT_NULL 472 -#define _GUARD_NOS_NULL 473 -#define _GUARD_NOS_OVERFLOWED 474 -#define _GUARD_NOS_TUPLE 475 -#define _GUARD_NOS_TYPE_VERSION 476 -#define _GUARD_NOS_UNICODE 477 -#define _GUARD_NOT_EXHAUSTED_LIST 478 -#define _GUARD_NOT_EXHAUSTED_RANGE 479 -#define _GUARD_NOT_EXHAUSTED_TUPLE 480 -#define _GUARD_THIRD_NULL 481 -#define _GUARD_TOS_ANY_DICT 482 -#define _GUARD_TOS_ANY_SET 483 -#define _GUARD_TOS_DICT 484 -#define _GUARD_TOS_FLOAT 485 -#define _GUARD_TOS_FROZENDICT 486 -#define _GUARD_TOS_FROZENSET 487 -#define _GUARD_TOS_INT 488 -#define _GUARD_TOS_IS_NONE 489 -#define _GUARD_TOS_LIST 490 -#define _GUARD_TOS_NOT_NULL 491 -#define _GUARD_TOS_OVERFLOWED 492 -#define _GUARD_TOS_SET 493 -#define _GUARD_TOS_SLICE 494 -#define _GUARD_TOS_TUPLE 495 -#define _GUARD_TOS_UNICODE 496 -#define _GUARD_TYPE 497 -#define _GUARD_TYPE_ITER 498 -#define _GUARD_TYPE_VERSION 499 -#define _GUARD_TYPE_VERSION_LOCKED 500 -#define _HANDLE_PENDING_AND_DEOPT 501 +#define _GUARD_LOAD_SUPER_ATTR_METHOD 463 +#define _GUARD_NOS_COMPACT_ASCII 464 +#define _GUARD_NOS_DICT_STORE_SUBSCRIPT 465 +#define _GUARD_NOS_DICT_SUBSCRIPT 466 +#define _GUARD_NOS_FLOAT 467 +#define _GUARD_NOS_INT 468 +#define _GUARD_NOS_ITER_VIRTUAL 469 +#define _GUARD_NOS_LIST 470 +#define _GUARD_NOS_NOT_NULL 471 +#define _GUARD_NOS_NULL 472 +#define _GUARD_NOS_OVERFLOWED 473 +#define _GUARD_NOS_TUPLE 474 +#define _GUARD_NOS_TYPE_VERSION 475 +#define _GUARD_NOS_UNICODE 476 +#define _GUARD_NOT_EXHAUSTED_LIST 477 +#define _GUARD_NOT_EXHAUSTED_RANGE 478 +#define _GUARD_NOT_EXHAUSTED_TUPLE 479 +#define _GUARD_THIRD_NULL 480 +#define _GUARD_TOS_ANY_DICT 481 +#define _GUARD_TOS_ANY_SET 482 +#define _GUARD_TOS_DICT 483 +#define _GUARD_TOS_FLOAT 484 +#define _GUARD_TOS_FROZENDICT 485 +#define _GUARD_TOS_FROZENSET 486 +#define _GUARD_TOS_INT 487 +#define _GUARD_TOS_IS_NONE 488 +#define _GUARD_TOS_LIST 489 +#define _GUARD_TOS_NOT_NULL 490 +#define _GUARD_TOS_OVERFLOWED 491 +#define _GUARD_TOS_SET 492 +#define _GUARD_TOS_SLICE 493 +#define _GUARD_TOS_TUPLE 494 +#define _GUARD_TOS_UNICODE 495 +#define _GUARD_TYPE 496 +#define _GUARD_TYPE_ITER 497 +#define _GUARD_TYPE_VERSION 498 +#define _GUARD_TYPE_VERSION_LOCKED 499 +#define _HANDLE_PENDING_AND_DEOPT 500 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 502 -#define _INIT_CALL_PY_EXACT_ARGS 503 -#define _INIT_CALL_PY_EXACT_ARGS_0 504 -#define _INIT_CALL_PY_EXACT_ARGS_1 505 -#define _INIT_CALL_PY_EXACT_ARGS_2 506 -#define _INIT_CALL_PY_EXACT_ARGS_3 507 -#define _INIT_CALL_PY_EXACT_ARGS_4 508 -#define _INSERT_NULL 509 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 501 +#define _INIT_CALL_PY_EXACT_ARGS 502 +#define _INIT_CALL_PY_EXACT_ARGS_0 503 +#define _INIT_CALL_PY_EXACT_ARGS_1 504 +#define _INIT_CALL_PY_EXACT_ARGS_2 505 +#define _INIT_CALL_PY_EXACT_ARGS_3 506 +#define _INIT_CALL_PY_EXACT_ARGS_4 507 +#define _INSERT_NULL 508 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -257,1194 +256,1190 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 510 -#define _IS_OP 511 -#define _ITER_CHECK_LIST 512 -#define _ITER_CHECK_RANGE 513 -#define _ITER_CHECK_TUPLE 514 -#define _ITER_JUMP_LIST 515 -#define _ITER_JUMP_RANGE 516 -#define _ITER_JUMP_TUPLE 517 -#define _ITER_NEXT_INLINE 518 -#define _ITER_NEXT_LIST 519 -#define _ITER_NEXT_LIST_TIER_TWO 520 -#define _ITER_NEXT_RANGE 521 -#define _ITER_NEXT_TUPLE 522 +#define _IS_NONE 509 +#define _IS_OP 510 +#define _ITER_CHECK_LIST 511 +#define _ITER_CHECK_RANGE 512 +#define _ITER_CHECK_TUPLE 513 +#define _ITER_JUMP_LIST 514 +#define _ITER_JUMP_RANGE 515 +#define _ITER_JUMP_TUPLE 516 +#define _ITER_NEXT_INLINE 517 +#define _ITER_NEXT_LIST 518 +#define _ITER_NEXT_LIST_TIER_TWO 519 +#define _ITER_NEXT_RANGE 520 +#define _ITER_NEXT_TUPLE 521 #define _JUMP_BACKWARD_NO_INTERRUPT JUMP_BACKWARD_NO_INTERRUPT -#define _JUMP_TO_TOP 523 +#define _JUMP_TO_TOP 522 #define _LIST_APPEND LIST_APPEND -#define _LIST_EXTEND 524 -#define _LOAD_ATTR 525 -#define _LOAD_ATTR_CLASS 526 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME 527 -#define _LOAD_ATTR_INSTANCE_VALUE 528 -#define _LOAD_ATTR_METHOD_LAZY_DICT 529 -#define _LOAD_ATTR_METHOD_NO_DICT 530 -#define _LOAD_ATTR_METHOD_WITH_VALUES 531 -#define _LOAD_ATTR_MODULE 532 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 533 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 534 -#define _LOAD_ATTR_PROPERTY_FRAME 535 -#define _LOAD_ATTR_SLOT 536 -#define _LOAD_ATTR_WITH_HINT 537 +#define _LIST_EXTEND 523 +#define _LOAD_ATTR 524 +#define _LOAD_ATTR_CLASS 525 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME 526 +#define _LOAD_ATTR_INSTANCE_VALUE 527 +#define _LOAD_ATTR_METHOD_LAZY_DICT 528 +#define _LOAD_ATTR_METHOD_NO_DICT 529 +#define _LOAD_ATTR_METHOD_WITH_VALUES 530 +#define _LOAD_ATTR_MODULE 531 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 532 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 533 +#define _LOAD_ATTR_PROPERTY_FRAME 534 +#define _LOAD_ATTR_SLOT 535 +#define _LOAD_ATTR_WITH_HINT 536 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 538 +#define _LOAD_BYTECODE 537 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 539 -#define _LOAD_CONST_INLINE_BORROW 540 +#define _LOAD_CONST_INLINE 538 +#define _LOAD_CONST_INLINE_BORROW 539 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 541 -#define _LOAD_FAST_0 542 -#define _LOAD_FAST_1 543 -#define _LOAD_FAST_2 544 -#define _LOAD_FAST_3 545 -#define _LOAD_FAST_4 546 -#define _LOAD_FAST_5 547 -#define _LOAD_FAST_6 548 -#define _LOAD_FAST_7 549 +#define _LOAD_FAST 540 +#define _LOAD_FAST_0 541 +#define _LOAD_FAST_1 542 +#define _LOAD_FAST_2 543 +#define _LOAD_FAST_3 544 +#define _LOAD_FAST_4 545 +#define _LOAD_FAST_5 546 +#define _LOAD_FAST_6 547 +#define _LOAD_FAST_7 548 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 550 -#define _LOAD_FAST_BORROW_0 551 -#define _LOAD_FAST_BORROW_1 552 -#define _LOAD_FAST_BORROW_2 553 -#define _LOAD_FAST_BORROW_3 554 -#define _LOAD_FAST_BORROW_4 555 -#define _LOAD_FAST_BORROW_5 556 -#define _LOAD_FAST_BORROW_6 557 -#define _LOAD_FAST_BORROW_7 558 +#define _LOAD_FAST_BORROW 549 +#define _LOAD_FAST_BORROW_0 550 +#define _LOAD_FAST_BORROW_1 551 +#define _LOAD_FAST_BORROW_2 552 +#define _LOAD_FAST_BORROW_3 553 +#define _LOAD_FAST_BORROW_4 554 +#define _LOAD_FAST_BORROW_5 555 +#define _LOAD_FAST_BORROW_6 556 +#define _LOAD_FAST_BORROW_7 557 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 559 -#define _LOAD_GLOBAL_BUILTINS 560 -#define _LOAD_GLOBAL_MODULE 561 +#define _LOAD_GLOBAL 558 +#define _LOAD_GLOBAL_BUILTINS 559 +#define _LOAD_GLOBAL_MODULE 560 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 562 -#define _LOAD_SMALL_INT_0 563 -#define _LOAD_SMALL_INT_1 564 -#define _LOAD_SMALL_INT_2 565 -#define _LOAD_SMALL_INT_3 566 -#define _LOAD_SPECIAL 567 +#define _LOAD_SMALL_INT 561 +#define _LOAD_SMALL_INT_0 562 +#define _LOAD_SMALL_INT_1 563 +#define _LOAD_SMALL_INT_2 564 +#define _LOAD_SMALL_INT_3 565 +#define _LOAD_SPECIAL 566 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR -#define _LOAD_SUPER_ATTR_METHOD 568 -#define _LOCK_OBJECT 569 -#define _MAKE_CALLARGS_A_TUPLE 570 +#define _LOAD_SUPER_ATTR_METHOD 567 +#define _LOCK_OBJECT 568 +#define _MAKE_CALLARGS_A_TUPLE 569 #define _MAKE_CELL MAKE_CELL -#define _MAKE_FUNCTION 571 -#define _MAKE_HEAP_SAFE 572 -#define _MAKE_WARM 573 +#define _MAKE_FUNCTION 570 +#define _MAKE_HEAP_SAFE 571 +#define _MAKE_WARM 572 #define _MAP_ADD MAP_ADD -#define _MATCH_CLASS 574 +#define _MATCH_CLASS 573 #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 575 -#define _MAYBE_EXPAND_METHOD_KW 576 -#define _MONITOR_CALL 577 -#define _MONITOR_CALL_KW 578 -#define _MONITOR_JUMP_BACKWARD 579 -#define _MONITOR_RESUME 580 +#define _MAYBE_EXPAND_METHOD 574 +#define _MAYBE_EXPAND_METHOD_KW 575 +#define _MONITOR_CALL 576 +#define _MONITOR_CALL_KW 577 +#define _MONITOR_JUMP_BACKWARD 578 +#define _MONITOR_RESUME 579 #define _NOP NOP #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 581 -#define _POP_JUMP_IF_TRUE 582 +#define _POP_JUMP_IF_FALSE 580 +#define _POP_JUMP_IF_TRUE 581 #define _POP_TOP POP_TOP -#define _POP_TOP_FLOAT 583 -#define _POP_TOP_INT 584 -#define _POP_TOP_NOP 585 -#define _POP_TOP_OPARG 586 -#define _POP_TOP_UNICODE 587 +#define _POP_TOP_FLOAT 582 +#define _POP_TOP_INT 583 +#define _POP_TOP_NOP 584 +#define _POP_TOP_OPARG 585 +#define _POP_TOP_UNICODE 586 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 588 +#define _PUSH_FRAME 587 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 589 -#define _PUSH_TAGGED_ZERO 590 -#define _PY_FRAME_EX 591 -#define _PY_FRAME_GENERAL 592 -#define _PY_FRAME_KW 593 -#define _RECORD_3OS_GEN_FUNC 594 -#define _RECORD_4OS 595 -#define _RECORD_BOUND_METHOD 596 -#define _RECORD_CALLABLE 597 -#define _RECORD_CALLABLE_KW 598 -#define _RECORD_CODE 599 -#define _RECORD_NOS 600 -#define _RECORD_NOS_GEN_FUNC 601 -#define _RECORD_NOS_TYPE 602 -#define _RECORD_TOS 603 -#define _RECORD_TOS_TYPE 604 -#define _REPLACE_WITH_TRUE 605 -#define _RESUME_CHECK 606 +#define _PUSH_NULL_CONDITIONAL 588 +#define _PUSH_TAGGED_ZERO 589 +#define _PY_FRAME_EX 590 +#define _PY_FRAME_GENERAL 591 +#define _PY_FRAME_KW 592 +#define _RECORD_3OS_GEN_FUNC 593 +#define _RECORD_4OS 594 +#define _RECORD_BOUND_METHOD 595 +#define _RECORD_CALLABLE 596 +#define _RECORD_CALLABLE_KW 597 +#define _RECORD_CODE 598 +#define _RECORD_NOS 599 +#define _RECORD_NOS_GEN_FUNC 600 +#define _RECORD_NOS_TYPE 601 +#define _RECORD_TOS 602 +#define _RECORD_TOS_TYPE 603 +#define _REPLACE_WITH_TRUE 604 +#define _RESUME_CHECK 605 #define _RETURN_GENERATOR RETURN_GENERATOR -#define _RETURN_VALUE 607 -#define _RROT_3 608 -#define _SAVE_RETURN_OFFSET 609 -#define _SEND_ASYNC_GEN 610 -#define _SEND_ASYNC_GEN_TIER_TWO 611 -#define _SEND_GEN_FRAME 612 -#define _SEND_VIRTUAL 613 -#define _SEND_VIRTUAL_TIER_TWO 614 +#define _RETURN_VALUE 606 +#define _RROT_3 607 +#define _SAVE_RETURN_OFFSET 608 +#define _SEND_ASYNC_GEN 609 +#define _SEND_ASYNC_GEN_TIER_TWO 610 +#define _SEND_GEN_FRAME 611 +#define _SEND_VIRTUAL 612 +#define _SEND_VIRTUAL_TIER_TWO 613 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE -#define _SET_UPDATE 615 -#define _SPILL_OR_RELOAD 616 -#define _START_EXECUTOR 617 -#define _STORE_ATTR 618 -#define _STORE_ATTR_INSTANCE_VALUE 619 -#define _STORE_ATTR_SLOT 620 -#define _STORE_ATTR_WITH_HINT 621 +#define _SET_UPDATE 614 +#define _SPILL_OR_RELOAD 615 +#define _START_EXECUTOR 616 +#define _STORE_ATTR 617 +#define _STORE_ATTR_INSTANCE_VALUE 618 +#define _STORE_ATTR_SLOT 619 +#define _STORE_ATTR_WITH_HINT 620 #define _STORE_DEREF STORE_DEREF #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 622 -#define _STORE_SUBSCR 623 -#define _STORE_SUBSCR_DICT 624 -#define _STORE_SUBSCR_DICT_KNOWN_HASH 625 -#define _STORE_SUBSCR_LIST_INT 626 -#define _SWAP 627 -#define _SWAP_2 628 -#define _SWAP_3 629 -#define _SWAP_FAST 630 -#define _SWAP_FAST_0 631 -#define _SWAP_FAST_1 632 -#define _SWAP_FAST_2 633 -#define _SWAP_FAST_3 634 -#define _SWAP_FAST_4 635 -#define _SWAP_FAST_5 636 -#define _SWAP_FAST_6 637 -#define _SWAP_FAST_7 638 -#define _TIER2_RESUME_CHECK 639 -#define _TO_BOOL 640 +#define _STORE_SLICE 621 +#define _STORE_SUBSCR 622 +#define _STORE_SUBSCR_DICT 623 +#define _STORE_SUBSCR_DICT_KNOWN_HASH 624 +#define _STORE_SUBSCR_LIST_INT 625 +#define _SWAP 626 +#define _SWAP_2 627 +#define _SWAP_3 628 +#define _SWAP_FAST 629 +#define _SWAP_FAST_0 630 +#define _SWAP_FAST_1 631 +#define _SWAP_FAST_2 632 +#define _SWAP_FAST_3 633 +#define _SWAP_FAST_4 634 +#define _SWAP_FAST_5 635 +#define _SWAP_FAST_6 636 +#define _SWAP_FAST_7 637 +#define _TIER2_RESUME_CHECK 638 +#define _TO_BOOL 639 #define _TO_BOOL_BOOL TO_BOOL_BOOL -#define _TO_BOOL_INT 641 -#define _TO_BOOL_LIST 642 +#define _TO_BOOL_INT 640 +#define _TO_BOOL_LIST 641 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 643 +#define _TO_BOOL_STR 642 #define _TRACE_RECORD TRACE_RECORD -#define _UNARY_INVERT 644 -#define _UNARY_NEGATIVE 645 -#define _UNARY_NEGATIVE_FLOAT_INPLACE 646 +#define _UNARY_INVERT 643 +#define _UNARY_NEGATIVE 644 +#define _UNARY_NEGATIVE_FLOAT_INPLACE 645 #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 647 -#define _UNPACK_SEQUENCE_LIST 648 -#define _UNPACK_SEQUENCE_TUPLE 649 -#define _UNPACK_SEQUENCE_TWO_TUPLE 650 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 651 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 652 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 653 +#define _UNPACK_SEQUENCE 646 +#define _UNPACK_SEQUENCE_LIST 647 +#define _UNPACK_SEQUENCE_TUPLE 648 +#define _UNPACK_SEQUENCE_TWO_TUPLE 649 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE 650 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE 651 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE 652 #define _WITH_EXCEPT_START WITH_EXCEPT_START -#define _YIELD_VALUE 654 -#define MAX_UOP_ID 654 -#define _ALLOCATE_OBJECT_r00 655 -#define _BINARY_OP_r23 656 -#define _BINARY_OP_ADD_FLOAT_r03 657 -#define _BINARY_OP_ADD_FLOAT_r13 658 -#define _BINARY_OP_ADD_FLOAT_r23 659 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 660 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 661 -#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 662 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 663 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 664 -#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 665 -#define _BINARY_OP_ADD_INT_r03 666 -#define _BINARY_OP_ADD_INT_r13 667 -#define _BINARY_OP_ADD_INT_r23 668 -#define _BINARY_OP_ADD_INT_INPLACE_r03 669 -#define _BINARY_OP_ADD_INT_INPLACE_r13 670 -#define _BINARY_OP_ADD_INT_INPLACE_r23 671 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 672 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 673 -#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 674 -#define _BINARY_OP_ADD_UNICODE_r03 675 -#define _BINARY_OP_ADD_UNICODE_r13 676 -#define _BINARY_OP_ADD_UNICODE_r23 677 -#define _BINARY_OP_EXTEND_r23 678 -#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 679 -#define _BINARY_OP_MULTIPLY_FLOAT_r03 680 -#define _BINARY_OP_MULTIPLY_FLOAT_r13 681 -#define _BINARY_OP_MULTIPLY_FLOAT_r23 682 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 683 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 684 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 685 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 686 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 687 -#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 688 -#define _BINARY_OP_MULTIPLY_INT_r03 689 -#define _BINARY_OP_MULTIPLY_INT_r13 690 -#define _BINARY_OP_MULTIPLY_INT_r23 691 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 692 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 693 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 694 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 695 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 696 -#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 697 -#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 698 -#define _BINARY_OP_SUBSCR_DICT_r23 699 -#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 700 -#define _BINARY_OP_SUBSCR_INIT_CALL_r01 701 -#define _BINARY_OP_SUBSCR_INIT_CALL_r11 702 -#define _BINARY_OP_SUBSCR_INIT_CALL_r21 703 -#define _BINARY_OP_SUBSCR_INIT_CALL_r31 704 -#define _BINARY_OP_SUBSCR_LIST_INT_r23 705 -#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 706 -#define _BINARY_OP_SUBSCR_STR_INT_r23 707 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 708 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 709 -#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 710 -#define _BINARY_OP_SUBSCR_USTR_INT_r23 711 -#define _BINARY_OP_SUBTRACT_FLOAT_r03 712 -#define _BINARY_OP_SUBTRACT_FLOAT_r13 713 -#define _BINARY_OP_SUBTRACT_FLOAT_r23 714 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 715 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 716 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 717 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 718 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 719 -#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 720 -#define _BINARY_OP_SUBTRACT_INT_r03 721 -#define _BINARY_OP_SUBTRACT_INT_r13 722 -#define _BINARY_OP_SUBTRACT_INT_r23 723 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 724 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 725 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 726 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 727 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 728 -#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 729 -#define _BINARY_OP_TRUEDIV_FLOAT_r23 730 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 731 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 732 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 733 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 734 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 735 -#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 736 -#define _BINARY_SLICE_r31 737 -#define _BUILD_INTERPOLATION_r01 738 -#define _BUILD_LIST_r01 739 -#define _BUILD_MAP_r01 740 -#define _BUILD_SET_r01 741 -#define _BUILD_SLICE_r01 742 -#define _BUILD_STRING_r01 743 -#define _BUILD_TEMPLATE_r21 744 -#define _BUILD_TUPLE_r01 745 -#define _CALL_BUILTIN_CLASS_r00 746 -#define _CALL_BUILTIN_FAST_r00 747 -#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 748 -#define _CALL_BUILTIN_O_r03 749 -#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 750 -#define _CALL_INTRINSIC_1_r12 751 -#define _CALL_INTRINSIC_2_r23 752 -#define _CALL_ISINSTANCE_r31 753 -#define _CALL_KW_NON_PY_r11 754 -#define _CALL_LEN_r33 755 -#define _CALL_LIST_APPEND_r03 756 -#define _CALL_LIST_APPEND_r13 757 -#define _CALL_LIST_APPEND_r23 758 -#define _CALL_LIST_APPEND_r33 759 -#define _CALL_METHOD_DESCRIPTOR_FAST_r00 760 -#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 761 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 762 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 763 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_r03 764 -#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 765 -#define _CALL_METHOD_DESCRIPTOR_O_r03 766 -#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 767 -#define _CALL_NON_PY_GENERAL_r01 768 -#define _CALL_STR_1_r32 769 -#define _CALL_TUPLE_1_r32 770 -#define _CALL_TYPE_1_r02 771 -#define _CALL_TYPE_1_r12 772 -#define _CALL_TYPE_1_r22 773 -#define _CALL_TYPE_1_r32 774 -#define _CHECK_ATTR_CLASS_r01 775 -#define _CHECK_ATTR_CLASS_r11 776 -#define _CHECK_ATTR_CLASS_r22 777 -#define _CHECK_ATTR_CLASS_r33 778 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 779 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 780 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 781 -#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 782 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 783 -#define _CHECK_EG_MATCH_r22 784 -#define _CHECK_EXC_MATCH_r22 785 -#define _CHECK_FUNCTION_EXACT_ARGS_r00 786 -#define _CHECK_FUNCTION_VERSION_r00 787 -#define _CHECK_FUNCTION_VERSION_INLINE_r00 788 -#define _CHECK_FUNCTION_VERSION_INLINE_r11 789 -#define _CHECK_FUNCTION_VERSION_INLINE_r22 790 -#define _CHECK_FUNCTION_VERSION_INLINE_r33 791 -#define _CHECK_FUNCTION_VERSION_KW_r11 792 -#define _CHECK_IS_NOT_PY_CALLABLE_r00 793 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 794 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 795 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 796 -#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 797 -#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 798 -#define _CHECK_IS_PY_CALLABLE_EX_r03 799 -#define _CHECK_IS_PY_CALLABLE_EX_r13 800 -#define _CHECK_IS_PY_CALLABLE_EX_r23 801 -#define _CHECK_IS_PY_CALLABLE_EX_r33 802 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 803 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 804 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 805 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 806 -#define _CHECK_METHOD_VERSION_r00 807 -#define _CHECK_METHOD_VERSION_KW_r11 808 -#define _CHECK_OBJECT_r00 809 -#define _CHECK_PEP_523_r00 810 -#define _CHECK_PEP_523_r11 811 -#define _CHECK_PEP_523_r22 812 -#define _CHECK_PEP_523_r33 813 -#define _CHECK_PERIODIC_r00 814 -#define _CHECK_PERIODIC_AT_END_r00 815 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 816 -#define _CHECK_RECURSION_LIMIT_r00 817 -#define _CHECK_RECURSION_LIMIT_r11 818 -#define _CHECK_RECURSION_LIMIT_r22 819 -#define _CHECK_RECURSION_LIMIT_r33 820 -#define _CHECK_RECURSION_REMAINING_r00 821 -#define _CHECK_RECURSION_REMAINING_r11 822 -#define _CHECK_RECURSION_REMAINING_r22 823 -#define _CHECK_RECURSION_REMAINING_r33 824 -#define _CHECK_STACK_SPACE_r00 825 -#define _CHECK_STACK_SPACE_OPERAND_r00 826 -#define _CHECK_STACK_SPACE_OPERAND_r11 827 -#define _CHECK_STACK_SPACE_OPERAND_r22 828 -#define _CHECK_STACK_SPACE_OPERAND_r33 829 -#define _CHECK_VALIDITY_r00 830 -#define _CHECK_VALIDITY_r11 831 -#define _CHECK_VALIDITY_r22 832 -#define _CHECK_VALIDITY_r33 833 -#define _COLD_DYNAMIC_EXIT_r00 834 -#define _COLD_EXIT_r00 835 -#define _COMPARE_OP_r21 836 -#define _COMPARE_OP_FLOAT_r03 837 -#define _COMPARE_OP_FLOAT_r13 838 -#define _COMPARE_OP_FLOAT_r23 839 -#define _COMPARE_OP_INT_r23 840 -#define _COMPARE_OP_STR_r23 841 -#define _CONTAINS_OP_r23 842 -#define _CONTAINS_OP_DICT_r23 843 -#define _CONTAINS_OP_SET_r23 844 -#define _CONVERT_VALUE_r11 845 -#define _COPY_r01 846 -#define _COPY_1_r02 847 -#define _COPY_1_r12 848 -#define _COPY_1_r23 849 -#define _COPY_2_r03 850 -#define _COPY_2_r13 851 -#define _COPY_2_r23 852 -#define _COPY_3_r03 853 -#define _COPY_3_r13 854 -#define _COPY_3_r23 855 -#define _COPY_3_r33 856 -#define _COPY_FREE_VARS_r00 857 -#define _COPY_FREE_VARS_r11 858 -#define _COPY_FREE_VARS_r22 859 -#define _COPY_FREE_VARS_r33 860 -#define _CREATE_INIT_FRAME_r01 861 -#define _DELETE_ATTR_r10 862 -#define _DELETE_DEREF_r00 863 -#define _DELETE_FAST_r00 864 -#define _DELETE_GLOBAL_r00 865 -#define _DELETE_NAME_r00 866 -#define _DELETE_SUBSCR_r20 867 -#define _DEOPT_r00 868 -#define _DEOPT_r10 869 -#define _DEOPT_r20 870 -#define _DEOPT_r30 871 -#define _DICT_MERGE_r11 872 -#define _DICT_UPDATE_r11 873 -#define _DO_CALL_r01 874 -#define _DO_CALL_FUNCTION_EX_r31 875 -#define _DO_CALL_KW_r11 876 -#define _DYNAMIC_EXIT_r00 877 -#define _DYNAMIC_EXIT_r10 878 -#define _DYNAMIC_EXIT_r20 879 -#define _DYNAMIC_EXIT_r30 880 -#define _END_FOR_r10 881 -#define _END_SEND_r31 882 -#define _ERROR_POP_N_r00 883 -#define _EXIT_INIT_CHECK_r10 884 -#define _EXIT_TRACE_r00 885 -#define _EXIT_TRACE_r10 886 -#define _EXIT_TRACE_r20 887 -#define _EXIT_TRACE_r30 888 -#define _EXPAND_METHOD_r00 889 -#define _EXPAND_METHOD_KW_r11 890 -#define _FATAL_ERROR_r00 891 -#define _FATAL_ERROR_r11 892 -#define _FATAL_ERROR_r22 893 -#define _FATAL_ERROR_r33 894 -#define _FORMAT_SIMPLE_r11 895 -#define _FORMAT_WITH_SPEC_r21 896 -#define _FOR_ITER_r23 897 -#define _FOR_ITER_GEN_FRAME_r03 898 -#define _FOR_ITER_GEN_FRAME_r13 899 -#define _FOR_ITER_GEN_FRAME_r23 900 -#define _FOR_ITER_TIER_TWO_r23 901 -#define _FOR_ITER_VIRTUAL_r23 902 -#define _FOR_ITER_VIRTUAL_TIER_TWO_r23 903 -#define _GET_AITER_r11 904 -#define _GET_ANEXT_r12 905 -#define _GET_AWAITABLE_r11 906 -#define _GET_ITER_r12 907 -#define _GET_ITER_TRAD_r12 908 -#define _GET_LEN_r12 909 -#define _GUARD_3OS_ASYNC_GEN_ASEND_r03 910 -#define _GUARD_3OS_ASYNC_GEN_ASEND_r13 911 -#define _GUARD_3OS_ASYNC_GEN_ASEND_r23 912 -#define _GUARD_3OS_ASYNC_GEN_ASEND_r33 913 -#define _GUARD_BINARY_OP_EXTEND_r22 914 -#define _GUARD_BINARY_OP_EXTEND_LHS_r02 915 -#define _GUARD_BINARY_OP_EXTEND_LHS_r12 916 -#define _GUARD_BINARY_OP_EXTEND_LHS_r22 917 -#define _GUARD_BINARY_OP_EXTEND_LHS_r33 918 -#define _GUARD_BINARY_OP_EXTEND_RHS_r02 919 -#define _GUARD_BINARY_OP_EXTEND_RHS_r12 920 -#define _GUARD_BINARY_OP_EXTEND_RHS_r22 921 -#define _GUARD_BINARY_OP_EXTEND_RHS_r33 922 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 923 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 924 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 925 -#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 926 -#define _GUARD_BIT_IS_SET_POP_r00 927 -#define _GUARD_BIT_IS_SET_POP_r10 928 -#define _GUARD_BIT_IS_SET_POP_r21 929 -#define _GUARD_BIT_IS_SET_POP_r32 930 -#define _GUARD_BIT_IS_SET_POP_4_r00 931 -#define _GUARD_BIT_IS_SET_POP_4_r10 932 -#define _GUARD_BIT_IS_SET_POP_4_r21 933 -#define _GUARD_BIT_IS_SET_POP_4_r32 934 -#define _GUARD_BIT_IS_SET_POP_5_r00 935 -#define _GUARD_BIT_IS_SET_POP_5_r10 936 -#define _GUARD_BIT_IS_SET_POP_5_r21 937 -#define _GUARD_BIT_IS_SET_POP_5_r32 938 -#define _GUARD_BIT_IS_SET_POP_6_r00 939 -#define _GUARD_BIT_IS_SET_POP_6_r10 940 -#define _GUARD_BIT_IS_SET_POP_6_r21 941 -#define _GUARD_BIT_IS_SET_POP_6_r32 942 -#define _GUARD_BIT_IS_SET_POP_7_r00 943 -#define _GUARD_BIT_IS_SET_POP_7_r10 944 -#define _GUARD_BIT_IS_SET_POP_7_r21 945 -#define _GUARD_BIT_IS_SET_POP_7_r32 946 -#define _GUARD_BIT_IS_UNSET_POP_r00 947 -#define _GUARD_BIT_IS_UNSET_POP_r10 948 -#define _GUARD_BIT_IS_UNSET_POP_r21 949 -#define _GUARD_BIT_IS_UNSET_POP_r32 950 -#define _GUARD_BIT_IS_UNSET_POP_4_r00 951 -#define _GUARD_BIT_IS_UNSET_POP_4_r10 952 -#define _GUARD_BIT_IS_UNSET_POP_4_r21 953 -#define _GUARD_BIT_IS_UNSET_POP_4_r32 954 -#define _GUARD_BIT_IS_UNSET_POP_5_r00 955 -#define _GUARD_BIT_IS_UNSET_POP_5_r10 956 -#define _GUARD_BIT_IS_UNSET_POP_5_r21 957 -#define _GUARD_BIT_IS_UNSET_POP_5_r32 958 -#define _GUARD_BIT_IS_UNSET_POP_6_r00 959 -#define _GUARD_BIT_IS_UNSET_POP_6_r10 960 -#define _GUARD_BIT_IS_UNSET_POP_6_r21 961 -#define _GUARD_BIT_IS_UNSET_POP_6_r32 962 -#define _GUARD_BIT_IS_UNSET_POP_7_r00 963 -#define _GUARD_BIT_IS_UNSET_POP_7_r10 964 -#define _GUARD_BIT_IS_UNSET_POP_7_r21 965 -#define _GUARD_BIT_IS_UNSET_POP_7_r32 966 -#define _GUARD_CALLABLE_BUILTIN_CLASS_r00 967 -#define _GUARD_CALLABLE_BUILTIN_FAST_r00 968 -#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 969 -#define _GUARD_CALLABLE_BUILTIN_O_r00 970 -#define _GUARD_CALLABLE_ISINSTANCE_r03 971 -#define _GUARD_CALLABLE_ISINSTANCE_r13 972 -#define _GUARD_CALLABLE_ISINSTANCE_r23 973 -#define _GUARD_CALLABLE_ISINSTANCE_r33 974 -#define _GUARD_CALLABLE_LEN_r03 975 -#define _GUARD_CALLABLE_LEN_r13 976 -#define _GUARD_CALLABLE_LEN_r23 977 -#define _GUARD_CALLABLE_LEN_r33 978 -#define _GUARD_CALLABLE_LIST_APPEND_r03 979 -#define _GUARD_CALLABLE_LIST_APPEND_r13 980 -#define _GUARD_CALLABLE_LIST_APPEND_r23 981 -#define _GUARD_CALLABLE_LIST_APPEND_r33 982 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 983 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 984 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 985 -#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 986 -#define _GUARD_CALLABLE_STR_1_r03 987 -#define _GUARD_CALLABLE_STR_1_r13 988 -#define _GUARD_CALLABLE_STR_1_r23 989 -#define _GUARD_CALLABLE_STR_1_r33 990 -#define _GUARD_CALLABLE_TUPLE_1_r03 991 -#define _GUARD_CALLABLE_TUPLE_1_r13 992 -#define _GUARD_CALLABLE_TUPLE_1_r23 993 -#define _GUARD_CALLABLE_TUPLE_1_r33 994 -#define _GUARD_CALLABLE_TYPE_1_r03 995 -#define _GUARD_CALLABLE_TYPE_1_r13 996 -#define _GUARD_CALLABLE_TYPE_1_r23 997 -#define _GUARD_CALLABLE_TYPE_1_r33 998 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 999 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 1000 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 1001 -#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 1002 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 1003 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 1004 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 1005 -#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 1006 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 1007 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 1008 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 1009 -#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 1010 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 1011 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 1012 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 1013 -#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 1014 -#define _GUARD_DORV_NO_DICT_r01 1015 -#define _GUARD_DORV_NO_DICT_r11 1016 -#define _GUARD_DORV_NO_DICT_r22 1017 -#define _GUARD_DORV_NO_DICT_r33 1018 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 1019 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 1020 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 1021 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 1022 -#define _GUARD_GLOBALS_VERSION_r00 1023 -#define _GUARD_GLOBALS_VERSION_r11 1024 -#define _GUARD_GLOBALS_VERSION_r22 1025 -#define _GUARD_GLOBALS_VERSION_r33 1026 -#define _GUARD_IP_RETURN_GENERATOR_r00 1027 -#define _GUARD_IP_RETURN_GENERATOR_r11 1028 -#define _GUARD_IP_RETURN_GENERATOR_r22 1029 -#define _GUARD_IP_RETURN_GENERATOR_r33 1030 -#define _GUARD_IP_RETURN_VALUE_r00 1031 -#define _GUARD_IP_RETURN_VALUE_r11 1032 -#define _GUARD_IP_RETURN_VALUE_r22 1033 -#define _GUARD_IP_RETURN_VALUE_r33 1034 -#define _GUARD_IP_YIELD_VALUE_r00 1035 -#define _GUARD_IP_YIELD_VALUE_r11 1036 -#define _GUARD_IP_YIELD_VALUE_r22 1037 -#define _GUARD_IP_YIELD_VALUE_r33 1038 -#define _GUARD_IP__PUSH_FRAME_r00 1039 -#define _GUARD_IP__PUSH_FRAME_r11 1040 -#define _GUARD_IP__PUSH_FRAME_r22 1041 -#define _GUARD_IP__PUSH_FRAME_r33 1042 -#define _GUARD_IS_FALSE_POP_r00 1043 -#define _GUARD_IS_FALSE_POP_r10 1044 -#define _GUARD_IS_FALSE_POP_r21 1045 -#define _GUARD_IS_FALSE_POP_r32 1046 -#define _GUARD_IS_NONE_POP_r00 1047 -#define _GUARD_IS_NONE_POP_r10 1048 -#define _GUARD_IS_NONE_POP_r21 1049 -#define _GUARD_IS_NONE_POP_r32 1050 -#define _GUARD_IS_NOT_NONE_POP_r10 1051 -#define _GUARD_IS_TRUE_POP_r00 1052 -#define _GUARD_IS_TRUE_POP_r10 1053 -#define _GUARD_IS_TRUE_POP_r21 1054 -#define _GUARD_IS_TRUE_POP_r32 1055 -#define _GUARD_ITERATOR_r01 1056 -#define _GUARD_ITERATOR_r11 1057 -#define _GUARD_ITERATOR_r22 1058 -#define _GUARD_ITERATOR_r33 1059 -#define _GUARD_ITER_VIRTUAL_r01 1060 -#define _GUARD_ITER_VIRTUAL_r11 1061 -#define _GUARD_ITER_VIRTUAL_r22 1062 -#define _GUARD_ITER_VIRTUAL_r33 1063 -#define _GUARD_KEYS_VERSION_r01 1064 -#define _GUARD_KEYS_VERSION_r11 1065 -#define _GUARD_KEYS_VERSION_r22 1066 -#define _GUARD_KEYS_VERSION_r33 1067 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r03 1068 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r13 1069 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r23 1070 -#define _GUARD_LOAD_SUPER_ATTR_METHOD_r33 1071 -#define _GUARD_NOS_COMPACT_ASCII_r02 1072 -#define _GUARD_NOS_COMPACT_ASCII_r12 1073 -#define _GUARD_NOS_COMPACT_ASCII_r22 1074 -#define _GUARD_NOS_COMPACT_ASCII_r33 1075 -#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r03 1076 -#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r13 1077 -#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r23 1078 -#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r33 1079 -#define _GUARD_NOS_DICT_SUBSCRIPT_r02 1080 -#define _GUARD_NOS_DICT_SUBSCRIPT_r12 1081 -#define _GUARD_NOS_DICT_SUBSCRIPT_r22 1082 -#define _GUARD_NOS_DICT_SUBSCRIPT_r33 1083 -#define _GUARD_NOS_FLOAT_r02 1084 -#define _GUARD_NOS_FLOAT_r12 1085 -#define _GUARD_NOS_FLOAT_r22 1086 -#define _GUARD_NOS_FLOAT_r33 1087 -#define _GUARD_NOS_INT_r02 1088 -#define _GUARD_NOS_INT_r12 1089 -#define _GUARD_NOS_INT_r22 1090 -#define _GUARD_NOS_INT_r33 1091 -#define _GUARD_NOS_ITER_VIRTUAL_r02 1092 -#define _GUARD_NOS_ITER_VIRTUAL_r12 1093 -#define _GUARD_NOS_ITER_VIRTUAL_r22 1094 -#define _GUARD_NOS_ITER_VIRTUAL_r33 1095 -#define _GUARD_NOS_LIST_r02 1096 -#define _GUARD_NOS_LIST_r12 1097 -#define _GUARD_NOS_LIST_r22 1098 -#define _GUARD_NOS_LIST_r33 1099 -#define _GUARD_NOS_NOT_NULL_r02 1100 -#define _GUARD_NOS_NOT_NULL_r12 1101 -#define _GUARD_NOS_NOT_NULL_r22 1102 -#define _GUARD_NOS_NOT_NULL_r33 1103 -#define _GUARD_NOS_NULL_r02 1104 -#define _GUARD_NOS_NULL_r12 1105 -#define _GUARD_NOS_NULL_r22 1106 -#define _GUARD_NOS_NULL_r33 1107 -#define _GUARD_NOS_OVERFLOWED_r02 1108 -#define _GUARD_NOS_OVERFLOWED_r12 1109 -#define _GUARD_NOS_OVERFLOWED_r22 1110 -#define _GUARD_NOS_OVERFLOWED_r33 1111 -#define _GUARD_NOS_TUPLE_r02 1112 -#define _GUARD_NOS_TUPLE_r12 1113 -#define _GUARD_NOS_TUPLE_r22 1114 -#define _GUARD_NOS_TUPLE_r33 1115 -#define _GUARD_NOS_TYPE_VERSION_r02 1116 -#define _GUARD_NOS_TYPE_VERSION_r12 1117 -#define _GUARD_NOS_TYPE_VERSION_r22 1118 -#define _GUARD_NOS_TYPE_VERSION_r33 1119 -#define _GUARD_NOS_UNICODE_r02 1120 -#define _GUARD_NOS_UNICODE_r12 1121 -#define _GUARD_NOS_UNICODE_r22 1122 -#define _GUARD_NOS_UNICODE_r33 1123 -#define _GUARD_NOT_EXHAUSTED_LIST_r02 1124 -#define _GUARD_NOT_EXHAUSTED_LIST_r12 1125 -#define _GUARD_NOT_EXHAUSTED_LIST_r22 1126 -#define _GUARD_NOT_EXHAUSTED_LIST_r33 1127 -#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1128 -#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1129 -#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1130 -#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1131 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1132 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1133 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1134 -#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1135 -#define _GUARD_THIRD_NULL_r03 1136 -#define _GUARD_THIRD_NULL_r13 1137 -#define _GUARD_THIRD_NULL_r23 1138 -#define _GUARD_THIRD_NULL_r33 1139 -#define _GUARD_TOS_ANY_DICT_r01 1140 -#define _GUARD_TOS_ANY_DICT_r11 1141 -#define _GUARD_TOS_ANY_DICT_r22 1142 -#define _GUARD_TOS_ANY_DICT_r33 1143 -#define _GUARD_TOS_ANY_SET_r01 1144 -#define _GUARD_TOS_ANY_SET_r11 1145 -#define _GUARD_TOS_ANY_SET_r22 1146 -#define _GUARD_TOS_ANY_SET_r33 1147 -#define _GUARD_TOS_DICT_r01 1148 -#define _GUARD_TOS_DICT_r11 1149 -#define _GUARD_TOS_DICT_r22 1150 -#define _GUARD_TOS_DICT_r33 1151 -#define _GUARD_TOS_FLOAT_r01 1152 -#define _GUARD_TOS_FLOAT_r11 1153 -#define _GUARD_TOS_FLOAT_r22 1154 -#define _GUARD_TOS_FLOAT_r33 1155 -#define _GUARD_TOS_FROZENDICT_r01 1156 -#define _GUARD_TOS_FROZENDICT_r11 1157 -#define _GUARD_TOS_FROZENDICT_r22 1158 -#define _GUARD_TOS_FROZENDICT_r33 1159 -#define _GUARD_TOS_FROZENSET_r01 1160 -#define _GUARD_TOS_FROZENSET_r11 1161 -#define _GUARD_TOS_FROZENSET_r22 1162 -#define _GUARD_TOS_FROZENSET_r33 1163 -#define _GUARD_TOS_INT_r01 1164 -#define _GUARD_TOS_INT_r11 1165 -#define _GUARD_TOS_INT_r22 1166 -#define _GUARD_TOS_INT_r33 1167 -#define _GUARD_TOS_IS_NONE_r01 1168 -#define _GUARD_TOS_IS_NONE_r11 1169 -#define _GUARD_TOS_IS_NONE_r22 1170 -#define _GUARD_TOS_IS_NONE_r33 1171 -#define _GUARD_TOS_LIST_r01 1172 -#define _GUARD_TOS_LIST_r11 1173 -#define _GUARD_TOS_LIST_r22 1174 -#define _GUARD_TOS_LIST_r33 1175 -#define _GUARD_TOS_NOT_NULL_r01 1176 -#define _GUARD_TOS_NOT_NULL_r11 1177 -#define _GUARD_TOS_NOT_NULL_r22 1178 -#define _GUARD_TOS_NOT_NULL_r33 1179 -#define _GUARD_TOS_OVERFLOWED_r01 1180 -#define _GUARD_TOS_OVERFLOWED_r11 1181 -#define _GUARD_TOS_OVERFLOWED_r22 1182 -#define _GUARD_TOS_OVERFLOWED_r33 1183 -#define _GUARD_TOS_SET_r01 1184 -#define _GUARD_TOS_SET_r11 1185 -#define _GUARD_TOS_SET_r22 1186 -#define _GUARD_TOS_SET_r33 1187 -#define _GUARD_TOS_SLICE_r01 1188 -#define _GUARD_TOS_SLICE_r11 1189 -#define _GUARD_TOS_SLICE_r22 1190 -#define _GUARD_TOS_SLICE_r33 1191 -#define _GUARD_TOS_TUPLE_r01 1192 -#define _GUARD_TOS_TUPLE_r11 1193 -#define _GUARD_TOS_TUPLE_r22 1194 -#define _GUARD_TOS_TUPLE_r33 1195 -#define _GUARD_TOS_UNICODE_r01 1196 -#define _GUARD_TOS_UNICODE_r11 1197 -#define _GUARD_TOS_UNICODE_r22 1198 -#define _GUARD_TOS_UNICODE_r33 1199 -#define _GUARD_TYPE_r01 1200 -#define _GUARD_TYPE_r11 1201 -#define _GUARD_TYPE_r22 1202 -#define _GUARD_TYPE_r33 1203 -#define _GUARD_TYPE_ITER_r02 1204 -#define _GUARD_TYPE_ITER_r12 1205 -#define _GUARD_TYPE_ITER_r22 1206 -#define _GUARD_TYPE_ITER_r33 1207 -#define _GUARD_TYPE_VERSION_r01 1208 -#define _GUARD_TYPE_VERSION_r11 1209 -#define _GUARD_TYPE_VERSION_r22 1210 -#define _GUARD_TYPE_VERSION_r33 1211 -#define _GUARD_TYPE_VERSION_LOCKED_r01 1212 -#define _GUARD_TYPE_VERSION_LOCKED_r11 1213 -#define _GUARD_TYPE_VERSION_LOCKED_r22 1214 -#define _GUARD_TYPE_VERSION_LOCKED_r33 1215 -#define _HANDLE_PENDING_AND_DEOPT_r00 1216 -#define _HANDLE_PENDING_AND_DEOPT_r10 1217 -#define _HANDLE_PENDING_AND_DEOPT_r20 1218 -#define _HANDLE_PENDING_AND_DEOPT_r30 1219 -#define _IMPORT_FROM_r12 1220 -#define _IMPORT_NAME_r21 1221 -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1222 -#define _INIT_CALL_PY_EXACT_ARGS_r01 1223 -#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1224 -#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1225 -#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1226 -#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1227 -#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1228 -#define _INSERT_NULL_r10 1229 -#define _INSTRUMENTED_FOR_ITER_r23 1230 -#define _INSTRUMENTED_INSTRUCTION_r00 1231 -#define _INSTRUMENTED_JUMP_FORWARD_r00 1232 -#define _INSTRUMENTED_JUMP_FORWARD_r11 1233 -#define _INSTRUMENTED_JUMP_FORWARD_r22 1234 -#define _INSTRUMENTED_JUMP_FORWARD_r33 1235 -#define _INSTRUMENTED_LINE_r00 1236 -#define _INSTRUMENTED_NOT_TAKEN_r00 1237 -#define _INSTRUMENTED_NOT_TAKEN_r11 1238 -#define _INSTRUMENTED_NOT_TAKEN_r22 1239 -#define _INSTRUMENTED_NOT_TAKEN_r33 1240 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1241 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1242 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1243 -#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1244 -#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1245 -#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1246 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1247 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1248 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1249 -#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1250 -#define _IS_NONE_r11 1251 -#define _IS_OP_r03 1252 -#define _IS_OP_r13 1253 -#define _IS_OP_r23 1254 -#define _ITER_CHECK_LIST_r02 1255 -#define _ITER_CHECK_LIST_r12 1256 -#define _ITER_CHECK_LIST_r22 1257 -#define _ITER_CHECK_LIST_r33 1258 -#define _ITER_CHECK_RANGE_r02 1259 -#define _ITER_CHECK_RANGE_r12 1260 -#define _ITER_CHECK_RANGE_r22 1261 -#define _ITER_CHECK_RANGE_r33 1262 -#define _ITER_CHECK_TUPLE_r02 1263 -#define _ITER_CHECK_TUPLE_r12 1264 -#define _ITER_CHECK_TUPLE_r22 1265 -#define _ITER_CHECK_TUPLE_r33 1266 -#define _ITER_JUMP_LIST_r02 1267 -#define _ITER_JUMP_LIST_r12 1268 -#define _ITER_JUMP_LIST_r22 1269 -#define _ITER_JUMP_LIST_r33 1270 -#define _ITER_JUMP_RANGE_r02 1271 -#define _ITER_JUMP_RANGE_r12 1272 -#define _ITER_JUMP_RANGE_r22 1273 -#define _ITER_JUMP_RANGE_r33 1274 -#define _ITER_JUMP_TUPLE_r02 1275 -#define _ITER_JUMP_TUPLE_r12 1276 -#define _ITER_JUMP_TUPLE_r22 1277 -#define _ITER_JUMP_TUPLE_r33 1278 -#define _ITER_NEXT_INLINE_r23 1279 -#define _ITER_NEXT_LIST_r23 1280 -#define _ITER_NEXT_LIST_TIER_TWO_r23 1281 -#define _ITER_NEXT_RANGE_r03 1282 -#define _ITER_NEXT_RANGE_r13 1283 -#define _ITER_NEXT_RANGE_r23 1284 -#define _ITER_NEXT_TUPLE_r03 1285 -#define _ITER_NEXT_TUPLE_r13 1286 -#define _ITER_NEXT_TUPLE_r23 1287 -#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1288 -#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1289 -#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1290 -#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1291 -#define _JUMP_TO_TOP_r00 1292 -#define _LIST_APPEND_r10 1293 -#define _LIST_EXTEND_r11 1294 -#define _LOAD_ATTR_r10 1295 -#define _LOAD_ATTR_CLASS_r11 1296 -#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 1297 -#define _LOAD_ATTR_INSTANCE_VALUE_r02 1298 -#define _LOAD_ATTR_INSTANCE_VALUE_r12 1299 -#define _LOAD_ATTR_INSTANCE_VALUE_r23 1300 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1301 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1302 -#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1303 -#define _LOAD_ATTR_METHOD_NO_DICT_r02 1304 -#define _LOAD_ATTR_METHOD_NO_DICT_r12 1305 -#define _LOAD_ATTR_METHOD_NO_DICT_r23 1306 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1307 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1308 -#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1309 -#define _LOAD_ATTR_MODULE_r12 1310 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1311 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1312 -#define _LOAD_ATTR_PROPERTY_FRAME_r01 1313 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1314 -#define _LOAD_ATTR_PROPERTY_FRAME_r22 1315 -#define _LOAD_ATTR_PROPERTY_FRAME_r33 1316 -#define _LOAD_ATTR_SLOT_r02 1317 -#define _LOAD_ATTR_SLOT_r12 1318 -#define _LOAD_ATTR_SLOT_r23 1319 -#define _LOAD_ATTR_WITH_HINT_r12 1320 -#define _LOAD_BUILD_CLASS_r01 1321 -#define _LOAD_BYTECODE_r00 1322 -#define _LOAD_COMMON_CONSTANT_r01 1323 -#define _LOAD_COMMON_CONSTANT_r12 1324 -#define _LOAD_COMMON_CONSTANT_r23 1325 -#define _LOAD_CONST_r01 1326 -#define _LOAD_CONST_r12 1327 -#define _LOAD_CONST_r23 1328 -#define _LOAD_CONST_INLINE_r01 1329 -#define _LOAD_CONST_INLINE_r12 1330 -#define _LOAD_CONST_INLINE_r23 1331 -#define _LOAD_CONST_INLINE_BORROW_r01 1332 -#define _LOAD_CONST_INLINE_BORROW_r12 1333 -#define _LOAD_CONST_INLINE_BORROW_r23 1334 -#define _LOAD_DEREF_r01 1335 -#define _LOAD_FAST_r01 1336 -#define _LOAD_FAST_r12 1337 -#define _LOAD_FAST_r23 1338 -#define _LOAD_FAST_0_r01 1339 -#define _LOAD_FAST_0_r12 1340 -#define _LOAD_FAST_0_r23 1341 -#define _LOAD_FAST_1_r01 1342 -#define _LOAD_FAST_1_r12 1343 -#define _LOAD_FAST_1_r23 1344 -#define _LOAD_FAST_2_r01 1345 -#define _LOAD_FAST_2_r12 1346 -#define _LOAD_FAST_2_r23 1347 -#define _LOAD_FAST_3_r01 1348 -#define _LOAD_FAST_3_r12 1349 -#define _LOAD_FAST_3_r23 1350 -#define _LOAD_FAST_4_r01 1351 -#define _LOAD_FAST_4_r12 1352 -#define _LOAD_FAST_4_r23 1353 -#define _LOAD_FAST_5_r01 1354 -#define _LOAD_FAST_5_r12 1355 -#define _LOAD_FAST_5_r23 1356 -#define _LOAD_FAST_6_r01 1357 -#define _LOAD_FAST_6_r12 1358 -#define _LOAD_FAST_6_r23 1359 -#define _LOAD_FAST_7_r01 1360 -#define _LOAD_FAST_7_r12 1361 -#define _LOAD_FAST_7_r23 1362 -#define _LOAD_FAST_AND_CLEAR_r01 1363 -#define _LOAD_FAST_AND_CLEAR_r12 1364 -#define _LOAD_FAST_AND_CLEAR_r23 1365 -#define _LOAD_FAST_BORROW_r01 1366 -#define _LOAD_FAST_BORROW_r12 1367 -#define _LOAD_FAST_BORROW_r23 1368 -#define _LOAD_FAST_BORROW_0_r01 1369 -#define _LOAD_FAST_BORROW_0_r12 1370 -#define _LOAD_FAST_BORROW_0_r23 1371 -#define _LOAD_FAST_BORROW_1_r01 1372 -#define _LOAD_FAST_BORROW_1_r12 1373 -#define _LOAD_FAST_BORROW_1_r23 1374 -#define _LOAD_FAST_BORROW_2_r01 1375 -#define _LOAD_FAST_BORROW_2_r12 1376 -#define _LOAD_FAST_BORROW_2_r23 1377 -#define _LOAD_FAST_BORROW_3_r01 1378 -#define _LOAD_FAST_BORROW_3_r12 1379 -#define _LOAD_FAST_BORROW_3_r23 1380 -#define _LOAD_FAST_BORROW_4_r01 1381 -#define _LOAD_FAST_BORROW_4_r12 1382 -#define _LOAD_FAST_BORROW_4_r23 1383 -#define _LOAD_FAST_BORROW_5_r01 1384 -#define _LOAD_FAST_BORROW_5_r12 1385 -#define _LOAD_FAST_BORROW_5_r23 1386 -#define _LOAD_FAST_BORROW_6_r01 1387 -#define _LOAD_FAST_BORROW_6_r12 1388 -#define _LOAD_FAST_BORROW_6_r23 1389 -#define _LOAD_FAST_BORROW_7_r01 1390 -#define _LOAD_FAST_BORROW_7_r12 1391 -#define _LOAD_FAST_BORROW_7_r23 1392 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1393 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1394 -#define _LOAD_FAST_CHECK_r01 1395 -#define _LOAD_FAST_CHECK_r12 1396 -#define _LOAD_FAST_CHECK_r23 1397 -#define _LOAD_FAST_LOAD_FAST_r02 1398 -#define _LOAD_FAST_LOAD_FAST_r13 1399 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1400 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1401 -#define _LOAD_GLOBAL_r00 1402 -#define _LOAD_GLOBAL_BUILTINS_r01 1403 -#define _LOAD_GLOBAL_MODULE_r01 1404 -#define _LOAD_LOCALS_r01 1405 -#define _LOAD_LOCALS_r12 1406 -#define _LOAD_LOCALS_r23 1407 -#define _LOAD_NAME_r01 1408 -#define _LOAD_SMALL_INT_r01 1409 -#define _LOAD_SMALL_INT_r12 1410 -#define _LOAD_SMALL_INT_r23 1411 -#define _LOAD_SMALL_INT_0_r01 1412 -#define _LOAD_SMALL_INT_0_r12 1413 -#define _LOAD_SMALL_INT_0_r23 1414 -#define _LOAD_SMALL_INT_1_r01 1415 -#define _LOAD_SMALL_INT_1_r12 1416 -#define _LOAD_SMALL_INT_1_r23 1417 -#define _LOAD_SMALL_INT_2_r01 1418 -#define _LOAD_SMALL_INT_2_r12 1419 -#define _LOAD_SMALL_INT_2_r23 1420 -#define _LOAD_SMALL_INT_3_r01 1421 -#define _LOAD_SMALL_INT_3_r12 1422 -#define _LOAD_SMALL_INT_3_r23 1423 -#define _LOAD_SPECIAL_r00 1424 -#define _LOAD_SUPER_ATTR_ATTR_r31 1425 -#define _LOAD_SUPER_ATTR_METHOD_r32 1426 -#define _LOCK_OBJECT_r01 1427 -#define _LOCK_OBJECT_r11 1428 -#define _LOCK_OBJECT_r22 1429 -#define _LOCK_OBJECT_r33 1430 -#define _MAKE_CALLARGS_A_TUPLE_r33 1431 -#define _MAKE_CELL_r00 1432 -#define _MAKE_FUNCTION_r12 1433 -#define _MAKE_HEAP_SAFE_r01 1434 -#define _MAKE_HEAP_SAFE_r11 1435 -#define _MAKE_HEAP_SAFE_r22 1436 -#define _MAKE_HEAP_SAFE_r33 1437 -#define _MAKE_WARM_r00 1438 -#define _MAKE_WARM_r11 1439 -#define _MAKE_WARM_r22 1440 -#define _MAKE_WARM_r33 1441 -#define _MAP_ADD_r20 1442 -#define _MATCH_CLASS_r33 1443 -#define _MATCH_KEYS_r23 1444 -#define _MATCH_MAPPING_r02 1445 -#define _MATCH_MAPPING_r12 1446 -#define _MATCH_MAPPING_r23 1447 -#define _MATCH_SEQUENCE_r02 1448 -#define _MATCH_SEQUENCE_r12 1449 -#define _MATCH_SEQUENCE_r23 1450 -#define _MAYBE_EXPAND_METHOD_r00 1451 -#define _MAYBE_EXPAND_METHOD_KW_r11 1452 -#define _MONITOR_CALL_r00 1453 -#define _MONITOR_CALL_KW_r11 1454 -#define _MONITOR_JUMP_BACKWARD_r00 1455 -#define _MONITOR_JUMP_BACKWARD_r11 1456 -#define _MONITOR_JUMP_BACKWARD_r22 1457 -#define _MONITOR_JUMP_BACKWARD_r33 1458 -#define _MONITOR_RESUME_r00 1459 -#define _NOP_r00 1460 -#define _NOP_r11 1461 -#define _NOP_r22 1462 -#define _NOP_r33 1463 -#define _POP_EXCEPT_r10 1464 -#define _POP_ITER_r20 1465 -#define _POP_JUMP_IF_FALSE_r00 1466 -#define _POP_JUMP_IF_FALSE_r10 1467 -#define _POP_JUMP_IF_FALSE_r21 1468 -#define _POP_JUMP_IF_FALSE_r32 1469 -#define _POP_JUMP_IF_TRUE_r00 1470 -#define _POP_JUMP_IF_TRUE_r10 1471 -#define _POP_JUMP_IF_TRUE_r21 1472 -#define _POP_JUMP_IF_TRUE_r32 1473 -#define _POP_TOP_r10 1474 -#define _POP_TOP_FLOAT_r00 1475 -#define _POP_TOP_FLOAT_r10 1476 -#define _POP_TOP_FLOAT_r21 1477 -#define _POP_TOP_FLOAT_r32 1478 -#define _POP_TOP_INT_r00 1479 -#define _POP_TOP_INT_r10 1480 -#define _POP_TOP_INT_r21 1481 -#define _POP_TOP_INT_r32 1482 -#define _POP_TOP_NOP_r00 1483 -#define _POP_TOP_NOP_r10 1484 -#define _POP_TOP_NOP_r21 1485 -#define _POP_TOP_NOP_r32 1486 -#define _POP_TOP_OPARG_r00 1487 -#define _POP_TOP_UNICODE_r00 1488 -#define _POP_TOP_UNICODE_r10 1489 -#define _POP_TOP_UNICODE_r21 1490 -#define _POP_TOP_UNICODE_r32 1491 -#define _PUSH_EXC_INFO_r02 1492 -#define _PUSH_EXC_INFO_r12 1493 -#define _PUSH_EXC_INFO_r23 1494 -#define _PUSH_FRAME_r10 1495 -#define _PUSH_NULL_r01 1496 -#define _PUSH_NULL_r12 1497 -#define _PUSH_NULL_r23 1498 -#define _PUSH_NULL_CONDITIONAL_r00 1499 -#define _PUSH_TAGGED_ZERO_r01 1500 -#define _PUSH_TAGGED_ZERO_r12 1501 -#define _PUSH_TAGGED_ZERO_r23 1502 -#define _PY_FRAME_EX_r31 1503 -#define _PY_FRAME_GENERAL_r01 1504 -#define _PY_FRAME_KW_r11 1505 -#define _REPLACE_WITH_TRUE_r02 1506 -#define _REPLACE_WITH_TRUE_r12 1507 -#define _REPLACE_WITH_TRUE_r23 1508 -#define _RESUME_CHECK_r00 1509 -#define _RESUME_CHECK_r11 1510 -#define _RESUME_CHECK_r22 1511 -#define _RESUME_CHECK_r33 1512 -#define _RETURN_GENERATOR_r01 1513 -#define _RETURN_VALUE_r11 1514 -#define _RROT_3_r03 1515 -#define _RROT_3_r13 1516 -#define _RROT_3_r23 1517 -#define _RROT_3_r33 1518 -#define _SAVE_RETURN_OFFSET_r00 1519 -#define _SAVE_RETURN_OFFSET_r11 1520 -#define _SAVE_RETURN_OFFSET_r22 1521 -#define _SAVE_RETURN_OFFSET_r33 1522 -#define _SEND_ASYNC_GEN_r33 1523 -#define _SEND_ASYNC_GEN_TIER_TWO_r33 1524 -#define _SEND_GEN_FRAME_r33 1525 -#define _SEND_VIRTUAL_r33 1526 -#define _SEND_VIRTUAL_TIER_TWO_r03 1527 -#define _SEND_VIRTUAL_TIER_TWO_r13 1528 -#define _SEND_VIRTUAL_TIER_TWO_r23 1529 -#define _SEND_VIRTUAL_TIER_TWO_r33 1530 -#define _SETUP_ANNOTATIONS_r00 1531 -#define _SET_ADD_r10 1532 -#define _SET_FUNCTION_ATTRIBUTE_r01 1533 -#define _SET_FUNCTION_ATTRIBUTE_r11 1534 -#define _SET_FUNCTION_ATTRIBUTE_r21 1535 -#define _SET_FUNCTION_ATTRIBUTE_r32 1536 -#define _SET_IP_r00 1537 -#define _SET_IP_r11 1538 -#define _SET_IP_r22 1539 -#define _SET_IP_r33 1540 -#define _SET_UPDATE_r11 1541 -#define _SPILL_OR_RELOAD_r01 1542 -#define _SPILL_OR_RELOAD_r02 1543 -#define _SPILL_OR_RELOAD_r03 1544 -#define _SPILL_OR_RELOAD_r10 1545 -#define _SPILL_OR_RELOAD_r12 1546 -#define _SPILL_OR_RELOAD_r13 1547 -#define _SPILL_OR_RELOAD_r20 1548 -#define _SPILL_OR_RELOAD_r21 1549 -#define _SPILL_OR_RELOAD_r23 1550 -#define _SPILL_OR_RELOAD_r30 1551 -#define _SPILL_OR_RELOAD_r31 1552 -#define _SPILL_OR_RELOAD_r32 1553 -#define _START_EXECUTOR_r00 1554 -#define _STORE_ATTR_r20 1555 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1556 -#define _STORE_ATTR_SLOT_r21 1557 -#define _STORE_ATTR_WITH_HINT_r21 1558 -#define _STORE_DEREF_r10 1559 -#define _STORE_FAST_LOAD_FAST_r11 1560 -#define _STORE_FAST_STORE_FAST_r20 1561 -#define _STORE_GLOBAL_r10 1562 -#define _STORE_NAME_r10 1563 -#define _STORE_SLICE_r30 1564 -#define _STORE_SUBSCR_r30 1565 -#define _STORE_SUBSCR_DICT_r31 1566 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1567 -#define _STORE_SUBSCR_LIST_INT_r32 1568 -#define _SWAP_r11 1569 -#define _SWAP_2_r02 1570 -#define _SWAP_2_r12 1571 -#define _SWAP_2_r22 1572 -#define _SWAP_2_r33 1573 -#define _SWAP_3_r03 1574 -#define _SWAP_3_r13 1575 -#define _SWAP_3_r23 1576 -#define _SWAP_3_r33 1577 -#define _SWAP_FAST_r01 1578 -#define _SWAP_FAST_r11 1579 -#define _SWAP_FAST_r22 1580 -#define _SWAP_FAST_r33 1581 -#define _SWAP_FAST_0_r01 1582 -#define _SWAP_FAST_0_r11 1583 -#define _SWAP_FAST_0_r22 1584 -#define _SWAP_FAST_0_r33 1585 -#define _SWAP_FAST_1_r01 1586 -#define _SWAP_FAST_1_r11 1587 -#define _SWAP_FAST_1_r22 1588 -#define _SWAP_FAST_1_r33 1589 -#define _SWAP_FAST_2_r01 1590 -#define _SWAP_FAST_2_r11 1591 -#define _SWAP_FAST_2_r22 1592 -#define _SWAP_FAST_2_r33 1593 -#define _SWAP_FAST_3_r01 1594 -#define _SWAP_FAST_3_r11 1595 -#define _SWAP_FAST_3_r22 1596 -#define _SWAP_FAST_3_r33 1597 -#define _SWAP_FAST_4_r01 1598 -#define _SWAP_FAST_4_r11 1599 -#define _SWAP_FAST_4_r22 1600 -#define _SWAP_FAST_4_r33 1601 -#define _SWAP_FAST_5_r01 1602 -#define _SWAP_FAST_5_r11 1603 -#define _SWAP_FAST_5_r22 1604 -#define _SWAP_FAST_5_r33 1605 -#define _SWAP_FAST_6_r01 1606 -#define _SWAP_FAST_6_r11 1607 -#define _SWAP_FAST_6_r22 1608 -#define _SWAP_FAST_6_r33 1609 -#define _SWAP_FAST_7_r01 1610 -#define _SWAP_FAST_7_r11 1611 -#define _SWAP_FAST_7_r22 1612 -#define _SWAP_FAST_7_r33 1613 -#define _TIER2_RESUME_CHECK_r00 1614 -#define _TIER2_RESUME_CHECK_r11 1615 -#define _TIER2_RESUME_CHECK_r22 1616 -#define _TIER2_RESUME_CHECK_r33 1617 -#define _TO_BOOL_r11 1618 -#define _TO_BOOL_BOOL_r01 1619 -#define _TO_BOOL_BOOL_r11 1620 -#define _TO_BOOL_BOOL_r22 1621 -#define _TO_BOOL_BOOL_r33 1622 -#define _TO_BOOL_INT_r02 1623 -#define _TO_BOOL_INT_r12 1624 -#define _TO_BOOL_INT_r23 1625 -#define _TO_BOOL_LIST_r02 1626 -#define _TO_BOOL_LIST_r12 1627 -#define _TO_BOOL_LIST_r23 1628 -#define _TO_BOOL_NONE_r01 1629 -#define _TO_BOOL_NONE_r11 1630 -#define _TO_BOOL_NONE_r22 1631 -#define _TO_BOOL_NONE_r33 1632 -#define _TO_BOOL_STR_r02 1633 -#define _TO_BOOL_STR_r12 1634 -#define _TO_BOOL_STR_r23 1635 -#define _TRACE_RECORD_r00 1636 -#define _UNARY_INVERT_r12 1637 -#define _UNARY_NEGATIVE_r12 1638 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1639 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1640 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1641 -#define _UNARY_NOT_r01 1642 -#define _UNARY_NOT_r11 1643 -#define _UNARY_NOT_r22 1644 -#define _UNARY_NOT_r33 1645 -#define _UNPACK_EX_r10 1646 -#define _UNPACK_SEQUENCE_r10 1647 -#define _UNPACK_SEQUENCE_LIST_r10 1648 -#define _UNPACK_SEQUENCE_TUPLE_r10 1649 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1650 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1651 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1652 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1653 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1654 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1655 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1656 -#define _WITH_EXCEPT_START_r33 1657 -#define _YIELD_VALUE_r11 1658 -#define MAX_UOP_REGS_ID 1658 +#define _YIELD_VALUE 653 +#define MAX_UOP_ID 653 +#define _ALLOCATE_OBJECT_r00 654 +#define _BINARY_OP_r23 655 +#define _BINARY_OP_ADD_FLOAT_r03 656 +#define _BINARY_OP_ADD_FLOAT_r13 657 +#define _BINARY_OP_ADD_FLOAT_r23 658 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r03 659 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r13 660 +#define _BINARY_OP_ADD_FLOAT_INPLACE_r23 661 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r03 662 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r13 663 +#define _BINARY_OP_ADD_FLOAT_INPLACE_RIGHT_r23 664 +#define _BINARY_OP_ADD_INT_r03 665 +#define _BINARY_OP_ADD_INT_r13 666 +#define _BINARY_OP_ADD_INT_r23 667 +#define _BINARY_OP_ADD_INT_INPLACE_r03 668 +#define _BINARY_OP_ADD_INT_INPLACE_r13 669 +#define _BINARY_OP_ADD_INT_INPLACE_r23 670 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r03 671 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r13 672 +#define _BINARY_OP_ADD_INT_INPLACE_RIGHT_r23 673 +#define _BINARY_OP_ADD_UNICODE_r03 674 +#define _BINARY_OP_ADD_UNICODE_r13 675 +#define _BINARY_OP_ADD_UNICODE_r23 676 +#define _BINARY_OP_EXTEND_r23 677 +#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 678 +#define _BINARY_OP_MULTIPLY_FLOAT_r03 679 +#define _BINARY_OP_MULTIPLY_FLOAT_r13 680 +#define _BINARY_OP_MULTIPLY_FLOAT_r23 681 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r03 682 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r13 683 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_r23 684 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r03 685 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r13 686 +#define _BINARY_OP_MULTIPLY_FLOAT_INPLACE_RIGHT_r23 687 +#define _BINARY_OP_MULTIPLY_INT_r03 688 +#define _BINARY_OP_MULTIPLY_INT_r13 689 +#define _BINARY_OP_MULTIPLY_INT_r23 690 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r03 691 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r13 692 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_r23 693 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r03 694 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r13 695 +#define _BINARY_OP_MULTIPLY_INT_INPLACE_RIGHT_r23 696 +#define _BINARY_OP_SUBSCR_CHECK_FUNC_r23 697 +#define _BINARY_OP_SUBSCR_DICT_r23 698 +#define _BINARY_OP_SUBSCR_DICT_KNOWN_HASH_r23 699 +#define _BINARY_OP_SUBSCR_INIT_CALL_r01 700 +#define _BINARY_OP_SUBSCR_INIT_CALL_r11 701 +#define _BINARY_OP_SUBSCR_INIT_CALL_r21 702 +#define _BINARY_OP_SUBSCR_INIT_CALL_r31 703 +#define _BINARY_OP_SUBSCR_LIST_INT_r23 704 +#define _BINARY_OP_SUBSCR_LIST_SLICE_r23 705 +#define _BINARY_OP_SUBSCR_STR_INT_r23 706 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r03 707 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r13 708 +#define _BINARY_OP_SUBSCR_TUPLE_INT_r23 709 +#define _BINARY_OP_SUBSCR_USTR_INT_r23 710 +#define _BINARY_OP_SUBTRACT_FLOAT_r03 711 +#define _BINARY_OP_SUBTRACT_FLOAT_r13 712 +#define _BINARY_OP_SUBTRACT_FLOAT_r23 713 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r03 714 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r13 715 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_r23 716 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r03 717 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r13 718 +#define _BINARY_OP_SUBTRACT_FLOAT_INPLACE_RIGHT_r23 719 +#define _BINARY_OP_SUBTRACT_INT_r03 720 +#define _BINARY_OP_SUBTRACT_INT_r13 721 +#define _BINARY_OP_SUBTRACT_INT_r23 722 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r03 723 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r13 724 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_r23 725 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r03 726 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r13 727 +#define _BINARY_OP_SUBTRACT_INT_INPLACE_RIGHT_r23 728 +#define _BINARY_OP_TRUEDIV_FLOAT_r23 729 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r03 730 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r13 731 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_r23 732 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r03 733 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r13 734 +#define _BINARY_OP_TRUEDIV_FLOAT_INPLACE_RIGHT_r23 735 +#define _BINARY_SLICE_r31 736 +#define _BUILD_INTERPOLATION_r01 737 +#define _BUILD_LIST_r01 738 +#define _BUILD_MAP_r01 739 +#define _BUILD_SET_r01 740 +#define _BUILD_SLICE_r01 741 +#define _BUILD_STRING_r01 742 +#define _BUILD_TEMPLATE_r21 743 +#define _BUILD_TUPLE_r01 744 +#define _CALL_BUILTIN_CLASS_r00 745 +#define _CALL_BUILTIN_FAST_r00 746 +#define _CALL_BUILTIN_FAST_WITH_KEYWORDS_r00 747 +#define _CALL_BUILTIN_O_r03 748 +#define _CALL_FUNCTION_EX_NON_PY_GENERAL_r31 749 +#define _CALL_INTRINSIC_1_r12 750 +#define _CALL_INTRINSIC_2_r23 751 +#define _CALL_ISINSTANCE_r31 752 +#define _CALL_KW_NON_PY_r11 753 +#define _CALL_LEN_r33 754 +#define _CALL_LIST_APPEND_r03 755 +#define _CALL_LIST_APPEND_r13 756 +#define _CALL_LIST_APPEND_r23 757 +#define _CALL_LIST_APPEND_r33 758 +#define _CALL_METHOD_DESCRIPTOR_FAST_r00 759 +#define _CALL_METHOD_DESCRIPTOR_FAST_INLINE_r00 760 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 761 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_INLINE_r00 762 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_r03 763 +#define _CALL_METHOD_DESCRIPTOR_NOARGS_INLINE_r03 764 +#define _CALL_METHOD_DESCRIPTOR_O_r03 765 +#define _CALL_METHOD_DESCRIPTOR_O_INLINE_r03 766 +#define _CALL_NON_PY_GENERAL_r01 767 +#define _CALL_STR_1_r32 768 +#define _CALL_TUPLE_1_r32 769 +#define _CALL_TYPE_1_r02 770 +#define _CALL_TYPE_1_r12 771 +#define _CALL_TYPE_1_r22 772 +#define _CALL_TYPE_1_r32 773 +#define _CHECK_ATTR_CLASS_r01 774 +#define _CHECK_ATTR_CLASS_r11 775 +#define _CHECK_ATTR_CLASS_r22 776 +#define _CHECK_ATTR_CLASS_r33 777 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r01 778 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r11 779 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r22 780 +#define _CHECK_ATTR_METHOD_LAZY_DICT_r33 781 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS_r00 782 +#define _CHECK_EG_MATCH_r22 783 +#define _CHECK_EXC_MATCH_r22 784 +#define _CHECK_FUNCTION_EXACT_ARGS_r00 785 +#define _CHECK_FUNCTION_VERSION_r00 786 +#define _CHECK_FUNCTION_VERSION_INLINE_r00 787 +#define _CHECK_FUNCTION_VERSION_INLINE_r11 788 +#define _CHECK_FUNCTION_VERSION_INLINE_r22 789 +#define _CHECK_FUNCTION_VERSION_INLINE_r33 790 +#define _CHECK_FUNCTION_VERSION_KW_r11 791 +#define _CHECK_IS_NOT_PY_CALLABLE_r00 792 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r03 793 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r13 794 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r23 795 +#define _CHECK_IS_NOT_PY_CALLABLE_EX_r33 796 +#define _CHECK_IS_NOT_PY_CALLABLE_KW_r11 797 +#define _CHECK_IS_PY_CALLABLE_EX_r03 798 +#define _CHECK_IS_PY_CALLABLE_EX_r13 799 +#define _CHECK_IS_PY_CALLABLE_EX_r23 800 +#define _CHECK_IS_PY_CALLABLE_EX_r33 801 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r01 802 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r11 803 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r22 804 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES_r33 805 +#define _CHECK_METHOD_VERSION_r00 806 +#define _CHECK_METHOD_VERSION_KW_r11 807 +#define _CHECK_OBJECT_r00 808 +#define _CHECK_PEP_523_r00 809 +#define _CHECK_PEP_523_r11 810 +#define _CHECK_PEP_523_r22 811 +#define _CHECK_PEP_523_r33 812 +#define _CHECK_PERIODIC_r00 813 +#define _CHECK_PERIODIC_AT_END_r00 814 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM_r00 815 +#define _CHECK_RECURSION_LIMIT_r00 816 +#define _CHECK_RECURSION_LIMIT_r11 817 +#define _CHECK_RECURSION_LIMIT_r22 818 +#define _CHECK_RECURSION_LIMIT_r33 819 +#define _CHECK_RECURSION_REMAINING_r00 820 +#define _CHECK_RECURSION_REMAINING_r11 821 +#define _CHECK_RECURSION_REMAINING_r22 822 +#define _CHECK_RECURSION_REMAINING_r33 823 +#define _CHECK_STACK_SPACE_r00 824 +#define _CHECK_STACK_SPACE_OPERAND_r00 825 +#define _CHECK_STACK_SPACE_OPERAND_r11 826 +#define _CHECK_STACK_SPACE_OPERAND_r22 827 +#define _CHECK_STACK_SPACE_OPERAND_r33 828 +#define _CHECK_VALIDITY_r00 829 +#define _CHECK_VALIDITY_r11 830 +#define _CHECK_VALIDITY_r22 831 +#define _CHECK_VALIDITY_r33 832 +#define _COLD_DYNAMIC_EXIT_r00 833 +#define _COLD_EXIT_r00 834 +#define _COMPARE_OP_r21 835 +#define _COMPARE_OP_FLOAT_r03 836 +#define _COMPARE_OP_FLOAT_r13 837 +#define _COMPARE_OP_FLOAT_r23 838 +#define _COMPARE_OP_INT_r23 839 +#define _COMPARE_OP_STR_r23 840 +#define _CONTAINS_OP_r23 841 +#define _CONTAINS_OP_DICT_r23 842 +#define _CONTAINS_OP_SET_r23 843 +#define _CONVERT_VALUE_r11 844 +#define _COPY_r01 845 +#define _COPY_1_r02 846 +#define _COPY_1_r12 847 +#define _COPY_1_r23 848 +#define _COPY_2_r03 849 +#define _COPY_2_r13 850 +#define _COPY_2_r23 851 +#define _COPY_3_r03 852 +#define _COPY_3_r13 853 +#define _COPY_3_r23 854 +#define _COPY_3_r33 855 +#define _COPY_FREE_VARS_r00 856 +#define _COPY_FREE_VARS_r11 857 +#define _COPY_FREE_VARS_r22 858 +#define _COPY_FREE_VARS_r33 859 +#define _CREATE_INIT_FRAME_r01 860 +#define _DELETE_ATTR_r10 861 +#define _DELETE_DEREF_r00 862 +#define _DELETE_FAST_r00 863 +#define _DELETE_GLOBAL_r00 864 +#define _DELETE_NAME_r00 865 +#define _DELETE_SUBSCR_r20 866 +#define _DEOPT_r00 867 +#define _DEOPT_r10 868 +#define _DEOPT_r20 869 +#define _DEOPT_r30 870 +#define _DICT_MERGE_r11 871 +#define _DICT_UPDATE_r11 872 +#define _DO_CALL_r01 873 +#define _DO_CALL_FUNCTION_EX_r31 874 +#define _DO_CALL_KW_r11 875 +#define _DYNAMIC_EXIT_r00 876 +#define _DYNAMIC_EXIT_r10 877 +#define _DYNAMIC_EXIT_r20 878 +#define _DYNAMIC_EXIT_r30 879 +#define _END_FOR_r10 880 +#define _END_SEND_r31 881 +#define _ERROR_POP_N_r00 882 +#define _EXIT_INIT_CHECK_r10 883 +#define _EXIT_TRACE_r00 884 +#define _EXIT_TRACE_r10 885 +#define _EXIT_TRACE_r20 886 +#define _EXIT_TRACE_r30 887 +#define _EXPAND_METHOD_r00 888 +#define _EXPAND_METHOD_KW_r11 889 +#define _FATAL_ERROR_r00 890 +#define _FATAL_ERROR_r11 891 +#define _FATAL_ERROR_r22 892 +#define _FATAL_ERROR_r33 893 +#define _FORMAT_SIMPLE_r11 894 +#define _FORMAT_WITH_SPEC_r21 895 +#define _FOR_ITER_r23 896 +#define _FOR_ITER_GEN_FRAME_r03 897 +#define _FOR_ITER_GEN_FRAME_r13 898 +#define _FOR_ITER_GEN_FRAME_r23 899 +#define _FOR_ITER_TIER_TWO_r23 900 +#define _FOR_ITER_VIRTUAL_r23 901 +#define _FOR_ITER_VIRTUAL_TIER_TWO_r23 902 +#define _GET_AITER_r11 903 +#define _GET_ANEXT_r12 904 +#define _GET_AWAITABLE_r11 905 +#define _GET_ITER_r12 906 +#define _GET_ITER_TRAD_r12 907 +#define _GET_LEN_r12 908 +#define _GUARD_3OS_ASYNC_GEN_ASEND_r03 909 +#define _GUARD_3OS_ASYNC_GEN_ASEND_r13 910 +#define _GUARD_3OS_ASYNC_GEN_ASEND_r23 911 +#define _GUARD_3OS_ASYNC_GEN_ASEND_r33 912 +#define _GUARD_BINARY_OP_EXTEND_r22 913 +#define _GUARD_BINARY_OP_EXTEND_LHS_r02 914 +#define _GUARD_BINARY_OP_EXTEND_LHS_r12 915 +#define _GUARD_BINARY_OP_EXTEND_LHS_r22 916 +#define _GUARD_BINARY_OP_EXTEND_LHS_r33 917 +#define _GUARD_BINARY_OP_EXTEND_RHS_r02 918 +#define _GUARD_BINARY_OP_EXTEND_RHS_r12 919 +#define _GUARD_BINARY_OP_EXTEND_RHS_r22 920 +#define _GUARD_BINARY_OP_EXTEND_RHS_r33 921 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r02 922 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r12 923 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r22 924 +#define _GUARD_BINARY_OP_SUBSCR_TUPLE_INT_BOUNDS_r33 925 +#define _GUARD_BIT_IS_SET_POP_r00 926 +#define _GUARD_BIT_IS_SET_POP_r10 927 +#define _GUARD_BIT_IS_SET_POP_r21 928 +#define _GUARD_BIT_IS_SET_POP_r32 929 +#define _GUARD_BIT_IS_SET_POP_4_r00 930 +#define _GUARD_BIT_IS_SET_POP_4_r10 931 +#define _GUARD_BIT_IS_SET_POP_4_r21 932 +#define _GUARD_BIT_IS_SET_POP_4_r32 933 +#define _GUARD_BIT_IS_SET_POP_5_r00 934 +#define _GUARD_BIT_IS_SET_POP_5_r10 935 +#define _GUARD_BIT_IS_SET_POP_5_r21 936 +#define _GUARD_BIT_IS_SET_POP_5_r32 937 +#define _GUARD_BIT_IS_SET_POP_6_r00 938 +#define _GUARD_BIT_IS_SET_POP_6_r10 939 +#define _GUARD_BIT_IS_SET_POP_6_r21 940 +#define _GUARD_BIT_IS_SET_POP_6_r32 941 +#define _GUARD_BIT_IS_SET_POP_7_r00 942 +#define _GUARD_BIT_IS_SET_POP_7_r10 943 +#define _GUARD_BIT_IS_SET_POP_7_r21 944 +#define _GUARD_BIT_IS_SET_POP_7_r32 945 +#define _GUARD_BIT_IS_UNSET_POP_r00 946 +#define _GUARD_BIT_IS_UNSET_POP_r10 947 +#define _GUARD_BIT_IS_UNSET_POP_r21 948 +#define _GUARD_BIT_IS_UNSET_POP_r32 949 +#define _GUARD_BIT_IS_UNSET_POP_4_r00 950 +#define _GUARD_BIT_IS_UNSET_POP_4_r10 951 +#define _GUARD_BIT_IS_UNSET_POP_4_r21 952 +#define _GUARD_BIT_IS_UNSET_POP_4_r32 953 +#define _GUARD_BIT_IS_UNSET_POP_5_r00 954 +#define _GUARD_BIT_IS_UNSET_POP_5_r10 955 +#define _GUARD_BIT_IS_UNSET_POP_5_r21 956 +#define _GUARD_BIT_IS_UNSET_POP_5_r32 957 +#define _GUARD_BIT_IS_UNSET_POP_6_r00 958 +#define _GUARD_BIT_IS_UNSET_POP_6_r10 959 +#define _GUARD_BIT_IS_UNSET_POP_6_r21 960 +#define _GUARD_BIT_IS_UNSET_POP_6_r32 961 +#define _GUARD_BIT_IS_UNSET_POP_7_r00 962 +#define _GUARD_BIT_IS_UNSET_POP_7_r10 963 +#define _GUARD_BIT_IS_UNSET_POP_7_r21 964 +#define _GUARD_BIT_IS_UNSET_POP_7_r32 965 +#define _GUARD_CALLABLE_BUILTIN_CLASS_r00 966 +#define _GUARD_CALLABLE_BUILTIN_FAST_r00 967 +#define _GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS_r00 968 +#define _GUARD_CALLABLE_BUILTIN_O_r00 969 +#define _GUARD_CALLABLE_ISINSTANCE_r03 970 +#define _GUARD_CALLABLE_ISINSTANCE_r13 971 +#define _GUARD_CALLABLE_ISINSTANCE_r23 972 +#define _GUARD_CALLABLE_ISINSTANCE_r33 973 +#define _GUARD_CALLABLE_LEN_r03 974 +#define _GUARD_CALLABLE_LEN_r13 975 +#define _GUARD_CALLABLE_LEN_r23 976 +#define _GUARD_CALLABLE_LEN_r33 977 +#define _GUARD_CALLABLE_LIST_APPEND_r03 978 +#define _GUARD_CALLABLE_LIST_APPEND_r13 979 +#define _GUARD_CALLABLE_LIST_APPEND_r23 980 +#define _GUARD_CALLABLE_LIST_APPEND_r33 981 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_r00 982 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r00 983 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_NOARGS_r00 984 +#define _GUARD_CALLABLE_METHOD_DESCRIPTOR_O_r00 985 +#define _GUARD_CALLABLE_STR_1_r03 986 +#define _GUARD_CALLABLE_STR_1_r13 987 +#define _GUARD_CALLABLE_STR_1_r23 988 +#define _GUARD_CALLABLE_STR_1_r33 989 +#define _GUARD_CALLABLE_TUPLE_1_r03 990 +#define _GUARD_CALLABLE_TUPLE_1_r13 991 +#define _GUARD_CALLABLE_TUPLE_1_r23 992 +#define _GUARD_CALLABLE_TUPLE_1_r33 993 +#define _GUARD_CALLABLE_TYPE_1_r03 994 +#define _GUARD_CALLABLE_TYPE_1_r13 995 +#define _GUARD_CALLABLE_TYPE_1_r23 996 +#define _GUARD_CALLABLE_TYPE_1_r33 997 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r00 998 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r11 999 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r22 1000 +#define _GUARD_CODE_VERSION_RETURN_GENERATOR_r33 1001 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r00 1002 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r11 1003 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r22 1004 +#define _GUARD_CODE_VERSION_RETURN_VALUE_r33 1005 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r00 1006 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r11 1007 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r22 1008 +#define _GUARD_CODE_VERSION_YIELD_VALUE_r33 1009 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r00 1010 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r11 1011 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r22 1012 +#define _GUARD_CODE_VERSION__PUSH_FRAME_r33 1013 +#define _GUARD_DORV_NO_DICT_r01 1014 +#define _GUARD_DORV_NO_DICT_r11 1015 +#define _GUARD_DORV_NO_DICT_r22 1016 +#define _GUARD_DORV_NO_DICT_r33 1017 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r01 1018 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11 1019 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22 1020 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 1021 +#define _GUARD_GLOBALS_VERSION_r00 1022 +#define _GUARD_GLOBALS_VERSION_r11 1023 +#define _GUARD_GLOBALS_VERSION_r22 1024 +#define _GUARD_GLOBALS_VERSION_r33 1025 +#define _GUARD_IP_RETURN_GENERATOR_r00 1026 +#define _GUARD_IP_RETURN_GENERATOR_r11 1027 +#define _GUARD_IP_RETURN_GENERATOR_r22 1028 +#define _GUARD_IP_RETURN_GENERATOR_r33 1029 +#define _GUARD_IP_RETURN_VALUE_r00 1030 +#define _GUARD_IP_RETURN_VALUE_r11 1031 +#define _GUARD_IP_RETURN_VALUE_r22 1032 +#define _GUARD_IP_RETURN_VALUE_r33 1033 +#define _GUARD_IP_YIELD_VALUE_r00 1034 +#define _GUARD_IP_YIELD_VALUE_r11 1035 +#define _GUARD_IP_YIELD_VALUE_r22 1036 +#define _GUARD_IP_YIELD_VALUE_r33 1037 +#define _GUARD_IP__PUSH_FRAME_r00 1038 +#define _GUARD_IP__PUSH_FRAME_r11 1039 +#define _GUARD_IP__PUSH_FRAME_r22 1040 +#define _GUARD_IP__PUSH_FRAME_r33 1041 +#define _GUARD_IS_FALSE_POP_r00 1042 +#define _GUARD_IS_FALSE_POP_r10 1043 +#define _GUARD_IS_FALSE_POP_r21 1044 +#define _GUARD_IS_FALSE_POP_r32 1045 +#define _GUARD_IS_NONE_POP_r00 1046 +#define _GUARD_IS_NONE_POP_r10 1047 +#define _GUARD_IS_NONE_POP_r21 1048 +#define _GUARD_IS_NONE_POP_r32 1049 +#define _GUARD_IS_NOT_NONE_POP_r10 1050 +#define _GUARD_IS_TRUE_POP_r00 1051 +#define _GUARD_IS_TRUE_POP_r10 1052 +#define _GUARD_IS_TRUE_POP_r21 1053 +#define _GUARD_IS_TRUE_POP_r32 1054 +#define _GUARD_ITERATOR_r01 1055 +#define _GUARD_ITERATOR_r11 1056 +#define _GUARD_ITERATOR_r22 1057 +#define _GUARD_ITERATOR_r33 1058 +#define _GUARD_ITER_VIRTUAL_r01 1059 +#define _GUARD_ITER_VIRTUAL_r11 1060 +#define _GUARD_ITER_VIRTUAL_r22 1061 +#define _GUARD_ITER_VIRTUAL_r33 1062 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r03 1063 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r13 1064 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r23 1065 +#define _GUARD_LOAD_SUPER_ATTR_METHOD_r33 1066 +#define _GUARD_NOS_COMPACT_ASCII_r02 1067 +#define _GUARD_NOS_COMPACT_ASCII_r12 1068 +#define _GUARD_NOS_COMPACT_ASCII_r22 1069 +#define _GUARD_NOS_COMPACT_ASCII_r33 1070 +#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r03 1071 +#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r13 1072 +#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r23 1073 +#define _GUARD_NOS_DICT_STORE_SUBSCRIPT_r33 1074 +#define _GUARD_NOS_DICT_SUBSCRIPT_r02 1075 +#define _GUARD_NOS_DICT_SUBSCRIPT_r12 1076 +#define _GUARD_NOS_DICT_SUBSCRIPT_r22 1077 +#define _GUARD_NOS_DICT_SUBSCRIPT_r33 1078 +#define _GUARD_NOS_FLOAT_r02 1079 +#define _GUARD_NOS_FLOAT_r12 1080 +#define _GUARD_NOS_FLOAT_r22 1081 +#define _GUARD_NOS_FLOAT_r33 1082 +#define _GUARD_NOS_INT_r02 1083 +#define _GUARD_NOS_INT_r12 1084 +#define _GUARD_NOS_INT_r22 1085 +#define _GUARD_NOS_INT_r33 1086 +#define _GUARD_NOS_ITER_VIRTUAL_r02 1087 +#define _GUARD_NOS_ITER_VIRTUAL_r12 1088 +#define _GUARD_NOS_ITER_VIRTUAL_r22 1089 +#define _GUARD_NOS_ITER_VIRTUAL_r33 1090 +#define _GUARD_NOS_LIST_r02 1091 +#define _GUARD_NOS_LIST_r12 1092 +#define _GUARD_NOS_LIST_r22 1093 +#define _GUARD_NOS_LIST_r33 1094 +#define _GUARD_NOS_NOT_NULL_r02 1095 +#define _GUARD_NOS_NOT_NULL_r12 1096 +#define _GUARD_NOS_NOT_NULL_r22 1097 +#define _GUARD_NOS_NOT_NULL_r33 1098 +#define _GUARD_NOS_NULL_r02 1099 +#define _GUARD_NOS_NULL_r12 1100 +#define _GUARD_NOS_NULL_r22 1101 +#define _GUARD_NOS_NULL_r33 1102 +#define _GUARD_NOS_OVERFLOWED_r02 1103 +#define _GUARD_NOS_OVERFLOWED_r12 1104 +#define _GUARD_NOS_OVERFLOWED_r22 1105 +#define _GUARD_NOS_OVERFLOWED_r33 1106 +#define _GUARD_NOS_TUPLE_r02 1107 +#define _GUARD_NOS_TUPLE_r12 1108 +#define _GUARD_NOS_TUPLE_r22 1109 +#define _GUARD_NOS_TUPLE_r33 1110 +#define _GUARD_NOS_TYPE_VERSION_r02 1111 +#define _GUARD_NOS_TYPE_VERSION_r12 1112 +#define _GUARD_NOS_TYPE_VERSION_r22 1113 +#define _GUARD_NOS_TYPE_VERSION_r33 1114 +#define _GUARD_NOS_UNICODE_r02 1115 +#define _GUARD_NOS_UNICODE_r12 1116 +#define _GUARD_NOS_UNICODE_r22 1117 +#define _GUARD_NOS_UNICODE_r33 1118 +#define _GUARD_NOT_EXHAUSTED_LIST_r02 1119 +#define _GUARD_NOT_EXHAUSTED_LIST_r12 1120 +#define _GUARD_NOT_EXHAUSTED_LIST_r22 1121 +#define _GUARD_NOT_EXHAUSTED_LIST_r33 1122 +#define _GUARD_NOT_EXHAUSTED_RANGE_r02 1123 +#define _GUARD_NOT_EXHAUSTED_RANGE_r12 1124 +#define _GUARD_NOT_EXHAUSTED_RANGE_r22 1125 +#define _GUARD_NOT_EXHAUSTED_RANGE_r33 1126 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r02 1127 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r12 1128 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r22 1129 +#define _GUARD_NOT_EXHAUSTED_TUPLE_r33 1130 +#define _GUARD_THIRD_NULL_r03 1131 +#define _GUARD_THIRD_NULL_r13 1132 +#define _GUARD_THIRD_NULL_r23 1133 +#define _GUARD_THIRD_NULL_r33 1134 +#define _GUARD_TOS_ANY_DICT_r01 1135 +#define _GUARD_TOS_ANY_DICT_r11 1136 +#define _GUARD_TOS_ANY_DICT_r22 1137 +#define _GUARD_TOS_ANY_DICT_r33 1138 +#define _GUARD_TOS_ANY_SET_r01 1139 +#define _GUARD_TOS_ANY_SET_r11 1140 +#define _GUARD_TOS_ANY_SET_r22 1141 +#define _GUARD_TOS_ANY_SET_r33 1142 +#define _GUARD_TOS_DICT_r01 1143 +#define _GUARD_TOS_DICT_r11 1144 +#define _GUARD_TOS_DICT_r22 1145 +#define _GUARD_TOS_DICT_r33 1146 +#define _GUARD_TOS_FLOAT_r01 1147 +#define _GUARD_TOS_FLOAT_r11 1148 +#define _GUARD_TOS_FLOAT_r22 1149 +#define _GUARD_TOS_FLOAT_r33 1150 +#define _GUARD_TOS_FROZENDICT_r01 1151 +#define _GUARD_TOS_FROZENDICT_r11 1152 +#define _GUARD_TOS_FROZENDICT_r22 1153 +#define _GUARD_TOS_FROZENDICT_r33 1154 +#define _GUARD_TOS_FROZENSET_r01 1155 +#define _GUARD_TOS_FROZENSET_r11 1156 +#define _GUARD_TOS_FROZENSET_r22 1157 +#define _GUARD_TOS_FROZENSET_r33 1158 +#define _GUARD_TOS_INT_r01 1159 +#define _GUARD_TOS_INT_r11 1160 +#define _GUARD_TOS_INT_r22 1161 +#define _GUARD_TOS_INT_r33 1162 +#define _GUARD_TOS_IS_NONE_r01 1163 +#define _GUARD_TOS_IS_NONE_r11 1164 +#define _GUARD_TOS_IS_NONE_r22 1165 +#define _GUARD_TOS_IS_NONE_r33 1166 +#define _GUARD_TOS_LIST_r01 1167 +#define _GUARD_TOS_LIST_r11 1168 +#define _GUARD_TOS_LIST_r22 1169 +#define _GUARD_TOS_LIST_r33 1170 +#define _GUARD_TOS_NOT_NULL_r01 1171 +#define _GUARD_TOS_NOT_NULL_r11 1172 +#define _GUARD_TOS_NOT_NULL_r22 1173 +#define _GUARD_TOS_NOT_NULL_r33 1174 +#define _GUARD_TOS_OVERFLOWED_r01 1175 +#define _GUARD_TOS_OVERFLOWED_r11 1176 +#define _GUARD_TOS_OVERFLOWED_r22 1177 +#define _GUARD_TOS_OVERFLOWED_r33 1178 +#define _GUARD_TOS_SET_r01 1179 +#define _GUARD_TOS_SET_r11 1180 +#define _GUARD_TOS_SET_r22 1181 +#define _GUARD_TOS_SET_r33 1182 +#define _GUARD_TOS_SLICE_r01 1183 +#define _GUARD_TOS_SLICE_r11 1184 +#define _GUARD_TOS_SLICE_r22 1185 +#define _GUARD_TOS_SLICE_r33 1186 +#define _GUARD_TOS_TUPLE_r01 1187 +#define _GUARD_TOS_TUPLE_r11 1188 +#define _GUARD_TOS_TUPLE_r22 1189 +#define _GUARD_TOS_TUPLE_r33 1190 +#define _GUARD_TOS_UNICODE_r01 1191 +#define _GUARD_TOS_UNICODE_r11 1192 +#define _GUARD_TOS_UNICODE_r22 1193 +#define _GUARD_TOS_UNICODE_r33 1194 +#define _GUARD_TYPE_r01 1195 +#define _GUARD_TYPE_r11 1196 +#define _GUARD_TYPE_r22 1197 +#define _GUARD_TYPE_r33 1198 +#define _GUARD_TYPE_ITER_r02 1199 +#define _GUARD_TYPE_ITER_r12 1200 +#define _GUARD_TYPE_ITER_r22 1201 +#define _GUARD_TYPE_ITER_r33 1202 +#define _GUARD_TYPE_VERSION_r01 1203 +#define _GUARD_TYPE_VERSION_r11 1204 +#define _GUARD_TYPE_VERSION_r22 1205 +#define _GUARD_TYPE_VERSION_r33 1206 +#define _GUARD_TYPE_VERSION_LOCKED_r01 1207 +#define _GUARD_TYPE_VERSION_LOCKED_r11 1208 +#define _GUARD_TYPE_VERSION_LOCKED_r22 1209 +#define _GUARD_TYPE_VERSION_LOCKED_r33 1210 +#define _HANDLE_PENDING_AND_DEOPT_r00 1211 +#define _HANDLE_PENDING_AND_DEOPT_r10 1212 +#define _HANDLE_PENDING_AND_DEOPT_r20 1213 +#define _HANDLE_PENDING_AND_DEOPT_r30 1214 +#define _IMPORT_FROM_r12 1215 +#define _IMPORT_NAME_r21 1216 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS_r00 1217 +#define _INIT_CALL_PY_EXACT_ARGS_r01 1218 +#define _INIT_CALL_PY_EXACT_ARGS_0_r01 1219 +#define _INIT_CALL_PY_EXACT_ARGS_1_r01 1220 +#define _INIT_CALL_PY_EXACT_ARGS_2_r01 1221 +#define _INIT_CALL_PY_EXACT_ARGS_3_r01 1222 +#define _INIT_CALL_PY_EXACT_ARGS_4_r01 1223 +#define _INSERT_NULL_r10 1224 +#define _INSTRUMENTED_FOR_ITER_r23 1225 +#define _INSTRUMENTED_INSTRUCTION_r00 1226 +#define _INSTRUMENTED_JUMP_FORWARD_r00 1227 +#define _INSTRUMENTED_JUMP_FORWARD_r11 1228 +#define _INSTRUMENTED_JUMP_FORWARD_r22 1229 +#define _INSTRUMENTED_JUMP_FORWARD_r33 1230 +#define _INSTRUMENTED_LINE_r00 1231 +#define _INSTRUMENTED_NOT_TAKEN_r00 1232 +#define _INSTRUMENTED_NOT_TAKEN_r11 1233 +#define _INSTRUMENTED_NOT_TAKEN_r22 1234 +#define _INSTRUMENTED_NOT_TAKEN_r33 1235 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r00 1236 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r10 1237 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r21 1238 +#define _INSTRUMENTED_POP_JUMP_IF_FALSE_r32 1239 +#define _INSTRUMENTED_POP_JUMP_IF_NONE_r10 1240 +#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE_r10 1241 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r00 1242 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r10 1243 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r21 1244 +#define _INSTRUMENTED_POP_JUMP_IF_TRUE_r32 1245 +#define _IS_NONE_r11 1246 +#define _IS_OP_r03 1247 +#define _IS_OP_r13 1248 +#define _IS_OP_r23 1249 +#define _ITER_CHECK_LIST_r02 1250 +#define _ITER_CHECK_LIST_r12 1251 +#define _ITER_CHECK_LIST_r22 1252 +#define _ITER_CHECK_LIST_r33 1253 +#define _ITER_CHECK_RANGE_r02 1254 +#define _ITER_CHECK_RANGE_r12 1255 +#define _ITER_CHECK_RANGE_r22 1256 +#define _ITER_CHECK_RANGE_r33 1257 +#define _ITER_CHECK_TUPLE_r02 1258 +#define _ITER_CHECK_TUPLE_r12 1259 +#define _ITER_CHECK_TUPLE_r22 1260 +#define _ITER_CHECK_TUPLE_r33 1261 +#define _ITER_JUMP_LIST_r02 1262 +#define _ITER_JUMP_LIST_r12 1263 +#define _ITER_JUMP_LIST_r22 1264 +#define _ITER_JUMP_LIST_r33 1265 +#define _ITER_JUMP_RANGE_r02 1266 +#define _ITER_JUMP_RANGE_r12 1267 +#define _ITER_JUMP_RANGE_r22 1268 +#define _ITER_JUMP_RANGE_r33 1269 +#define _ITER_JUMP_TUPLE_r02 1270 +#define _ITER_JUMP_TUPLE_r12 1271 +#define _ITER_JUMP_TUPLE_r22 1272 +#define _ITER_JUMP_TUPLE_r33 1273 +#define _ITER_NEXT_INLINE_r23 1274 +#define _ITER_NEXT_LIST_r23 1275 +#define _ITER_NEXT_LIST_TIER_TWO_r23 1276 +#define _ITER_NEXT_RANGE_r03 1277 +#define _ITER_NEXT_RANGE_r13 1278 +#define _ITER_NEXT_RANGE_r23 1279 +#define _ITER_NEXT_TUPLE_r03 1280 +#define _ITER_NEXT_TUPLE_r13 1281 +#define _ITER_NEXT_TUPLE_r23 1282 +#define _JUMP_BACKWARD_NO_INTERRUPT_r00 1283 +#define _JUMP_BACKWARD_NO_INTERRUPT_r11 1284 +#define _JUMP_BACKWARD_NO_INTERRUPT_r22 1285 +#define _JUMP_BACKWARD_NO_INTERRUPT_r33 1286 +#define _JUMP_TO_TOP_r00 1287 +#define _LIST_APPEND_r10 1288 +#define _LIST_EXTEND_r11 1289 +#define _LOAD_ATTR_r10 1290 +#define _LOAD_ATTR_CLASS_r11 1291 +#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN_FRAME_r11 1292 +#define _LOAD_ATTR_INSTANCE_VALUE_r02 1293 +#define _LOAD_ATTR_INSTANCE_VALUE_r12 1294 +#define _LOAD_ATTR_INSTANCE_VALUE_r23 1295 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r02 1296 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r12 1297 +#define _LOAD_ATTR_METHOD_LAZY_DICT_r23 1298 +#define _LOAD_ATTR_METHOD_NO_DICT_r02 1299 +#define _LOAD_ATTR_METHOD_NO_DICT_r12 1300 +#define _LOAD_ATTR_METHOD_NO_DICT_r23 1301 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r02 1302 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r12 1303 +#define _LOAD_ATTR_METHOD_WITH_VALUES_r23 1304 +#define _LOAD_ATTR_MODULE_r12 1305 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1306 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1307 +#define _LOAD_ATTR_PROPERTY_FRAME_r01 1308 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1309 +#define _LOAD_ATTR_PROPERTY_FRAME_r22 1310 +#define _LOAD_ATTR_PROPERTY_FRAME_r33 1311 +#define _LOAD_ATTR_SLOT_r02 1312 +#define _LOAD_ATTR_SLOT_r12 1313 +#define _LOAD_ATTR_SLOT_r23 1314 +#define _LOAD_ATTR_WITH_HINT_r12 1315 +#define _LOAD_BUILD_CLASS_r01 1316 +#define _LOAD_BYTECODE_r00 1317 +#define _LOAD_COMMON_CONSTANT_r01 1318 +#define _LOAD_COMMON_CONSTANT_r12 1319 +#define _LOAD_COMMON_CONSTANT_r23 1320 +#define _LOAD_CONST_r01 1321 +#define _LOAD_CONST_r12 1322 +#define _LOAD_CONST_r23 1323 +#define _LOAD_CONST_INLINE_r01 1324 +#define _LOAD_CONST_INLINE_r12 1325 +#define _LOAD_CONST_INLINE_r23 1326 +#define _LOAD_CONST_INLINE_BORROW_r01 1327 +#define _LOAD_CONST_INLINE_BORROW_r12 1328 +#define _LOAD_CONST_INLINE_BORROW_r23 1329 +#define _LOAD_DEREF_r01 1330 +#define _LOAD_FAST_r01 1331 +#define _LOAD_FAST_r12 1332 +#define _LOAD_FAST_r23 1333 +#define _LOAD_FAST_0_r01 1334 +#define _LOAD_FAST_0_r12 1335 +#define _LOAD_FAST_0_r23 1336 +#define _LOAD_FAST_1_r01 1337 +#define _LOAD_FAST_1_r12 1338 +#define _LOAD_FAST_1_r23 1339 +#define _LOAD_FAST_2_r01 1340 +#define _LOAD_FAST_2_r12 1341 +#define _LOAD_FAST_2_r23 1342 +#define _LOAD_FAST_3_r01 1343 +#define _LOAD_FAST_3_r12 1344 +#define _LOAD_FAST_3_r23 1345 +#define _LOAD_FAST_4_r01 1346 +#define _LOAD_FAST_4_r12 1347 +#define _LOAD_FAST_4_r23 1348 +#define _LOAD_FAST_5_r01 1349 +#define _LOAD_FAST_5_r12 1350 +#define _LOAD_FAST_5_r23 1351 +#define _LOAD_FAST_6_r01 1352 +#define _LOAD_FAST_6_r12 1353 +#define _LOAD_FAST_6_r23 1354 +#define _LOAD_FAST_7_r01 1355 +#define _LOAD_FAST_7_r12 1356 +#define _LOAD_FAST_7_r23 1357 +#define _LOAD_FAST_AND_CLEAR_r01 1358 +#define _LOAD_FAST_AND_CLEAR_r12 1359 +#define _LOAD_FAST_AND_CLEAR_r23 1360 +#define _LOAD_FAST_BORROW_r01 1361 +#define _LOAD_FAST_BORROW_r12 1362 +#define _LOAD_FAST_BORROW_r23 1363 +#define _LOAD_FAST_BORROW_0_r01 1364 +#define _LOAD_FAST_BORROW_0_r12 1365 +#define _LOAD_FAST_BORROW_0_r23 1366 +#define _LOAD_FAST_BORROW_1_r01 1367 +#define _LOAD_FAST_BORROW_1_r12 1368 +#define _LOAD_FAST_BORROW_1_r23 1369 +#define _LOAD_FAST_BORROW_2_r01 1370 +#define _LOAD_FAST_BORROW_2_r12 1371 +#define _LOAD_FAST_BORROW_2_r23 1372 +#define _LOAD_FAST_BORROW_3_r01 1373 +#define _LOAD_FAST_BORROW_3_r12 1374 +#define _LOAD_FAST_BORROW_3_r23 1375 +#define _LOAD_FAST_BORROW_4_r01 1376 +#define _LOAD_FAST_BORROW_4_r12 1377 +#define _LOAD_FAST_BORROW_4_r23 1378 +#define _LOAD_FAST_BORROW_5_r01 1379 +#define _LOAD_FAST_BORROW_5_r12 1380 +#define _LOAD_FAST_BORROW_5_r23 1381 +#define _LOAD_FAST_BORROW_6_r01 1382 +#define _LOAD_FAST_BORROW_6_r12 1383 +#define _LOAD_FAST_BORROW_6_r23 1384 +#define _LOAD_FAST_BORROW_7_r01 1385 +#define _LOAD_FAST_BORROW_7_r12 1386 +#define _LOAD_FAST_BORROW_7_r23 1387 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1388 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1389 +#define _LOAD_FAST_CHECK_r01 1390 +#define _LOAD_FAST_CHECK_r12 1391 +#define _LOAD_FAST_CHECK_r23 1392 +#define _LOAD_FAST_LOAD_FAST_r02 1393 +#define _LOAD_FAST_LOAD_FAST_r13 1394 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1395 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1396 +#define _LOAD_GLOBAL_r00 1397 +#define _LOAD_GLOBAL_BUILTINS_r01 1398 +#define _LOAD_GLOBAL_MODULE_r01 1399 +#define _LOAD_LOCALS_r01 1400 +#define _LOAD_LOCALS_r12 1401 +#define _LOAD_LOCALS_r23 1402 +#define _LOAD_NAME_r01 1403 +#define _LOAD_SMALL_INT_r01 1404 +#define _LOAD_SMALL_INT_r12 1405 +#define _LOAD_SMALL_INT_r23 1406 +#define _LOAD_SMALL_INT_0_r01 1407 +#define _LOAD_SMALL_INT_0_r12 1408 +#define _LOAD_SMALL_INT_0_r23 1409 +#define _LOAD_SMALL_INT_1_r01 1410 +#define _LOAD_SMALL_INT_1_r12 1411 +#define _LOAD_SMALL_INT_1_r23 1412 +#define _LOAD_SMALL_INT_2_r01 1413 +#define _LOAD_SMALL_INT_2_r12 1414 +#define _LOAD_SMALL_INT_2_r23 1415 +#define _LOAD_SMALL_INT_3_r01 1416 +#define _LOAD_SMALL_INT_3_r12 1417 +#define _LOAD_SMALL_INT_3_r23 1418 +#define _LOAD_SPECIAL_r00 1419 +#define _LOAD_SUPER_ATTR_ATTR_r31 1420 +#define _LOAD_SUPER_ATTR_METHOD_r32 1421 +#define _LOCK_OBJECT_r01 1422 +#define _LOCK_OBJECT_r11 1423 +#define _LOCK_OBJECT_r22 1424 +#define _LOCK_OBJECT_r33 1425 +#define _MAKE_CALLARGS_A_TUPLE_r33 1426 +#define _MAKE_CELL_r00 1427 +#define _MAKE_FUNCTION_r12 1428 +#define _MAKE_HEAP_SAFE_r01 1429 +#define _MAKE_HEAP_SAFE_r11 1430 +#define _MAKE_HEAP_SAFE_r22 1431 +#define _MAKE_HEAP_SAFE_r33 1432 +#define _MAKE_WARM_r00 1433 +#define _MAKE_WARM_r11 1434 +#define _MAKE_WARM_r22 1435 +#define _MAKE_WARM_r33 1436 +#define _MAP_ADD_r20 1437 +#define _MATCH_CLASS_r33 1438 +#define _MATCH_KEYS_r23 1439 +#define _MATCH_MAPPING_r02 1440 +#define _MATCH_MAPPING_r12 1441 +#define _MATCH_MAPPING_r23 1442 +#define _MATCH_SEQUENCE_r02 1443 +#define _MATCH_SEQUENCE_r12 1444 +#define _MATCH_SEQUENCE_r23 1445 +#define _MAYBE_EXPAND_METHOD_r00 1446 +#define _MAYBE_EXPAND_METHOD_KW_r11 1447 +#define _MONITOR_CALL_r00 1448 +#define _MONITOR_CALL_KW_r11 1449 +#define _MONITOR_JUMP_BACKWARD_r00 1450 +#define _MONITOR_JUMP_BACKWARD_r11 1451 +#define _MONITOR_JUMP_BACKWARD_r22 1452 +#define _MONITOR_JUMP_BACKWARD_r33 1453 +#define _MONITOR_RESUME_r00 1454 +#define _NOP_r00 1455 +#define _NOP_r11 1456 +#define _NOP_r22 1457 +#define _NOP_r33 1458 +#define _POP_EXCEPT_r10 1459 +#define _POP_ITER_r20 1460 +#define _POP_JUMP_IF_FALSE_r00 1461 +#define _POP_JUMP_IF_FALSE_r10 1462 +#define _POP_JUMP_IF_FALSE_r21 1463 +#define _POP_JUMP_IF_FALSE_r32 1464 +#define _POP_JUMP_IF_TRUE_r00 1465 +#define _POP_JUMP_IF_TRUE_r10 1466 +#define _POP_JUMP_IF_TRUE_r21 1467 +#define _POP_JUMP_IF_TRUE_r32 1468 +#define _POP_TOP_r10 1469 +#define _POP_TOP_FLOAT_r00 1470 +#define _POP_TOP_FLOAT_r10 1471 +#define _POP_TOP_FLOAT_r21 1472 +#define _POP_TOP_FLOAT_r32 1473 +#define _POP_TOP_INT_r00 1474 +#define _POP_TOP_INT_r10 1475 +#define _POP_TOP_INT_r21 1476 +#define _POP_TOP_INT_r32 1477 +#define _POP_TOP_NOP_r00 1478 +#define _POP_TOP_NOP_r10 1479 +#define _POP_TOP_NOP_r21 1480 +#define _POP_TOP_NOP_r32 1481 +#define _POP_TOP_OPARG_r00 1482 +#define _POP_TOP_UNICODE_r00 1483 +#define _POP_TOP_UNICODE_r10 1484 +#define _POP_TOP_UNICODE_r21 1485 +#define _POP_TOP_UNICODE_r32 1486 +#define _PUSH_EXC_INFO_r02 1487 +#define _PUSH_EXC_INFO_r12 1488 +#define _PUSH_EXC_INFO_r23 1489 +#define _PUSH_FRAME_r10 1490 +#define _PUSH_NULL_r01 1491 +#define _PUSH_NULL_r12 1492 +#define _PUSH_NULL_r23 1493 +#define _PUSH_NULL_CONDITIONAL_r00 1494 +#define _PUSH_TAGGED_ZERO_r01 1495 +#define _PUSH_TAGGED_ZERO_r12 1496 +#define _PUSH_TAGGED_ZERO_r23 1497 +#define _PY_FRAME_EX_r31 1498 +#define _PY_FRAME_GENERAL_r01 1499 +#define _PY_FRAME_KW_r11 1500 +#define _REPLACE_WITH_TRUE_r02 1501 +#define _REPLACE_WITH_TRUE_r12 1502 +#define _REPLACE_WITH_TRUE_r23 1503 +#define _RESUME_CHECK_r00 1504 +#define _RESUME_CHECK_r11 1505 +#define _RESUME_CHECK_r22 1506 +#define _RESUME_CHECK_r33 1507 +#define _RETURN_GENERATOR_r01 1508 +#define _RETURN_VALUE_r11 1509 +#define _RROT_3_r03 1510 +#define _RROT_3_r13 1511 +#define _RROT_3_r23 1512 +#define _RROT_3_r33 1513 +#define _SAVE_RETURN_OFFSET_r00 1514 +#define _SAVE_RETURN_OFFSET_r11 1515 +#define _SAVE_RETURN_OFFSET_r22 1516 +#define _SAVE_RETURN_OFFSET_r33 1517 +#define _SEND_ASYNC_GEN_r33 1518 +#define _SEND_ASYNC_GEN_TIER_TWO_r33 1519 +#define _SEND_GEN_FRAME_r33 1520 +#define _SEND_VIRTUAL_r33 1521 +#define _SEND_VIRTUAL_TIER_TWO_r03 1522 +#define _SEND_VIRTUAL_TIER_TWO_r13 1523 +#define _SEND_VIRTUAL_TIER_TWO_r23 1524 +#define _SEND_VIRTUAL_TIER_TWO_r33 1525 +#define _SETUP_ANNOTATIONS_r00 1526 +#define _SET_ADD_r10 1527 +#define _SET_FUNCTION_ATTRIBUTE_r01 1528 +#define _SET_FUNCTION_ATTRIBUTE_r11 1529 +#define _SET_FUNCTION_ATTRIBUTE_r21 1530 +#define _SET_FUNCTION_ATTRIBUTE_r32 1531 +#define _SET_IP_r00 1532 +#define _SET_IP_r11 1533 +#define _SET_IP_r22 1534 +#define _SET_IP_r33 1535 +#define _SET_UPDATE_r11 1536 +#define _SPILL_OR_RELOAD_r01 1537 +#define _SPILL_OR_RELOAD_r02 1538 +#define _SPILL_OR_RELOAD_r03 1539 +#define _SPILL_OR_RELOAD_r10 1540 +#define _SPILL_OR_RELOAD_r12 1541 +#define _SPILL_OR_RELOAD_r13 1542 +#define _SPILL_OR_RELOAD_r20 1543 +#define _SPILL_OR_RELOAD_r21 1544 +#define _SPILL_OR_RELOAD_r23 1545 +#define _SPILL_OR_RELOAD_r30 1546 +#define _SPILL_OR_RELOAD_r31 1547 +#define _SPILL_OR_RELOAD_r32 1548 +#define _START_EXECUTOR_r00 1549 +#define _STORE_ATTR_r20 1550 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1551 +#define _STORE_ATTR_SLOT_r21 1552 +#define _STORE_ATTR_WITH_HINT_r21 1553 +#define _STORE_DEREF_r10 1554 +#define _STORE_FAST_LOAD_FAST_r11 1555 +#define _STORE_FAST_STORE_FAST_r20 1556 +#define _STORE_GLOBAL_r10 1557 +#define _STORE_NAME_r10 1558 +#define _STORE_SLICE_r30 1559 +#define _STORE_SUBSCR_r30 1560 +#define _STORE_SUBSCR_DICT_r31 1561 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1562 +#define _STORE_SUBSCR_LIST_INT_r32 1563 +#define _SWAP_r11 1564 +#define _SWAP_2_r02 1565 +#define _SWAP_2_r12 1566 +#define _SWAP_2_r22 1567 +#define _SWAP_2_r33 1568 +#define _SWAP_3_r03 1569 +#define _SWAP_3_r13 1570 +#define _SWAP_3_r23 1571 +#define _SWAP_3_r33 1572 +#define _SWAP_FAST_r01 1573 +#define _SWAP_FAST_r11 1574 +#define _SWAP_FAST_r22 1575 +#define _SWAP_FAST_r33 1576 +#define _SWAP_FAST_0_r01 1577 +#define _SWAP_FAST_0_r11 1578 +#define _SWAP_FAST_0_r22 1579 +#define _SWAP_FAST_0_r33 1580 +#define _SWAP_FAST_1_r01 1581 +#define _SWAP_FAST_1_r11 1582 +#define _SWAP_FAST_1_r22 1583 +#define _SWAP_FAST_1_r33 1584 +#define _SWAP_FAST_2_r01 1585 +#define _SWAP_FAST_2_r11 1586 +#define _SWAP_FAST_2_r22 1587 +#define _SWAP_FAST_2_r33 1588 +#define _SWAP_FAST_3_r01 1589 +#define _SWAP_FAST_3_r11 1590 +#define _SWAP_FAST_3_r22 1591 +#define _SWAP_FAST_3_r33 1592 +#define _SWAP_FAST_4_r01 1593 +#define _SWAP_FAST_4_r11 1594 +#define _SWAP_FAST_4_r22 1595 +#define _SWAP_FAST_4_r33 1596 +#define _SWAP_FAST_5_r01 1597 +#define _SWAP_FAST_5_r11 1598 +#define _SWAP_FAST_5_r22 1599 +#define _SWAP_FAST_5_r33 1600 +#define _SWAP_FAST_6_r01 1601 +#define _SWAP_FAST_6_r11 1602 +#define _SWAP_FAST_6_r22 1603 +#define _SWAP_FAST_6_r33 1604 +#define _SWAP_FAST_7_r01 1605 +#define _SWAP_FAST_7_r11 1606 +#define _SWAP_FAST_7_r22 1607 +#define _SWAP_FAST_7_r33 1608 +#define _TIER2_RESUME_CHECK_r00 1609 +#define _TIER2_RESUME_CHECK_r11 1610 +#define _TIER2_RESUME_CHECK_r22 1611 +#define _TIER2_RESUME_CHECK_r33 1612 +#define _TO_BOOL_r11 1613 +#define _TO_BOOL_BOOL_r01 1614 +#define _TO_BOOL_BOOL_r11 1615 +#define _TO_BOOL_BOOL_r22 1616 +#define _TO_BOOL_BOOL_r33 1617 +#define _TO_BOOL_INT_r02 1618 +#define _TO_BOOL_INT_r12 1619 +#define _TO_BOOL_INT_r23 1620 +#define _TO_BOOL_LIST_r02 1621 +#define _TO_BOOL_LIST_r12 1622 +#define _TO_BOOL_LIST_r23 1623 +#define _TO_BOOL_NONE_r01 1624 +#define _TO_BOOL_NONE_r11 1625 +#define _TO_BOOL_NONE_r22 1626 +#define _TO_BOOL_NONE_r33 1627 +#define _TO_BOOL_STR_r02 1628 +#define _TO_BOOL_STR_r12 1629 +#define _TO_BOOL_STR_r23 1630 +#define _TRACE_RECORD_r00 1631 +#define _UNARY_INVERT_r12 1632 +#define _UNARY_NEGATIVE_r12 1633 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1634 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1635 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1636 +#define _UNARY_NOT_r01 1637 +#define _UNARY_NOT_r11 1638 +#define _UNARY_NOT_r22 1639 +#define _UNARY_NOT_r33 1640 +#define _UNPACK_EX_r10 1641 +#define _UNPACK_SEQUENCE_r10 1642 +#define _UNPACK_SEQUENCE_LIST_r10 1643 +#define _UNPACK_SEQUENCE_TUPLE_r10 1644 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1645 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1646 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1647 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1648 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1649 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1650 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1651 +#define _WITH_EXCEPT_START_r33 1652 +#define _YIELD_VALUE_r11 1653 +#define MAX_UOP_REGS_ID 1653 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 6713e9bc95f942d..45f407dae3ddf57 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -287,7 +287,6 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_WITH_EXCEPT_START] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_PUSH_EXC_INFO] = 0, [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_EXIT_FLAG, - [_GUARD_KEYS_VERSION] = HAS_EXIT_FLAG, [_LOAD_ATTR_METHOD_WITH_VALUES] = HAS_ARG_FLAG, [_LOAD_ATTR_METHOD_NO_DICT] = HAS_ARG_FLAG, [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, @@ -2717,15 +2716,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { 3, 3, _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33 }, }, }, - [_GUARD_KEYS_VERSION] = { - .best = { 0, 1, 2, 3 }, - .entries = { - { 1, 0, _GUARD_KEYS_VERSION_r01 }, - { 1, 1, _GUARD_KEYS_VERSION_r11 }, - { 2, 2, _GUARD_KEYS_VERSION_r22 }, - { 3, 3, _GUARD_KEYS_VERSION_r33 }, - }, - }, [_LOAD_ATTR_METHOD_WITH_VALUES] = { .best = { 0, 1, 2, 2 }, .entries = { @@ -4543,10 +4533,6 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r11] = _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r22] = _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, [_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT_r33] = _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, - [_GUARD_KEYS_VERSION_r01] = _GUARD_KEYS_VERSION, - [_GUARD_KEYS_VERSION_r11] = _GUARD_KEYS_VERSION, - [_GUARD_KEYS_VERSION_r22] = _GUARD_KEYS_VERSION, - [_GUARD_KEYS_VERSION_r33] = _GUARD_KEYS_VERSION, [_LOAD_ATTR_METHOD_WITH_VALUES_r02] = _LOAD_ATTR_METHOD_WITH_VALUES, [_LOAD_ATTR_METHOD_WITH_VALUES_r12] = _LOAD_ATTR_METHOD_WITH_VALUES, [_LOAD_ATTR_METHOD_WITH_VALUES_r23] = _LOAD_ATTR_METHOD_WITH_VALUES, @@ -5473,11 +5459,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_GUARD_ITER_VIRTUAL_r11] = "_GUARD_ITER_VIRTUAL_r11", [_GUARD_ITER_VIRTUAL_r22] = "_GUARD_ITER_VIRTUAL_r22", [_GUARD_ITER_VIRTUAL_r33] = "_GUARD_ITER_VIRTUAL_r33", - [_GUARD_KEYS_VERSION] = "_GUARD_KEYS_VERSION", - [_GUARD_KEYS_VERSION_r01] = "_GUARD_KEYS_VERSION_r01", - [_GUARD_KEYS_VERSION_r11] = "_GUARD_KEYS_VERSION_r11", - [_GUARD_KEYS_VERSION_r22] = "_GUARD_KEYS_VERSION_r22", - [_GUARD_KEYS_VERSION_r33] = "_GUARD_KEYS_VERSION_r33", [_GUARD_LOAD_SUPER_ATTR_METHOD] = "_GUARD_LOAD_SUPER_ATTR_METHOD", [_GUARD_LOAD_SUPER_ATTR_METHOD_r03] = "_GUARD_LOAD_SUPER_ATTR_METHOD_r03", [_GUARD_LOAD_SUPER_ATTR_METHOD_r13] = "_GUARD_LOAD_SUPER_ATTR_METHOD_r13", @@ -6728,8 +6709,6 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT: return 0; - case _GUARD_KEYS_VERSION: - return 0; case _LOAD_ATTR_METHOD_WITH_VALUES: return 1; case _LOAD_ATTR_METHOD_NO_DICT: diff --git a/Lib/.ruff.toml b/Lib/.ruff.toml new file mode 100644 index 000000000000000..c9ae9b95641b318 --- /dev/null +++ b/Lib/.ruff.toml @@ -0,0 +1,21 @@ +extend = "../.ruff.toml" # Inherit the project-wide settings + +# Unlike Tools/, stdlib can use newer syntax than PYTHON_FOR_REGEN +target-version = "py315" + +[lint] +select = [ + "F401", # Unused import +] + +[lint.per-file-ignores] +"ctypes/__init__.py" = ["F401"] # Re-exports from _ctypes +"ensurepip/__init__.py" = ["F401"] # `import zlib` availability check +"idlelib/idle_test/htest.py" = ["F401"] # Import for Windows DPI side effect +"idlelib/idle_test/test_iomenu.py" = ["F401"] # Imports checked for existence +"importlib/_abc.py" = ["F401"] # Bootstrap-sensitive _bootstrap import +"importlib/machinery.py" = ["F401"] # NamespacePath re-export +"importlib/metadata/__init__.py" = ["F401"] # Synced from importlib_metadata +"profiling/sampling/sample.py" = ["F401"] # Re-exports PROFILING_MODE_* constants +"ssl.py" = ["F401"] # Re-exports from _ssl +"warnings.py" = ["F401"] # Re-exports from _py_warnings diff --git a/Lib/_pyrepl/completing_reader.py b/Lib/_pyrepl/completing_reader.py index f783e8db36b0287..7eb3ebac84124b5 100644 --- a/Lib/_pyrepl/completing_reader.py +++ b/Lib/_pyrepl/completing_reader.py @@ -32,7 +32,7 @@ # types Command = commands.Command if TYPE_CHECKING: - from .types import CommandName, CompletionAction, Keymap, KeySpec + from .types import CompletionAction, Keymap def prefix(wordlist: list[str], j: int = 0) -> str: diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py index 7e4dd801c84d5c2..832e67b534f2969 100644 --- a/Lib/_pyrepl/reader.py +++ b/Lib/_pyrepl/reader.py @@ -38,7 +38,7 @@ ) from .layout import LayoutMap, LayoutResult, LayoutRow, WrappedRow, layout_content_lines from .render import RenderCell, RenderLine, RenderedScreen, ScreenOverlay -from .utils import ANSI_ESCAPE_SEQUENCE, ColorSpan, THEME, StyleRef, wlen, gen_colors +from .utils import ANSI_ESCAPE_SEQUENCE, ColorSpan, THEME, StyleRef, gen_colors from .trace import trace diff --git a/Lib/_pyrepl/unix_console.py b/Lib/_pyrepl/unix_console.py index 9c4644db53e3436..9a4f8e0c623abfa 100644 --- a/Lib/_pyrepl/unix_console.py +++ b/Lib/_pyrepl/unix_console.py @@ -34,7 +34,7 @@ from collections.abc import Callable from dataclasses import dataclass from fcntl import ioctl -from typing import TYPE_CHECKING, cast, overload +from typing import TYPE_CHECKING, overload from . import terminfo from .console import Console, Event diff --git a/Lib/_pyrepl/utils.py b/Lib/_pyrepl/utils.py index b50426c31ead53a..230dae35af665ab 100644 --- a/Lib/_pyrepl/utils.py +++ b/Lib/_pyrepl/utils.py @@ -259,7 +259,7 @@ def is_soft_keyword_used(*tokens: TI | None) -> bool: None | TI(T.NEWLINE) | TI(T.INDENT) | TI(string=":"), TI(string="match"), TI(T.NUMBER | T.STRING | T.FSTRING_START | T.TSTRING_START) - | TI(T.OP, string="(" | "*" | "[" | "{" | "~" | "...") + | TI(T.OP, string="(" | "*" | "-" | "+" | "[" | "{" | "~" | "...") ): return True case ( @@ -274,7 +274,7 @@ def is_soft_keyword_used(*tokens: TI | None) -> bool: None | TI(T.NEWLINE) | TI(T.INDENT) | TI(T.DEDENT) | TI(string=":"), TI(string="case"), TI(T.NUMBER | T.STRING | T.FSTRING_START | T.TSTRING_START) - | TI(T.OP, string="(" | "*" | "-" | "[" | "{") + | TI(T.OP, string="(" | "*" | "-" | "+" | "[" | "{") ): return True case ( diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 3732294c5848f02..e6c72e3d5b5487e 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -488,10 +488,10 @@ def set_task_factory(self, factory): If factory is None the default task factory will be set. If factory is a callable, it should have a signature matching - '(loop, coro, **kwargs)', where 'loop' will be a reference to the active - event loop, 'coro' will be a coroutine object, and **kwargs will be - arbitrary keyword arguments that should be passed on to Task. - The callable must return a Task. + '(loop, coro, **kwargs)', where 'loop' will be a reference to the + active event loop, 'coro' will be a coroutine object, and **kwargs + will be arbitrary keyword arguments that should be passed on to + Task. The callable must return a Task. """ if factory is not None and not callable(factory): raise TypeError('task factory must be a callable or None') @@ -727,8 +727,8 @@ def run_until_complete(self, future): def stop(self): """Stop running the event loop. - Every callback already scheduled will still run. This simply informs - run_forever to stop looping after a complete iteration. + Every callback already scheduled will still run. This simply + informs run_forever to stop looping after a complete iteration. """ self._stopping = True @@ -1076,12 +1076,12 @@ async def create_connection( Create a streaming transport connection to a given internet host and port: socket family AF_INET or socket.AF_INET6 depending on host (or - family if specified), socket type SOCK_STREAM. protocol_factory must be - a callable returning a protocol instance. + family if specified), socket type SOCK_STREAM. protocol_factory must + be a callable returning a protocol instance. - This method is a coroutine which will try to establish the connection - in the background. When successful, the coroutine returns a - (transport, protocol) pair. + This method is a coroutine which will try to establish the + connection in the background. When successful, the coroutine + returns a (transport, protocol) pair. """ if server_hostname is not None and not ssl: raise ValueError('server_hostname is only meaningful with ssl') @@ -1550,11 +1550,11 @@ async def create_server( The host parameter can be a string, in that case the TCP server is bound to host and port. - The host parameter can also be a sequence of strings and in that case - the TCP server is bound to all hosts of the sequence. If a host - appears multiple times (possibly indirectly e.g. when hostnames - resolve to the same IP address), the server is only bound once to that - host. + The host parameter can also be a sequence of strings and in that + case the TCP server is bound to all hosts of the sequence. If + a host appears multiple times (possibly indirectly e.g. when + hostnames resolve to the same IP address), the server is only bound + once to that host. Return a Server object which can be used to stop the service. diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index bfffb6da4b19a18..3a4246f6ccd4c24 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -1,7 +1,6 @@ __all__ = ('iscoroutine',) import collections.abc -import inspect import os import sys import types diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index a7fb55982abe9ca..42d8408a38dfd1f 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -374,8 +374,8 @@ async def create_server( If host is an empty string or None all interfaces are assumed and a list of multiple sockets will be returned (most likely - one for IPv4 and another one for IPv6). The host parameter can also be - a sequence (e.g. list) of hosts to bind to. + one for IPv4 and another one for IPv6). The host parameter can also + be a sequence (e.g. list) of hosts to bind to. family can be set to either AF_INET or AF_INET6 to force the socket to use IPv4 or IPv6. If not set it will be determined @@ -415,8 +415,9 @@ async def create_server( start_serving set to True (default) causes the created server to start accepting connections immediately. When set to False, - the user should await Server.start_serving() or Server.serve_forever() - to make the server to start accepting connections. + the user should await Server.start_serving() or + Server.serve_forever() to make the server to start accepting + connections. """ raise NotImplementedError @@ -479,8 +480,9 @@ async def create_unix_server( start_serving set to True (default) causes the created server to start accepting connections immediately. When set to False, - the user should await Server.start_serving() or Server.serve_forever() - to make the server to start accepting connections. + the user should await Server.start_serving() or + Server.serve_forever() to make the server to start accepting + connections. """ raise NotImplementedError @@ -511,8 +513,8 @@ async def create_datagram_endpoint(self, protocol_factory, protocol_factory must be a callable returning a protocol instance. - socket family AF_INET, socket.AF_INET6 or socket.AF_UNIX depending on - host (or family if specified), socket type SOCK_DGRAM. + socket family AF_INET, socket.AF_INET6 or socket.AF_UNIX depending + on host (or family if specified), socket type SOCK_DGRAM. reuse_address tells the kernel to reuse a local socket in TIME_WAIT state, without waiting for its natural timeout to @@ -552,7 +554,8 @@ async def connect_read_pipe(self, protocol_factory, pipe): async def connect_write_pipe(self, protocol_factory, pipe): """Register write pipe in event loop. - protocol_factory should instantiate object with BaseProtocol interface. + protocol_factory should instantiate object with BaseProtocol + interface. Pipe is file-like object already switched to nonblocking. Return pair (transport, protocol), where transport support WriteTransport interface.""" diff --git a/Lib/asyncio/graph.py b/Lib/asyncio/graph.py index b5bfeb1630a1590..35f7fa62140bd49 100644 --- a/Lib/asyncio/graph.py +++ b/Lib/asyncio/graph.py @@ -112,13 +112,13 @@ def capture_call_graph( optional keyword-only 'depth' argument can be used to skip the specified number of frames from top of the stack. - If the optional keyword-only 'limit' argument is provided, each call stack - in the resulting graph is truncated to include at most ``abs(limit)`` - entries. If 'limit' is positive, the entries left are the closest to - the invocation point. If 'limit' is negative, the topmost entries are - left. If 'limit' is omitted or None, all entries are present. - If 'limit' is 0, the call stack is not captured at all, only - "awaited by" information is present. + If the optional keyword-only 'limit' argument is provided, each call + stack in the resulting graph is truncated to include at most + ``abs(limit)`` entries. If 'limit' is positive, the entries left are + the closest to the invocation point. If 'limit' is negative, the + topmost entries are left. If 'limit' is omitted or None, all entries + are present. If 'limit' is 0, the call stack is not captured at all, + only "awaited by" information is present. """ loop = events._get_running_loop() diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 0d5e362188ab21d..c59ea15111bef2b 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -155,10 +155,10 @@ def _wake_up_first(self): class Event(mixins._LoopBoundMixin): """Asynchronous equivalent to threading.Event. - Class implementing event objects. An event manages a flag that can be set - to true with the set() method and reset to false with the clear() method. - The wait() method blocks until the flag is true. The flag is initially - false. + Class implementing event objects. An event manages a flag that can be + set to true with the set() method and reset to false with the clear() + method. The wait() method blocks until the flag is true. The flag is + initially false. """ def __init__(self): @@ -350,9 +350,9 @@ class Semaphore(_ContextManagerMixin, mixins._LoopBoundMixin): """A Semaphore implementation. A semaphore manages an internal counter which is decremented by each - acquire() call and incremented by each release() call. The counter - can never go below zero; when acquire() finds that it is zero, it blocks, - waiting until some other thread calls release(). + acquire() call and incremented by each release() call. The counter + can never go below zero; when acquire() finds that it is zero, it + blocks, waiting until some other thread calls release(). Semaphores also support the context management protocol. @@ -508,8 +508,8 @@ async def __aexit__(self, *args): async def wait(self): """Wait for the barrier. - When the specified number of tasks have started waiting, they are all - simultaneously awoken. + When the specified number of tasks have started waiting, they are + all simultaneously awoken. Returns an unique and individual index number from 0 to 'parties-1'. """ async with self._cond: diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py index 756216fac809329..30004f2bc9bacd2 100644 --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -33,9 +33,9 @@ class QueueShutDown(Exception): class Queue(mixins._LoopBoundMixin): """A queue, useful for coordinating producer and consumer coroutines. - If maxsize is less than or equal to zero, the queue size is infinite. If it - is an integer greater than 0, then "await put()" will block when the - queue reaches maxsize, until an item is removed by get(). + If maxsize is less than or equal to zero, the queue size is infinite. + If it is an integer greater than 0, then "await put()" will block when + the queue reaches maxsize, until an item is removed by get(). Unlike queue.Queue, you can reliably know this Queue's size with qsize(), since your single-threaded asyncio application won't be @@ -174,8 +174,8 @@ async def get(self): If queue is empty, wait until an item is available. - Raises QueueShutDown if the queue has been shut down and is empty, or - if the queue has been shut down immediately. + Raises QueueShutDown if the queue has been shut down and is empty, + or if the queue has been shut down immediately. """ while self.empty(): if self._is_shutdown and self.empty(): @@ -203,10 +203,11 @@ async def get(self): def get_nowait(self): """Remove and return an item from the queue. - Return an item if one is immediately available, else raise QueueEmpty. + Return an item if one is immediately available, else raise + QueueEmpty. - Raises QueueShutDown if the queue has been shut down and is empty, or - if the queue has been shut down immediately. + Raises QueueShutDown if the queue has been shut down and is empty, + or if the queue has been shut down immediately. """ if self.empty(): if self._is_shutdown: @@ -223,12 +224,12 @@ def task_done(self): a subsequent call to task_done() tells the queue that the processing on the task is complete. - If a join() is currently blocking, it will resume when all items have - been processed (meaning that a task_done() call was received for every - item that had been put() into the queue). + If a join() is currently blocking, it will resume when all items + have been processed (meaning that a task_done() call was received + for every item that had been put() into the queue). - Raises ValueError if called more times than there were items placed in - the queue. + Raises ValueError if called more times than there were items placed + in the queue. """ if self._unfinished_tasks <= 0: raise ValueError('task_done() called too many times') @@ -239,10 +240,11 @@ def task_done(self): async def join(self): """Block until all items in the queue have been gotten and processed. - The count of unfinished tasks goes up whenever an item is added to the - queue. The count goes down whenever a consumer calls task_done() to - indicate that the item was retrieved and all work on it is complete. - When the count of unfinished tasks drops to zero, join() unblocks. + The count of unfinished tasks goes up whenever an item is added to + the queue. The count goes down whenever a consumer calls + task_done() to indicate that the item was retrieved and all work on + it is complete. When the count of unfinished tasks drops to zero, + join() unblocks. """ if self._unfinished_tasks > 0: await self._finished.wait() diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index ba37e003a655c0a..774a317564df22c 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -35,7 +35,8 @@ class Runner: with asyncio.Runner(debug=True) as runner: runner.run(main()) - The run() method can be called multiple times within the runner's context. + The run() method can be called multiple times within the runner's + context. This can be useful for interactive console (e.g. IPython), unittest runners, console tools, -- everywhere when async code diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index fa04c1db36d33c0..4fa4dd5a885236e 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -533,11 +533,12 @@ def _sock_recvfrom_into(self, fut, sock, buf, bufsize): async def sock_sendall(self, sock, data): """Send data to the socket. - The socket must be connected to a remote socket. This method continues - to send data from data until either all data has been sent or an - error occurs. None is returned on success. On error, an exception is - raised, and there is no way to determine how much data, if any, was - successfully processed by the receiving end of the connection. + The socket must be connected to a remote socket. This method + continues to send data from data until either all data has been + sent or an error occurs. None is returned on success. On error, + an exception is raised, and there is no way to determine how much + data, if any, was successfully processed by the receiving end of + the connection. """ base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: @@ -586,11 +587,12 @@ def _sock_sendall(self, fut, sock, view, pos): async def sock_sendto(self, sock, data, address): """Send data to the socket. - The socket must be connected to a remote socket. This method continues - to send data from data until either all data has been sent or an - error occurs. None is returned on success. On error, an exception is - raised, and there is no way to determine how much data, if any, was - successfully processed by the receiving end of the connection. + The socket must be connected to a remote socket. This method + continues to send data from data until either all data has been + sent or an error occurs. None is returned on success. On error, + an exception is raised, and there is no way to determine how much + data, if any, was successfully processed by the receiving end of + the connection. """ base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: @@ -701,10 +703,11 @@ def _sock_connect_cb(self, fut, sock, address): async def sock_accept(self, sock): """Accept a connection. - The socket must be bound to an address and listening for connections. - The return value is a pair (conn, address) where conn is a new socket - object usable to send and receive data on the connection, and address - is the address bound to the socket on the other end of the connection. + The socket must be bound to an address and listening for + connections. The return value is a pair (conn, address) where + conn is a new socket object usable to send and receive data on the + connection, and address is the address bound to the socket on the + other end of the connection. """ base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index d2db1a930c2ad2b..a28c11e928f806a 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -539,17 +539,17 @@ async def _wait_for_data(self, func_name): self._waiter = None async def readline(self): - """Read chunk of data from the stream until newline (b'\n') is found. + r"""Read chunk of data from the stream until newline (b'\n') is found. - On success, return chunk that ends with newline. If only partial + On success, return chunk that ends with newline. If only partial line can be read due to EOF, return incomplete line without - terminating newline. When EOF was reached while no bytes read, empty - bytes object is returned. + terminating newline. When EOF was reached while no bytes read, + empty bytes object is returned. - If limit is reached, ValueError will be raised. In that case, if + If limit is reached, ValueError will be raised. In that case, if newline was found, complete line including newline will be removed - from internal buffer. Else, internal buffer will be cleared. Limit is - compared against part of the line without newline. + from internal buffer. Else, internal buffer will be cleared. + Limit is compared against part of the line without newline. If stream was paused, this function will automatically resume it if needed. diff --git a/Lib/asyncio/taskgroups.py b/Lib/asyncio/taskgroups.py index 45dfebc65904fce..e1ec025791a52e6 100644 --- a/Lib/asyncio/taskgroups.py +++ b/Lib/asyncio/taskgroups.py @@ -289,14 +289,14 @@ def cancel(self): """Cancel the task group `cancel()` will be called on any tasks in the group that aren't yet - done, as well as the parent (body) of the group. This will cause the - task group context manager to exit *without* `asyncio.CancelledError` - being raised. - - If `cancel()` is called before entering the task group, the group will be - cancelled upon entry. This is useful for patterns where one piece of - code passes an unused TaskGroup instance to another in order to have - the ability to cancel anything run within the group. + done, as well as the parent (body) of the group. This will cause + the task group context manager to exit *without* + `asyncio.CancelledError` being raised. + + If `cancel()` is called before entering the task group, the group + will be cancelled upon entry. This is useful for patterns where + one piece of code passes an unused TaskGroup instance to another in + order to have the ability to cancel anything run within the group. `cancel()` is idempotent and may be called after the task group has already exited. diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index fbd5c39a7c56ac4..14d3c1ceb58cacb 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -624,10 +624,11 @@ def as_completed(fs, *, timeout=None): Run the supplied awaitables concurrently. The returned object can be iterated to obtain the results of the awaitables as they finish. - The object returned can be iterated as an asynchronous iterator or a plain - iterator. When asynchronous iteration is used, the originally-supplied - awaitables are yielded if they are tasks or futures. This makes it easy to - correlate previously-scheduled tasks with their results: + The object returned can be iterated as an asynchronous iterator or + a plain iterator. When asynchronous iteration is used, the + originally-supplied awaitables are yielded if they are tasks or + futures. This makes it easy to correlate previously-scheduled tasks + with their results: ipv4_connect = create_task(open_connection("127.0.0.1", 80)) ipv6_connect = create_task(open_connection("::1", 80)) @@ -643,26 +644,27 @@ def as_completed(fs, *, timeout=None): else: print("IPv4 connection established.") - During asynchronous iteration, implicitly-created tasks will be yielded for - supplied awaitables that aren't tasks or futures. + During asynchronous iteration, implicitly-created tasks will be + yielded for supplied awaitables that aren't tasks or futures. - When used as a plain iterator, each iteration yields a new coroutine that - returns the result or raises the exception of the next completed awaitable. - This pattern is compatible with Python versions older than 3.13: + When used as a plain iterator, each iteration yields a new coroutine + that returns the result or raises the exception of the next completed + awaitable. This pattern is compatible with Python versions older than + 3.13: ipv4_connect = create_task(open_connection("127.0.0.1", 80)) ipv6_connect = create_task(open_connection("::1", 80)) tasks = [ipv4_connect, ipv6_connect] for next_connect in as_completed(tasks): - # next_connect is not one of the original task objects. It must be - # awaited to obtain the result value or raise the exception of the - # awaitable that finishes next. + # next_connect is not one of the original task objects. It must + # be awaited to obtain the result value or raise the exception + # of the awaitable that finishes next. reader, writer = await next_connect - A TimeoutError is raised if the timeout occurs before all awaitables are - done. This is raised by the async for loop during asynchronous iteration or - by the coroutines yielded during plain iteration. + A TimeoutError is raised if the timeout occurs before all awaitables + are done. This is raised by the async for loop during asynchronous + iteration or by the coroutines yielded during plain iteration. """ if inspect.isawaitable(fs): raise TypeError( @@ -1030,21 +1032,22 @@ def callback(): def create_eager_task_factory(custom_task_constructor): """Create a function suitable for use as a task factory on an event-loop. - Example usage: + Example usage: - loop.set_task_factory( - asyncio.create_eager_task_factory(my_task_constructor)) + loop.set_task_factory( + asyncio.create_eager_task_factory(my_task_constructor)) - Now, tasks created will be started immediately (rather than being first - scheduled to an event loop). The constructor argument can be any callable - that returns a Task-compatible object and has a signature compatible - with `Task.__init__`; it must have the `eager_start` keyword argument. + Now, tasks created will be started immediately (rather than being first + scheduled to an event loop). The constructor argument can be any + callable that returns a Task-compatible object and has a signature + compatible with `Task.__init__`; it must have the `eager_start` + keyword argument. - Most applications will use `Task` for `custom_task_constructor` and in - this case there's no need to call `create_eager_task_factory()` - directly. Instead the global `eager_task_factory` instance can be - used. E.g. `loop.set_task_factory(asyncio.eager_task_factory)`. - """ + Most applications will use `Task` for `custom_task_constructor` and in + this case there's no need to call `create_eager_task_factory()` + directly. Instead the global `eager_task_factory` instance can be + used. E.g. `loop.set_task_factory(asyncio.eager_task_factory)`. + """ def factory(loop, coro, *, eager_start=True, **kwargs): return custom_task_constructor( diff --git a/Lib/asyncio/threads.py b/Lib/asyncio/threads.py index db048a8231de166..5001351b0976ecd 100644 --- a/Lib/asyncio/threads.py +++ b/Lib/asyncio/threads.py @@ -17,7 +17,8 @@ async def to_thread(func, /, *args, **kwargs): allowing context variables from the main thread to be accessed in the separate thread. - Return a coroutine that can be awaited to get the eventual result of *func*. + Return a coroutine that can be awaited to get the eventual result of + *func*. """ loop = events.get_running_loop() ctx = contextvars.copy_context() diff --git a/Lib/asyncio/timeouts.py b/Lib/asyncio/timeouts.py index 09342dc7c1310b0..65ddc285abd971d 100644 --- a/Lib/asyncio/timeouts.py +++ b/Lib/asyncio/timeouts.py @@ -25,7 +25,8 @@ class _State(enum.Enum): class Timeout: """Asynchronous context manager for cancelling overdue coroutines. - Use `timeout()` or `timeout_at()` rather than instantiating this class directly. + Use `timeout()` or `timeout_at()` rather than instantiating this class + directly. """ def __init__(self, when: float | None) -> None: diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 646ae71bbf5919e..676e0b670faa49b 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -55,7 +55,8 @@ def waitstatus_to_exitcode(status): class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): """Unix event loop. - Adds signal handling and UNIX Domain Socket support to SelectorEventLoop. + Adds signal handling and UNIX Domain Socket support to + SelectorEventLoop. """ def __init__(self, selector=None): @@ -888,8 +889,8 @@ def _do_wait(self, pid, pidfd, callback, args): pid) else: returncode = waitstatus_to_exitcode(status) - - os.close(pidfd) + finally: + os.close(pidfd) callback(pid, returncode, *args) class _ThreadedChildWatcher: diff --git a/Lib/base64.py b/Lib/base64.py index 4a0e9d446edb0bc..fa562f74a810345 100644 --- a/Lib/base64.py +++ b/Lib/base64.py @@ -1,4 +1,4 @@ -"""Base16, Base32, Base64 (RFC 3548), Base85 and Ascii85 data encodings""" +"""Base16, Base32, Base64 (RFC 4648), Base85 and Ascii85 data encodings""" # Modified 04-Oct-1995 by Jack Jansen to use binascii module # Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support @@ -219,7 +219,7 @@ def urlsafe_b64decode(s, *, padded=False): characters present in the input. ''' _B32_DECODE_MAP01_DOCSTRING = ''' -RFC 3548 allows for optional mapping of the digit 0 (zero) to the +RFC 4648 allows for optional mapping of the digit 0 (zero) to the letter O (oh), and for optional mapping of the digit 1 (one) to either the letter I (eye) or letter L (el). The optional argument map01 when not None, specifies which letter the digit 1 should be @@ -266,7 +266,7 @@ def b32hexdecode(s, casefold=False, *, padded=True, ignorechars=b'', extra_args='') -# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns +# RFC 4648, Base 16 Alphabet specifies uppercase, but hexlify() returns # lowercase. The RFC also recommends against accepting input case # insensitively. def b16encode(s, *, wrapcol=0): diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index f506ce68aea5b29..4e71331f9a0a594 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -194,15 +194,15 @@ def as_completed(fs, timeout=None): """An iterator over the given futures that yields each as it completes. Args: - fs: The sequence of Futures (possibly created by different Executors) to - iterate over. - timeout: The maximum number of seconds to wait. If None, then there - is no limit on the wait time. + fs: The sequence of Futures (possibly created by different + Executors) to iterate over. + timeout: The maximum number of seconds to wait. If None, then + there is no limit on the wait time. Returns: - An iterator that yields the given Futures as they complete (finished or - cancelled). If any given Futures are duplicated, they will be returned - once. + An iterator that yields the given Futures as they complete + (finished or cancelled). If any given Futures are duplicated, + they will be returned once. Raises: TimeoutError: If the entire result iterator could not be generated @@ -258,19 +258,20 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED): """Wait for the futures in the given sequence to complete. Args: - fs: The sequence of Futures (possibly created by different Executors) to - wait upon. - timeout: The maximum number of seconds to wait. If None, then there - is no limit on the wait time. - return_when: Indicates when this function should return. The options - are: + fs: The sequence of Futures (possibly created by different + Executors) to wait upon. + timeout: The maximum number of seconds to wait. If None, then + there is no limit on the wait time. + return_when: Indicates when this function should return. + The options are: FIRST_COMPLETED - Return when any future finishes or is cancelled. FIRST_EXCEPTION - Return when any future finishes by raising an - exception. If no future raises an exception + exception. If no future raises an exception then it is equivalent to ALL_COMPLETED. - ALL_COMPLETED - Return when all futures finish or are cancelled. + ALL_COMPLETED - Return when all futures finish or are + cancelled. Returns: A named 2-tuple of sets. The first set, named 'done', contains the @@ -404,11 +405,12 @@ def add_done_callback(self, fn): Args: fn: A callable that will be called with this future as its only - argument when the future completes or is cancelled. The callable - will always be called by a thread in the same process in which - it was added. If the future has already completed or been - cancelled then the callable will be called immediately. These - callables are called in the order that they were added. + argument when the future completes or is cancelled. The + callable will always be called by a thread in the same + process in which it was added. If the future has already + completed or been cancelled then the callable will be + called immediately. These callables are called in the + order that they were added. """ with self._condition: if self._state not in [CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED]: @@ -423,17 +425,19 @@ def result(self, timeout=None): """Return the result of the call that the future represents. Args: - timeout: The number of seconds to wait for the result if the future - isn't done. If None, then there is no limit on the wait time. + timeout: The number of seconds to wait for the result if the + future isn't done. If None, then there is no limit on the + wait time. Returns: The result of the call that the future represents. Raises: CancelledError: If the future was cancelled. - TimeoutError: If the future didn't finish executing before the given - timeout. - Exception: If the call raised then that exception will be raised. + TimeoutError: If the future didn't finish executing before the + given timeout. + Exception: If the call raised then that exception will be + raised. """ try: with self._condition: @@ -459,17 +463,17 @@ def exception(self, timeout=None): Args: timeout: The number of seconds to wait for the exception if the - future isn't done. If None, then there is no limit on the wait - time. + future isn't done. If None, then there is no limit on the + wait time. Returns: - The exception raised by the call that the future represents or None - if the call completed without raising. + The exception raised by the call that the future represents or + None if the call completed without raising. Raises: CancelledError: If the future was cancelled. - TimeoutError: If the future didn't finish executing before the given - timeout. + TimeoutError: If the future didn't finish executing before the + given timeout. """ with self._condition: @@ -494,22 +498,23 @@ def set_running_or_notify_cancel(self): Should only be used by Executor implementations and unit tests. If the future has been cancelled (cancel() was called and returned - True) then any threads waiting on the future completing (though calls - to as_completed() or wait()) are notified and False is returned. + True) then any threads waiting on the future completing (though + calls to as_completed() or wait()) are notified and False is + returned. If the future was not cancelled then it is put in the running state (future calls to running() will return True) and True is returned. This method should be called by Executor implementations before - executing the work associated with this future. If this method returns - False then the work should not be executed. + executing the work associated with this future. If this method + returns False then the work should not be executed. Returns: False if the Future was cancelled, True otherwise. Raises: - RuntimeError: if this method was already called or if set_result() - or set_exception() was called. + RuntimeError: if this method was already called or if + set_result() or set_exception() was called. """ with self._condition: if self._state == CANCELLED: @@ -593,8 +598,9 @@ class Executor(object): def submit(self, fn, /, *args, **kwargs): """Submits a callable to be executed with the given arguments. - Schedules the callable to be executed as fn(*args, **kwargs) and returns - a Future instance representing the execution of the callable. + Schedules the callable to be executed as fn(*args, **kwargs) and + returns a Future instance representing the execution of the + callable. Returns: A Future representing the given call. @@ -607,25 +613,25 @@ def map(self, fn, *iterables, timeout=None, chunksize=1, buffersize=None): Args: fn: A callable that will take as many arguments as there are passed iterables. - timeout: The maximum number of seconds to wait. If None, then there - is no limit on the wait time. - chunksize: The size of the chunks the iterable will be broken into - before being passed to a child process. This argument is only - used by ProcessPoolExecutor; it is ignored by + timeout: The maximum number of seconds to wait. If None, then + there is no limit on the wait time. + chunksize: The size of the chunks the iterable will be broken + into before being passed to a child process. This argument + is only used by ProcessPoolExecutor; it is ignored by ThreadPoolExecutor. buffersize: The number of submitted tasks whose results have not - yet been yielded. If the buffer is full, iteration over the + yet been yielded. If the buffer is full, iteration over the iterables pauses until a result is yielded from the buffer. - If None, all input elements are eagerly collected, and a task is - submitted for each. + If None, all input elements are eagerly collected, and + a task is submitted for each. Returns: - An iterator equivalent to: map(func, *iterables) but the calls may - be evaluated out-of-order. + An iterator equivalent to: map(func, *iterables) but the calls + may be evaluated out-of-order. Raises: - TimeoutError: If the entire result iterator could not be generated - before the given timeout. + TimeoutError: If the entire result iterator could not be + generated before the given timeout. Exception: If fn(*args) raises for any values. """ if buffersize is not None and not isinstance(buffersize, int): @@ -679,8 +685,8 @@ def shutdown(self, wait=True, *, cancel_futures=False): Args: wait: If True then shutdown will not return until all running - futures have finished executing and the resources used by the - executor have been reclaimed. + futures have finished executing and the resources used by + the executor have been reclaimed. cancel_futures: If True then shutdown will cancel all pending futures. Futures that are completed or running will not be cancelled. diff --git a/Lib/concurrent/futures/interpreter.py b/Lib/concurrent/futures/interpreter.py index 85c1da2c7228943..fd3d45144b49a71 100644 --- a/Lib/concurrent/futures/interpreter.py +++ b/Lib/concurrent/futures/interpreter.py @@ -110,8 +110,8 @@ def __init__(self, max_workers=None, thread_name_prefix='', """Initializes a new InterpreterPoolExecutor instance. Args: - max_workers: The maximum number of interpreters that can be used to - execute the given calls. + max_workers: The maximum number of interpreters that can be used + to execute the given calls. thread_name_prefix: An optional name prefix to give our threads. initializer: A callable or script used to initialize each worker interpreter. diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index a42afa68efcb148..10d4ac89d725713 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -469,11 +469,9 @@ def _terminate_broken(self, cause): executor._shutdown_thread = True executor = None - # All pending tasks are to be marked failed with the following - # BrokenProcessPool error - bpe = BrokenProcessPool("A process in the process pool was " - "terminated abruptly while the future was " - "running or pending.") + # All pending tasks are to be marked failed with a + # BrokenProcessPool error, as separate instances to avoid sharing + # a traceback (gh-101267). cause_str = None if cause is not None: cause_str = ''.join(cause) @@ -489,11 +487,15 @@ def _terminate_broken(self, cause): f"with exit code {p.exitcode}") if errors: cause_str = "\n".join(errors) - if cause_str: - bpe.__cause__ = _RemoteTraceback(f"\n'''\n{cause_str}'''") + cause_tb = f"\n'''\n{cause_str}'''" if cause_str else None # Mark pending tasks as failed. for work_id, work_item in self.pending_work_items.items(): + bpe = BrokenProcessPool("A process in the process pool was " + "terminated abruptly while the future was " + "running or pending.") + if cause_tb is not None: + bpe.__cause__ = _RemoteTraceback(cause_tb) try: work_item.future.set_exception(bpe) except _base.InvalidStateError: @@ -656,19 +658,21 @@ def __init__(self, max_workers=None, mp_context=None, Args: max_workers: The maximum number of processes that can be used to - execute the given calls. If None or not given then as many - worker processes will be created as the machine has processors. - mp_context: A multiprocessing context to launch the workers created - using the multiprocessing.get_context('start method') API. This - object should provide SimpleQueue, Queue and Process. + execute the given calls. If None or not given then as many + worker processes will be created as the machine has + processors. + mp_context: A multiprocessing context to launch the workers + created using the multiprocessing.get_context('start method') + API. This object should provide SimpleQueue, Queue and + Process. initializer: A callable used to initialize worker processes. initargs: A tuple of arguments to pass to the initializer. - max_tasks_per_child: The maximum number of tasks a worker process - can complete before it will exit and be replaced with a fresh - worker process. The default of None means worker process will - live as long as the executor. Requires a non-'fork' mp_context - start method. When given, we default to using 'spawn' if no - mp_context is supplied. + max_tasks_per_child: The maximum number of tasks a worker + process can complete before it will exit and be replaced + with a fresh worker process. The default of None means + worker process will live as long as the executor. Requires + a non-'fork' mp_context start method. When given, we + default to using 'spawn' if no mp_context is supplied. """ _check_system_limits() @@ -838,24 +842,25 @@ def map(self, fn, *iterables, timeout=None, chunksize=1, buffersize=None): Args: fn: A callable that will take as many arguments as there are passed iterables. - timeout: The maximum number of seconds to wait. If None, then there - is no limit on the wait time. - chunksize: If greater than one, the iterables will be chopped into - chunks of size chunksize and submitted to the process pool. - If set to one, the items in the list will be sent one at a time. + timeout: The maximum number of seconds to wait. If None, then + there is no limit on the wait time. + chunksize: If greater than one, the iterables will be chopped + into chunks of size chunksize and submitted to the process + pool. If set to one, the items in the list will be sent + one at a time. buffersize: The number of submitted tasks whose results have not - yet been yielded. If the buffer is full, iteration over the + yet been yielded. If the buffer is full, iteration over the iterables pauses until a result is yielded from the buffer. - If None, all input elements are eagerly collected, and a task is - submitted for each. + If None, all input elements are eagerly collected, and + a task is submitted for each. Returns: - An iterator equivalent to: map(func, *iterables) but the calls may - be evaluated out-of-order. + An iterator equivalent to: map(func, *iterables) but the calls + may be evaluated out-of-order. Raises: - TimeoutError: If the entire result iterator could not be generated - before the given timeout. + TimeoutError: If the entire result iterator could not be + generated before the given timeout. Exception: If fn(*args) raises for any values. """ if chunksize < 1: diff --git a/Lib/concurrent/interpreters/_queues.py b/Lib/concurrent/interpreters/_queues.py index ee159d7de638272..5f3ee0934de59d6 100644 --- a/Lib/concurrent/interpreters/_queues.py +++ b/Lib/concurrent/interpreters/_queues.py @@ -185,7 +185,8 @@ def put(self, obj, block=True, timeout=None, *, underlying data is actually shared. Furthermore, some types can be sent through a queue more efficiently than others. This group includes various immutable types like int, str, bytes, and - tuple (if the items are likewise efficiently shareable). See interpreters.is_shareable(). + tuple (if the items are likewise efficiently shareable). + See interpreters.is_shareable(). "unbounditems" controls the behavior of Queue.get() for the given object if the current interpreter (calling put()) is later diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 035678d902adaf9..bd317aa9b0f2f37 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1250,6 +1250,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen, # classes with slots. These could be slightly more performant if we generated # the code instead of iterating over fields. But that can be a project for # another day, if performance becomes an issue. + def _dataclass_getstate(self): return [getattr(self, f.name) for f in fields(self)] diff --git a/Lib/email/charset.py b/Lib/email/charset.py index c4b246455f86c64..5981791820e740c 100644 --- a/Lib/email/charset.py +++ b/Lib/email/charset.py @@ -9,6 +9,7 @@ 'add_codec', ] +import codecs from functools import partial import email.base64mime @@ -58,37 +59,71 @@ 'shift_jis': (BASE64, None, 'iso-2022-jp'), 'iso-2022-jp': (BASE64, None, None), 'koi8-r': (BASE64, BASE64, None), - 'utf-8': (SHORTEST, BASE64, 'utf-8'), } -# Aliases for other commonly-used names for character sets. Map -# them to the real ones used in email. +# Map Python codec names to their corresponding MIME/IANA names. ALIASES = { - 'latin_1': 'iso-8859-1', - 'latin-1': 'iso-8859-1', - 'latin_2': 'iso-8859-2', - 'latin-2': 'iso-8859-2', - 'latin_3': 'iso-8859-3', - 'latin-3': 'iso-8859-3', - 'latin_4': 'iso-8859-4', - 'latin-4': 'iso-8859-4', - 'latin_5': 'iso-8859-9', - 'latin-5': 'iso-8859-9', - 'latin_6': 'iso-8859-10', - 'latin-6': 'iso-8859-10', - 'latin_7': 'iso-8859-13', - 'latin-7': 'iso-8859-13', - 'latin_8': 'iso-8859-14', - 'latin-8': 'iso-8859-14', - 'latin_9': 'iso-8859-15', - 'latin-9': 'iso-8859-15', - 'latin_10':'iso-8859-16', - 'latin-10':'iso-8859-16', - 'cp949': 'ks_c_5601-1987', - 'euc_jp': 'euc-jp', - 'euc_kr': 'euc-kr', - 'ascii': 'us-ascii', - } + 'ascii': 'us-ascii', + 'big5hkscs': 'big5-hkscs', + 'cp037': 'ibm037', + 'cp1026': 'ibm1026', + 'cp1140': 'ibm01140', + 'cp1250': 'windows-1250', + 'cp1251': 'windows-1251', + 'cp1252': 'windows-1252', + 'cp1253': 'windows-1253', + 'cp1254': 'windows-1254', + 'cp1255': 'windows-1255', + 'cp1256': 'windows-1256', + 'cp1257': 'windows-1257', + 'cp1258': 'windows-1258', + 'cp273': 'ibm273', + 'cp424': 'ibm424', + 'cp437': 'ibm437', + 'cp500': 'ibm500', + 'cp775': 'ibm775', + 'cp850': 'ibm850', + 'cp852': 'ibm852', + 'cp855': 'ibm855', + 'cp857': 'ibm857', + 'cp858': 'ibm00858', + 'cp860': 'ibm860', + 'cp861': 'ibm861', + 'cp862': 'ibm862', + 'cp863': 'ibm863', + 'cp864': 'ibm864', + 'cp865': 'ibm865', + 'cp866': 'ibm866', + 'cp869': 'ibm869', + 'cp874': 'windows-874', + 'euc_jp': 'euc-jp', + 'euc_kr': 'euc-kr', + 'hz': 'hz-gb-2312', + 'iso2022_jp': 'iso-2022-jp', + 'iso2022_jp_2': 'iso-2022-jp-2', + 'iso2022_kr': 'iso-2022-kr', + 'iso8859-1': 'iso-8859-1', + 'iso8859-10': 'iso-8859-10', + 'iso8859-11': 'iso-8859-11', + 'iso8859-13': 'iso-8859-13', + 'iso8859-14': 'iso-8859-14', + 'iso8859-15': 'iso-8859-15', + 'iso8859-16': 'iso-8859-16', + 'iso8859-2': 'iso-8859-2', + 'iso8859-3': 'iso-8859-3', + 'iso8859-4': 'iso-8859-4', + 'iso8859-5': 'iso-8859-5', + 'iso8859-6': 'iso-8859-6', + 'iso8859-7': 'iso-8859-7', + 'iso8859-8': 'iso-8859-8-i', + 'iso8859-9': 'iso-8859-9', + 'kz1048': 'kz-1048', + 'mac-roman': 'macintosh', + + # CP949 is not registered in IANA. KS_C_5601-1987 is not the same, + # but the closest registered option. + 'cp949': 'ks_c_5601-1987', +} # Map charsets to their Unicode codec strings. @@ -215,7 +250,18 @@ def __init__(self, input_charset=DEFAULT_CHARSET): raise errors.CharsetError(input_charset) input_charset = input_charset.lower() # Set the input charset after filtering through the aliases - self.input_charset = ALIASES.get(input_charset, input_charset) + # For backward compatibility, try ALIASES first to let the user + # override it. + if input_charset in ALIASES: + input_charset = ALIASES[input_charset] + else: + try: + input_codec = codecs.lookup(input_charset).name + except LookupError: + pass + else: + input_charset = ALIASES.get(input_codec, input_codec) + self.input_charset = input_charset # We can try to guess which encoding and conversion to use by the # charset_map dictionary. Try that first, but let the user override # it. diff --git a/Lib/email/contentmanager.py b/Lib/email/contentmanager.py index 13fcb9787f1f320..c0090af716575d7 100644 --- a/Lib/email/contentmanager.py +++ b/Lib/email/contentmanager.py @@ -173,11 +173,12 @@ def set_text_content(msg, string, subtype="plain", charset='utf-8', cte=None, disposition=None, filename=None, cid=None, params=None, headers=None): _prepare_set(msg, 'text', subtype, headers) + + cs = email.charset.Charset(charset) + charset = cs.output_charset cte, payload = _encode_text(string, charset, cte, msg.policy) msg.set_payload(payload) - msg.set_param('charset', - email.charset.ALIASES.get(charset, charset), - replace=True) + msg.set_param('charset', charset, replace=True) msg['Content-Transfer-Encoding'] = cte _finalize_set(msg, disposition, filename, cid, params) raw_data_manager.add_set_handler(str, set_text_content) diff --git a/Lib/encodings/aliases.py b/Lib/encodings/aliases.py index e5e50630f33d14d..ef51168d755ba98 100644 --- a/Lib/encodings/aliases.py +++ b/Lib/encodings/aliases.py @@ -43,6 +43,7 @@ # big5hkscs codec 'big5_hkscs' : 'big5hkscs', + 'csbig5hkscs' : 'big5hkscs', 'hkscs' : 'big5hkscs', # bz2_codec codec @@ -71,6 +72,7 @@ # cp1140 codec '1140' : 'cp1140', + 'ccsid01140' : 'cp1140', 'cp01140' : 'cp1140', 'csibm01140' : 'cp1140', 'ebcdic_us_37_euro' : 'cp1140', @@ -79,38 +81,47 @@ # cp1250 codec '1250' : 'cp1250', + 'cswindows1250' : 'cp1250', 'windows_1250' : 'cp1250', # cp1251 codec '1251' : 'cp1251', + 'cswindows1251' : 'cp1251', 'windows_1251' : 'cp1251', # cp1252 codec '1252' : 'cp1252', + 'cswindows1252' : 'cp1252', 'windows_1252' : 'cp1252', # cp1253 codec '1253' : 'cp1253', + 'cswindows1253' : 'cp1253', 'windows_1253' : 'cp1253', # cp1254 codec '1254' : 'cp1254', + 'cswindows1254' : 'cp1254', 'windows_1254' : 'cp1254', # cp1255 codec '1255' : 'cp1255', + 'cswindows1255' : 'cp1255', 'windows_1255' : 'cp1255', # cp1256 codec '1256' : 'cp1256', + 'cswindows1256' : 'cp1256', 'windows_1256' : 'cp1256', # cp1257 codec '1257' : 'cp1257', + 'cswindows1257' : 'cp1257', 'windows_1257' : 'cp1257', # cp1258 codec '1258' : 'cp1258', + 'cswindows1258' : 'cp1258', 'windows_1258' : 'cp1258', # cp273 codec @@ -163,6 +174,7 @@ # cp858 codec '858' : 'cp858', + 'ccsid00858' : 'cp858', 'cp00858' : 'cp858', 'csibm00858' : 'cp858', 'csibm858' : 'cp858', @@ -214,11 +226,13 @@ # cp874 codec '874' : 'cp874', + 'cswindows874' : 'cp874', 'ms874' : 'cp874', 'windows_874' : 'cp874', # cp932 codec '932' : 'cp932', + 'cswindows31j' : 'cp932', 'ms932' : 'cp932', 'mskanji' : 'cp932', 'ms_kanji' : 'cp932', @@ -226,6 +240,16 @@ # cp949 codec '949' : 'cp949', + 'csksc56011987' : 'cp949', + 'iso_ir_149' : 'cp949', + 'korean' : 'cp949', + 'ks_c_5601_1987' : 'cp949', + 'ks_c_5601_1989' : 'cp949', + 'ksc5601' : 'cp949', + 'ks_c_5601' : 'cp949', + 'ksc_5601' : 'cp949', + 'ksx1001' : 'cp949', + 'ks_x_1001' : 'cp949', 'ms949' : 'cp949', 'uhc' : 'cp949', @@ -242,47 +266,47 @@ 'eucjisx0213' : 'euc_jisx0213', # euc_jp codec + 'cseucpkdfmtjapanese' : 'euc_jp', 'eucjp' : 'euc_jp', 'ujis' : 'euc_jp', 'u_jis' : 'euc_jp', # euc_kr codec - 'euckr' : 'euc_kr', - 'korean' : 'euc_kr', - 'ksc5601' : 'euc_kr', - 'ks_c_5601' : 'euc_kr', - 'ks_c_5601_1987' : 'euc_kr', - 'ksx1001' : 'euc_kr', - 'ks_x_1001' : 'euc_kr', 'cseuckr' : 'euc_kr', + 'euckr' : 'euc_kr', # gb18030 codec + 'csgb18030' : 'gb18030', 'gb18030_2000' : 'gb18030', # gb2312 codec 'chinese' : 'gb2312', + 'csgb2312' : 'gb2312', 'csiso58gb231280' : 'gb2312', 'euc_cn' : 'gb2312', 'euccn' : 'gb2312', 'eucgb2312_cn' : 'gb2312', 'gb2312_1980' : 'gb2312', 'gb2312_80' : 'gb2312', + 'gb_2312_80' : 'gb2312', 'iso_ir_58' : 'gb2312', # gbk codec '936' : 'gbk', 'cp936' : 'gbk', + 'csgbk' : 'gbk', 'ms936' : 'gbk', + 'windows_936' : 'gbk', # hex_codec codec 'hex' : 'hex_codec', # hp_roman8 codec - 'roman8' : 'hp_roman8', - 'r8' : 'hp_roman8', - 'csHPRoman8' : 'hp_roman8', 'cp1051' : 'hp_roman8', + 'cshproman8' : 'hp_roman8', 'ibm1051' : 'hp_roman8', + 'r8' : 'hp_roman8', + 'roman8' : 'hp_roman8', # hz codec 'hzgb' : 'hz', @@ -299,6 +323,7 @@ 'iso_2022_jp_1' : 'iso2022_jp_1', # iso2022_jp_2 codec + 'csiso2022jp2' : 'iso2022_jp_2', 'iso2022jp_2' : 'iso2022_jp_2', 'iso_2022_jp_2' : 'iso2022_jp_2', @@ -334,12 +359,14 @@ 'iso_8859_11_2001' : 'iso8859_11', # iso8859_13 codec + 'csiso885913' : 'iso8859_13', 'iso_8859_13' : 'iso8859_13', 'l7' : 'iso8859_13', 'latin7' : 'iso8859_13', 'latin_7' : 'iso8859_13', # iso8859_14 codec + 'csiso885914' : 'iso8859_14', 'iso_8859_14' : 'iso8859_14', 'iso_8859_14_1998' : 'iso8859_14', 'iso_celtic' : 'iso8859_14', @@ -349,12 +376,14 @@ 'latin_8' : 'iso8859_14', # iso8859_15 codec + 'csiso885915' : 'iso8859_15', 'iso_8859_15' : 'iso8859_15', 'l9' : 'iso8859_15', 'latin9' : 'iso8859_15', 'latin_9' : 'iso8859_15', # iso8859_16 codec + 'csiso885916' : 'iso8859_16', 'iso_8859_16' : 'iso8859_16', 'iso_8859_16_2001' : 'iso8859_16', 'iso_ir_226' : 'iso8859_16', @@ -416,6 +445,8 @@ 'iso_ir_126' : 'iso8859_7', # iso8859_8 codec + 'csiso88598e' : 'iso8859_8', + 'csiso88598i' : 'iso8859_8', 'csisolatinhebrew' : 'iso8859_8', 'hebrew' : 'iso8859_8', 'iso_8859_8' : 'iso8859_8', @@ -440,7 +471,11 @@ # koi8_r codec 'cskoi8r' : 'koi8_r', + # koi8_u codec + 'cskoi8u' : 'koi8_u', + # kz1048 codec + 'cskz1048' : 'kz1048', 'kz_1048' : 'kz1048', 'rk1048' : 'kz1048', 'strk1048_2002' : 'kz1048', @@ -480,7 +515,9 @@ 'maclatin2' : 'mac_latin2', # mac_roman codec + 'csmacintosh' : 'mac_roman', 'macintosh' : 'mac_roman', + 'mac' : 'mac_roman', 'macroman' : 'mac_roman', # mac_turkish codec @@ -521,6 +558,7 @@ 's_jisx0213' : 'shift_jisx0213', # tis_620 codec + 'cstis620' : 'tis_620', 'tis620' : 'tis_620', 'tis_620_0' : 'tis_620', 'tis_620_2529_0' : 'tis_620', @@ -528,33 +566,42 @@ 'iso_ir_166' : 'tis_620', # utf_16 codec + 'csutf16' : 'utf_16', 'u16' : 'utf_16', 'utf16' : 'utf_16', # utf_16_be codec + 'csutf16be' : 'utf_16_be', 'unicodebigunmarked' : 'utf_16_be', 'utf_16be' : 'utf_16_be', # utf_16_le codec + 'csutf16le' : 'utf_16_le', 'unicodelittleunmarked' : 'utf_16_le', 'utf_16le' : 'utf_16_le', # utf_32 codec + 'csutf32' : 'utf_32', 'u32' : 'utf_32', 'utf32' : 'utf_32', # utf_32_be codec + 'csutf32be' : 'utf_32_be', 'utf_32be' : 'utf_32_be', # utf_32_le codec + 'csutf32le' : 'utf_32_le', 'utf_32le' : 'utf_32_le', # utf_7 codec + 'csunicode11utf7' : 'utf_7', + 'csutf7' : 'utf_7', 'u7' : 'utf_7', 'utf7' : 'utf_7', 'unicode_1_1_utf_7' : 'utf_7', # utf_8 codec + 'csutf8' : 'utf_8', 'u8' : 'utf_8', 'utf' : 'utf_8', 'utf8' : 'utf_8', diff --git a/Lib/enum.py b/Lib/enum.py index f97a5193492e602..7aff36c94ce1dcf 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -1620,10 +1620,14 @@ def __or__(self, other): if other_value is NotImplemented: return NotImplemented - for flag in self, other: - if self._get_value(flag) is None: - raise TypeError(f"'{flag}' cannot be combined with other flags with |") value = self._value_ + # _get_value(self) is self._value_ and _get_value(other) is + # other_value, so only walk the operands (to raise on the offending + # flag) when one of those values is actually None. + if value is None or other_value is None: + for flag in self, other: + if self._get_value(flag) is None: + raise TypeError(f"'{flag}' cannot be combined with other flags with |") return self.__class__(value | other_value) def __and__(self, other): @@ -1631,10 +1635,11 @@ def __and__(self, other): if other_value is NotImplemented: return NotImplemented - for flag in self, other: - if self._get_value(flag) is None: - raise TypeError(f"'{flag}' cannot be combined with other flags with &") value = self._value_ + if value is None or other_value is None: + for flag in self, other: + if self._get_value(flag) is None: + raise TypeError(f"'{flag}' cannot be combined with other flags with &") return self.__class__(value & other_value) def __xor__(self, other): @@ -1642,10 +1647,11 @@ def __xor__(self, other): if other_value is NotImplemented: return NotImplemented - for flag in self, other: - if self._get_value(flag) is None: - raise TypeError(f"'{flag}' cannot be combined with other flags with ^") value = self._value_ + if value is None or other_value is None: + for flag in self, other: + if self._get_value(flag) is None: + raise TypeError(f"'{flag}' cannot be combined with other flags with ^") return self.__class__(value ^ other_value) def __invert__(self): diff --git a/Lib/idlelib/idle_test/template.py b/Lib/idlelib/idle_test/template.py index 725a55b9c47230c..6e98556458ec588 100644 --- a/Lib/idlelib/idle_test/template.py +++ b/Lib/idlelib/idle_test/template.py @@ -1,6 +1,5 @@ "Test , coverage %." -from idlelib import zzdummy import unittest from test.support import requires from tkinter import Tk diff --git a/Lib/idlelib/idle_test/test_help.py b/Lib/idlelib/idle_test/test_help.py index ebb02b5c0d8356a..ebbaceb2eb7bbfd 100644 --- a/Lib/idlelib/idle_test/test_help.py +++ b/Lib/idlelib/idle_test/test_help.py @@ -4,7 +4,6 @@ import unittest from test.support import requires requires('gui') -from os.path import abspath, dirname, join from tkinter import Tk diff --git a/Lib/idlelib/iomenu.py b/Lib/idlelib/iomenu.py index 464126e2df06682..fc502f7fde17808 100644 --- a/Lib/idlelib/iomenu.py +++ b/Lib/idlelib/iomenu.py @@ -61,6 +61,7 @@ def set_filename_change_hook(self, hook): self.filename_change_hook = hook filename = None + file_timestamp = None dirname = None def set_filename(self, filename): @@ -127,6 +128,7 @@ def loadfile(self, filename): chars = f.read() fileencoding = f.encoding eol_convention = f.newlines + file_timestamp = self.getmtime(filename) converted = False except (UnicodeDecodeError, SyntaxError): # Wait for the editor window to appear @@ -142,6 +144,7 @@ def loadfile(self, filename): chars = f.read() fileencoding = f.encoding eol_convention = f.newlines + file_timestamp = self.getmtime(filename) converted = True except OSError as err: messagebox.showerror("I/O Error", str(err), parent=self.text) @@ -170,6 +173,7 @@ def loadfile(self, filename): self.text.insert("1.0", chars) self.reset_undo() self.set_filename(filename) + self.file_timestamp = file_timestamp if converted: # We need to save the conversion results first # before being able to execute the code @@ -206,7 +210,26 @@ def save(self, event): if not self.filename: self.save_as(event) else: + # Check the time of most recent content modification so the + # user doesn't accidentally overwrite a newer version of the file. + try: + file_timestamp = self.getmtime(self.filename) + except OSError: + pass + else: + if self.file_timestamp != file_timestamp: + confirm = messagebox.askokcancel( + title="File has changed", + message=( + "The file has changed on disk since reading it!\n\n" + "Do you really want to overwrite it?"), + default=messagebox.CANCEL, + parent=self.text) + if not confirm: + return "break" + if self.writefile(self.filename): + self.file_timestamp = self.getmtime(self.filename) self.set_saved(True) try: self.editwin.store_file_breaks() @@ -219,6 +242,7 @@ def save_as(self, event): filename = self.asksavefile() if filename: if self.writefile(filename): + self.file_timestamp = self.getmtime(filename) self.set_filename(filename) self.set_saved(1) try: @@ -251,6 +275,9 @@ def writefile(self, filename): parent=self.text) return False + def getmtime(self, filename): + return os.stat(filename).st_mtime + def fixnewlines(self): """Return text with os eols. diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 06dc45d71d7ca4a..eb1686a5c8217c6 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -20,12 +20,6 @@ # reference any injected objects! This includes not only global code but also # anything specified at the class level. -def _object_name(obj): - try: - return obj.__qualname__ - except AttributeError: - return type(obj).__qualname__ - # Bootstrap-related code ###################################################### # Modules injected manually by _setup() diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 6eef90ae5cd9143..b4a5f5cc2f598f5 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -1373,9 +1373,17 @@ def getLogger(self, name): logger and fix up the parent/child references which pointed to the placeholder to now point to the logger. """ - rv = None if not isinstance(name, str): raise TypeError('A logger name must be a string') + # Fast path: an already-registered, non-placeholder logger can be + # returned without taking the lock. dict.get() is atomic under both + # the GIL and free threading. A Logger is inserted into loggerDict only + # after it is fully wired up (parent/child references fixed) under the + # lock, so the fast path never observes a logger whose parent is not yet + # set. + rv = self.loggerDict.get(name) + if rv is not None and not isinstance(rv, PlaceHolder): + return rv with _lock: if name in self.loggerDict: rv = self.loggerDict[name] @@ -1383,14 +1391,18 @@ def getLogger(self, name): ph = rv rv = (self.loggerClass or _loggerClass)(name) rv.manager = self - self.loggerDict[name] = rv self._fixupChildren(ph, rv) self._fixupParents(rv) + # Publish only after rv is fully wired: the fast path reads + # loggerDict without the lock. + self.loggerDict[name] = rv else: rv = (self.loggerClass or _loggerClass)(name) rv.manager = self - self.loggerDict[name] = rv self._fixupParents(rv) + # Publish only after rv is fully wired: the fast path reads + # loggerDict without the lock. + self.loggerDict[name] = rv return rv def setLoggerClass(self, klass): diff --git a/Lib/logging/config.py b/Lib/logging/config.py index e39dac432f6ab5c..35233e731eb42d1 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -21,7 +21,7 @@ Copyright (C) 2001-2022 Vinay Sajip. All Rights Reserved. -To use, simply 'import logging' and log away! +To use, simply 'import logging.config' and log away! """ import errno diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 575f2babbc47853..a5394d2dbea6494 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -282,7 +282,30 @@ def __init__(self, filename, when='h', interval=1, backupCount=0, # path object (see Issue #27493), but self.baseFilename will be a string filename = self.baseFilename if os.path.exists(filename): - t = int(os.stat(filename).st_mtime) + # Use the minimum of file creation and modification time as + # the base of the rollover calculation + creation_time = modification_time = None + if hasattr(os, 'statx'): + statx_result = os.statx(filename, + os.STATX_BTIME|os.STATX_CTIME|os.STATX_MTIME) + # Use stx_btime whenever it is available or use stx_ctime + # instead otherwise + creation_time = statx_result.stx_btime + if creation_time is None: + creation_time = statx_result.stx_ctime + modification_time = statx_result.stx_mtime + if creation_time is None or modification_time is None: + stat_result = os.stat(filename) + # Use st_birthtime whenever it is available or use st_ctime + # instead otherwise + if creation_time is None: + try: + creation_time = stat_result.st_birthtime + except AttributeError: + creation_time = stat_result.st_ctime + if modification_time is None: + modification_time = stat_result.st_mtime + t = int(min(creation_time, modification_time)) else: t = int(time.time()) self.rolloverAt = self.computeRollover(t) diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py index 15e8c0a437bfd93..4339ef5a61397dd 100644 --- a/Lib/mimetypes.py +++ b/Lib/mimetypes.py @@ -86,6 +86,9 @@ def add_type(self, type, ext, strict=True): is already known the extension will be added to the list of known extensions. + Registered lower-case extensions are matched + case-insensitively. + If strict is true, information will be added to list of standard types, else to the list of non-standard types. @@ -172,23 +175,33 @@ def guess_file_type(self, path, *, strict=True): def _guess_file_type(self, path, strict, splitext): base, ext = splitext(path) - while (ext_lower := ext.lower()) in self.suffix_map: - base, ext = splitext(base + self.suffix_map[ext_lower]) + while True: + if ext in self.suffix_map: + suffix = self.suffix_map[ext] + elif (ext_lower := ext.lower()) in self.suffix_map: + suffix = self.suffix_map[ext_lower] + else: + break + base, ext = splitext(base + suffix) # encodings_map is case sensitive if ext in self.encodings_map: encoding = self.encodings_map[ext] base, ext = splitext(base) else: encoding = None - ext = ext.lower() + ext_lower = ext.lower() types_map = self.types_map[True] if ext in types_map: return types_map[ext], encoding + if ext_lower in types_map: + return types_map[ext_lower], encoding elif strict: return None, encoding types_map = self.types_map[False] if ext in types_map: return types_map[ext], encoding + if ext_lower in types_map: + return types_map[ext_lower], encoding else: return None, encoding @@ -386,6 +399,9 @@ def add_type(type, ext, strict=True): is already known the extension will be added to the list of known extensions. + Registered lower-case extensions are matched + case-insensitively. + If strict is true, information will be added to list of standard types, else to the list of non-standard types. diff --git a/Lib/profiling/sampling/gecko_collector.py b/Lib/profiling/sampling/gecko_collector.py index 54392af95000082..361f6037f216fdc 100644 --- a/Lib/profiling/sampling/gecko_collector.py +++ b/Lib/profiling/sampling/gecko_collector.py @@ -1,8 +1,10 @@ import itertools +import io import json import os import platform import sys +import tempfile import threading import time @@ -61,6 +63,77 @@ PROCESS_TYPE_MAIN = 0 STACKWALK_DISABLED = 0 +# In-memory buffer before spilling to disk +DEFAULT_SPILL_BUFFER_BYTES = 128 * 1024 +_JSON_SEPARATORS = (",", ":") +_JSON_ENCODER = json.JSONEncoder( + separators=_JSON_SEPARATORS, allow_nan=False +) + + +class SpillColumn: + def __init__(self, directory, basename, *, + buffer_bytes=None): + self.path = os.path.join(directory, basename) + self.buffer = bytearray() + self._buffer_bytes = ( + DEFAULT_SPILL_BUFFER_BYTES if buffer_bytes is None + else buffer_bytes + ) + + def append(self, value): + self.buffer += (_JSON_ENCODER.encode(value) + "\n").encode("utf-8") + if len(self.buffer) >= self._buffer_bytes: + self.flush() + + def flush(self): + with open(self.path, "ab") as file: + file.write(self.buffer) + self.buffer.clear() + + def iter_tokens(self): + with open(self.path, encoding="utf-8") as file: + for line in file: + yield line.rstrip("\n") + + +class GeckoThreadSpill: + _COLUMNS = ( + ("samples_stack", "samples-stack.json"), + ("samples_time", "samples-time.json"), + ("markers_name", "markers-name.json"), + ("markers_start_time", "markers-start-time.json"), + ("markers_end_time", "markers-end-time.json"), + ("markers_phase", "markers-phase.json"), + ("markers_category", "markers-category.json"), + ("markers_data", "markers-data.json"), + ) + + def __init__(self, directory, tid): + prefix = f"thread-{tid}-" + for attr, basename in self._COLUMNS: + setattr(self, attr, SpillColumn(directory, prefix + basename)) + self.sample_count = 0 + self.marker_count = 0 + + def append_sample(self, stack_index, time_ms): + self.samples_stack.append(stack_index) + self.samples_time.append(time_ms) + self.sample_count += 1 + + def append_marker(self, name_idx, start_time, end_time, phase, category, data): + self.markers_name.append(name_idx) + self.markers_start_time.append(start_time) + self.markers_end_time.append(end_time) + self.markers_phase.append(phase) + self.markers_category.append(category) + self.markers_data.append(data) + self.marker_count += 1 + + def prepare_read(self): + for attr, _basename in self._COLUMNS: + getattr(self, attr).flush() + class GeckoCollector(Collector): aggregating = True @@ -77,6 +150,8 @@ def __init__(self, sample_interval_usec, *, skip_idle=False, opcodes=False): # Per-thread data structures self.threads = {} # tid -> thread data + self.spill_dir = None + self.exported = False # Global tables self.libs = [] @@ -151,6 +226,9 @@ def collect(self, stack_frames, timestamps_us=None): stack_frames: List of interpreter/thread frame info timestamps_us: List of timestamps in microseconds (None for live sampling) """ + if self.exported: + raise RuntimeError("cannot append to GeckoCollector after export") + # Handle live sampling (no timestamps provided) if timestamps_us is None: current_time = (time.monotonic() * 1000) - self.start_time @@ -259,15 +337,9 @@ def collect(self, stack_frames, timestamps_us=None): stack_index = self._process_stack(thread_data, frames) # Add samples with timestamps - samples = thread_data["samples"] - samples_stack = samples["stack"] - samples_time = samples["time"] - samples_delay = samples["eventDelay"] - + thread_spill = thread_data["_spill"] for t in times: - samples_stack.append(stack_index) - samples_time.append(t) - samples_delay.append(None) + thread_spill.append_sample(stack_index, t) # Handle opcodes if self.opcodes_enabled and frames: @@ -294,6 +366,8 @@ def collect(self, stack_frames, timestamps_us=None): def _create_thread(self, tid, is_main_thread): """Create a new thread structure with processed profile format.""" + if self.spill_dir is None: + self.spill_dir = tempfile.TemporaryDirectory() thread = { "name": f"Thread-{tid}", @@ -307,15 +381,6 @@ def _create_thread(self, tid, is_main_thread): "tid": tid, "processType": "default", "processName": "Python Process", - # Sample data - processed format with direct arrays - "samples": { - "stack": [], - "time": [], - "eventDelay": [], - "weight": None, - "weightType": "samples", - "length": 0, # Will be updated on export - }, # Stack table - processed format "stackTable": { "frame": [], @@ -366,21 +431,12 @@ def _create_thread(self, tid, is_main_thread): "functionSize": [], "length": 0, }, - # Markers - processed format (arrays) - "markers": { - "data": [], - "name": [], - "startTime": [], - "endTime": [], - "phase": [], - "category": [], - "length": 0, - }, # Caches for deduplication "_stackCache": {}, "_frameCache": {}, "_funcCache": {}, "_resourceCache": {}, + "_spill": GeckoThreadSpill(self.spill_dir.name, tid), } return thread @@ -405,51 +461,42 @@ def _add_marker(self, tid, name, start_time, end_time, category): if tid not in self.threads: return - thread_data = self.threads[tid] duration = end_time - start_time name_idx = self._intern_string(name) - markers = thread_data["markers"] - markers["name"].append(name_idx) - markers["startTime"].append(start_time) - markers["endTime"].append(end_time) - markers["phase"].append(1) # 1 = interval marker - markers["category"].append(category) - markers["data"].append({ - "type": name.replace(" ", ""), - "duration": duration, - "tid": tid - }) - - def _add_opcode_interval_marker(self, tid, opcode, lineno, col_offset, funcname, start_time, end_time): + self.threads[tid]["_spill"].append_marker( + name_idx, start_time, end_time, 1, category, { + "type": name.replace(" ", ""), + "duration": duration, + "tid": tid, + } + ) + + def _add_opcode_interval_marker(self, tid, opcode, lineno, col_offset, + funcname, start_time, end_time): """Add an interval marker for opcode execution span.""" if tid not in self.threads or opcode is None: return - thread_data = self.threads[tid] opcode_info = get_opcode_info(opcode) # Use formatted opcode name (with base opcode for specialized ones) formatted_opname = format_opcode(opcode) name_idx = self._intern_string(formatted_opname) - markers = thread_data["markers"] - markers["name"].append(name_idx) - markers["startTime"].append(start_time) - markers["endTime"].append(end_time) - markers["phase"].append(1) # 1 = interval marker - markers["category"].append(CATEGORY_OPCODES) - markers["data"].append({ - "type": "Opcode", - "opcode": opcode, - "opname": formatted_opname, - "base_opname": opcode_info["base_opname"], - "is_specialized": opcode_info["is_specialized"], - "line": lineno, - "column": col_offset if col_offset >= 0 else None, - "function": funcname, - "duration": end_time - start_time, - }) + self.threads[tid]["_spill"].append_marker( + name_idx, start_time, end_time, 1, CATEGORY_OPCODES, { + "type": "Opcode", + "opcode": opcode, + "opname": formatted_opname, + "base_opname": opcode_info["base_opname"], + "is_specialized": opcode_info["is_specialized"], + "line": lineno, + "column": col_offset if col_offset >= 0 else None, + "function": funcname, + "duration": end_time - start_time, + } + ) def _process_stack(self, thread_data, frames): """Process a stack and return the stack index.""" @@ -660,7 +707,6 @@ def _finalize_markers(self): def export(self, filename): """Export the profile to a Gecko JSON file.""" - if self.sample_count > 0 and self.last_sample_time > 0: self.interval = self.last_sample_time / self.sample_count @@ -681,19 +727,30 @@ def spin(): spinner_thread = threading.Thread(target=spin, daemon=True) spinner_thread.start() + temp_path = None + replaced = False try: - # Finalize any open markers before building profile - self._finalize_markers() - - profile = self._build_profile() - - with open(filename, "w") as f: - json.dump(profile, f, separators=(",", ":")) + self._prepare_for_serialization() + output_dir = os.path.dirname(os.path.abspath(filename)) or "." + with tempfile.NamedTemporaryFile( + "w", dir=output_dir, delete=False + ) as file: + temp_path = file.name + self._stream_profile(file) + os.replace(temp_path, filename) + replaced = True finally: + self.exported = True stop_spinner.set() spinner_thread.join(timeout=1.0) # Small delay to ensure the clear happens time.sleep(0.01) + if temp_path is not None and not replaced: + try: + os.unlink(temp_path) + except FileNotFoundError: + pass + self._cleanup_spills() print(f"Gecko profile written to {filename}") print( @@ -727,34 +784,17 @@ def _build_marker_schema(self): def _build_profile(self): """Build the complete profile structure in processed format.""" - # Convert thread data to final format - threads = [] - - for tid, thread_data in self.threads.items(): - # Update lengths - samples = thread_data["samples"] - stack_table = thread_data["stackTable"] - frame_table = thread_data["frameTable"] - func_table = thread_data["funcTable"] - resource_table = thread_data["resourceTable"] - - samples["length"] = len(samples["stack"]) - stack_table["length"] = len(stack_table["frame"]) - frame_table["length"] = len(frame_table["func"]) - func_table["length"] = len(func_table["name"]) - resource_table["length"] = len(resource_table["name"]) - thread_data["markers"]["length"] = len(thread_data["markers"]["name"]) - - # Clean up internal caches - del thread_data["_stackCache"] - del thread_data["_frameCache"] - del thread_data["_funcCache"] - del thread_data["_resourceCache"] - - threads.append(thread_data) - - # Main profile structure in processed format - profile = { + try: + self._prepare_for_serialization() + file = io.StringIO() + self._stream_profile(file) + return json.loads(file.getvalue()) + finally: + self.exported = True + self._cleanup_spills() + + def _profile_head(self): + return { "meta": { "interval": self.interval, "startTime": self.start_time, @@ -784,7 +824,10 @@ def _build_profile(self): }, }, "libs": self.libs, - "threads": threads, + } + + def _profile_tail(self): + return { "pages": [], "shared": { "stringArray": self.global_strings, @@ -792,4 +835,146 @@ def _build_profile(self): }, } - return profile + def _prepare_for_serialization(self): + if self.exported: + raise RuntimeError("GeckoCollector has already been exported") + self._finalize_markers() + for thread_data in self.threads.values(): + thread_data["_spill"].prepare_read() + thread_data["stackTable"]["length"] = len(thread_data["stackTable"]["frame"]) + thread_data["frameTable"]["length"] = len(thread_data["frameTable"]["func"]) + thread_data["funcTable"]["length"] = len(thread_data["funcTable"]["name"]) + thread_data["resourceTable"]["length"] = len(thread_data["resourceTable"]["name"]) + + def _cleanup_spills(self): + if self.spill_dir is not None: + self.spill_dir.cleanup() + self.spill_dir = None + + def _stream_profile(self, file): + file.write("{") + first = True + for key, value in self._profile_head().items(): + first = _write_json_member(file, key, value, first) + + first = _write_member_name(file, "threads", first) + file.write("[") + for index, (tid, thread_data) in enumerate(self.threads.items()): + if index: + file.write(",") + self._stream_thread(file, tid, thread_data) + file.write("]") + + for key, value in self._profile_tail().items(): + first = _write_json_member(file, key, value, first) + file.write("}") + + def _stream_thread(self, file, tid, thread_data): + spill = thread_data["_spill"] + metadata = { + "name": thread_data["name"], + "isMainThread": thread_data["isMainThread"], + "processStartupTime": thread_data["processStartupTime"], + "processShutdownTime": thread_data["processShutdownTime"], + "registerTime": thread_data["registerTime"], + "unregisterTime": thread_data["unregisterTime"], + "pausedRanges": thread_data["pausedRanges"], + "pid": thread_data["pid"], + "tid": thread_data["tid"], + "processType": thread_data["processType"], + "processName": thread_data["processName"], + } + file.write("{") + first = True + for key, value in metadata.items(): + first = _write_json_member(file, key, value, first) + + first = _write_member_name(file, "samples", first) + self._stream_samples(file, spill) + for key in ( + "stackTable", + "frameTable", + "funcTable", + "resourceTable", + "nativeSymbols", + ): + first = _write_json_member(file, key, thread_data[key], first) + first = _write_member_name(file, "markers", first) + self._stream_markers(file, spill) + file.write("}") + + def _stream_samples(self, file, spill): + _stream_column_table( + file, + ( + ("stack", spill.samples_stack.iter_tokens()), + ("time", spill.samples_time.iter_tokens()), + ("eventDelay", ("null" for _ in range(spill.sample_count))), + ), + spill.sample_count, + ( + ("weight", None), + ("weightType", "samples"), + ("length", spill.sample_count), + ), + ) + + def _stream_markers(self, file, spill): + _stream_column_table( + file, + ( + ("data", spill.markers_data.iter_tokens()), + ("name", spill.markers_name.iter_tokens()), + ("startTime", spill.markers_start_time.iter_tokens()), + ("endTime", spill.markers_end_time.iter_tokens()), + ("phase", spill.markers_phase.iter_tokens()), + ("category", spill.markers_category.iter_tokens()), + ), + spill.marker_count, + (("length", spill.marker_count),), + ) + + +def _write_json(file, value): + for chunk in _JSON_ENCODER.iterencode(value): + file.write(chunk) + + +def _write_member_name(file, name, first): + if not first: + file.write(",") + _write_json(file, name) + file.write(":") + return False + + +def _write_json_member(file, name, value, first): + first = _write_member_name(file, name, first) + _write_json(file, value) + return first + + +def _stream_column_table(file, columns, expected_count, trailing_members=()): + file.write("{") + first = True + for name, token_iter in columns: + first = _write_member_name(file, name, first) + _stream_array(file, token_iter, expected_count, name) + for name, value in trailing_members: + first = _write_json_member(file, name, value, first) + file.write("}") + + +def _stream_array(file, token_iter, expected_count, label="array"): + file.write("[") + count = 0 + for token in token_iter: + if count: + file.write(",") + file.write(token) + count += 1 + if count != expected_count: + raise RuntimeError( + f"streamed {count} {label} items, expected {expected_count}" + ) + file.write("]") diff --git a/Lib/profiling/sampling/heatmap_collector.py b/Lib/profiling/sampling/heatmap_collector.py index 6e650ec08f410bc..78f1e39f6a002d0 100644 --- a/Lib/profiling/sampling/heatmap_collector.py +++ b/Lib/profiling/sampling/heatmap_collector.py @@ -5,11 +5,9 @@ import html import importlib.resources import json -import locale import math import os import platform -import site import sys from dataclasses import dataclass, field from pathlib import Path diff --git a/Lib/profiling/sampling/live_collector/collector.py b/Lib/profiling/sampling/live_collector/collector.py index a53cfc6b719a105..2805134f239eb38 100644 --- a/Lib/profiling/sampling/live_collector/collector.py +++ b/Lib/profiling/sampling/live_collector/collector.py @@ -18,9 +18,6 @@ THREAD_STATUS_UNKNOWN, THREAD_STATUS_GIL_REQUESTED, THREAD_STATUS_HAS_EXCEPTION, - PROFILING_MODE_CPU, - PROFILING_MODE_GIL, - PROFILING_MODE_WALL, ) from .constants import ( MICROSECONDS_PER_SECOND, diff --git a/Lib/profiling/sampling/live_collector/display.py b/Lib/profiling/sampling/live_collector/display.py index f5324421b102111..ec7e39c02963056 100644 --- a/Lib/profiling/sampling/live_collector/display.py +++ b/Lib/profiling/sampling/live_collector/display.py @@ -1,6 +1,5 @@ """Display interface abstractions for the live profiling collector.""" -import contextlib import curses from abc import ABC, abstractmethod diff --git a/Lib/profiling/sampling/live_collector/widgets.py b/Lib/profiling/sampling/live_collector/widgets.py index 86d2649f875e622..7535d0c753b0465 100644 --- a/Lib/profiling/sampling/live_collector/widgets.py +++ b/Lib/profiling/sampling/live_collector/widgets.py @@ -1,7 +1,6 @@ """Widget classes for the live profiling collector UI.""" import curses -import time from abc import ABC, abstractmethod from .constants import ( @@ -13,24 +12,14 @@ WIDTH_THRESHOLD_CUMUL_PCT, WIDTH_THRESHOLD_CUMTIME, MICROSECONDS_PER_SECOND, - DISPLAY_UPDATE_INTERVAL_SEC, MIN_BAR_WIDTH, MAX_SAMPLE_RATE_BAR_WIDTH, MAX_EFFICIENCY_BAR_WIDTH, MIN_SAMPLE_RATE_FOR_SCALING, FOOTER_LINES, - FINISHED_BANNER_EXTRA_LINES, OPCODE_PANEL_HEIGHT, ) -from ..constants import ( - THREAD_STATUS_HAS_GIL, - THREAD_STATUS_ON_CPU, - THREAD_STATUS_UNKNOWN, - THREAD_STATUS_GIL_REQUESTED, - PROFILING_MODE_CPU, - PROFILING_MODE_GIL, - PROFILING_MODE_WALL, -) +from ..constants import PROFILING_MODE_GIL from ..opcode_utils import get_opcode_info, format_opcode diff --git a/Lib/profiling/sampling/sample.py b/Lib/profiling/sampling/sample.py index 2d379e1e16a35e3..6cb6dd483520887 100644 --- a/Lib/profiling/sampling/sample.py +++ b/Lib/profiling/sampling/sample.py @@ -8,10 +8,6 @@ from collections import deque lazy from _colorize import ANSIColors -from .pstats_collector import PstatsCollector -from .stack_collector import CollapsedStackCollector, FlamegraphCollector -from .heatmap_collector import HeatmapCollector -from .gecko_collector import GeckoCollector from .binary_collector import BinaryCollector @@ -50,9 +46,38 @@ def _pause_threads(unwinder, blocking): # Maximum number of consecutive identical samples to keep before flushing. MAX_PENDING_SAMPLES = 8192 + +def _resolve_python_pid(pid): + """On Windows, if pid is a venvlauncher process, return the child Python PID. + + The venvlauncher (used as python.exe in venvs) spawns the real Python + interpreter as a child process via CreateProcessW. The RemoteUnwinder + needs the child's PID, not the launcher's. + + Returns the original pid if not on Windows, not a venv launcher, + or no child process is found. + """ + if os.name != "nt" or sys.prefix == sys.base_prefix: + return pid + try: + children = _remote_debugging.get_child_pids(pid, recursive=False) + python_children = [ + child for child in children + if _remote_debugging.is_python_process(child) + ] + if len(python_children) == 1: + return python_children[0] + except (OSError, RuntimeError) as err: + raise SystemExit( + f"Failed to initialize profiler from virtualenv: {err}\n" + f"Try running with the base interpreter: {sys._base_executable}" + ) from err + return pid + + class SampleProfiler: def __init__(self, pid, sample_interval_usec, all_threads, *, mode=PROFILING_MODE_WALL, native=False, gc=True, opcodes=False, skip_non_matching_threads=True, collect_stats=False, blocking=False): - self.pid = pid + self.pid = _resolve_python_pid(pid) self.sample_interval_usec = sample_interval_usec self.all_threads = all_threads self.mode = mode # Store mode for later use @@ -61,10 +86,6 @@ def __init__(self, pid, sample_interval_usec, all_threads, *, mode=PROFILING_MOD try: self.unwinder = self._new_unwinder(native, gc, opcodes, skip_non_matching_threads) except RuntimeError as err: - if os.name == "nt" and sys.executable.endswith("python.exe"): - raise SystemExit( - "Running profiling.sampling from virtualenv on Windows platform is not supported" - ) from err raise SystemExit(err) from err # Track sample intervals and total sample count self.sample_intervals = deque(maxlen=100) diff --git a/Lib/py_compile.py b/Lib/py_compile.py index 7ca479141e01e4e..b22446e2f098dee 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -202,12 +202,12 @@ def main(): if args.quiet: parser.exit(1) else: - parser.exit(1, error.msg) + parser.exit(1, error.msg + '\n') except OSError as error: if args.quiet: parser.exit(1) else: - parser.exit(1, str(error)) + parser.exit(1, str(error) + '\n') if __name__ == "__main__": diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 497cc7d90a42456..fe42592530c2cfd 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1240,6 +1240,17 @@ def indent(self, text, prefix=' '): lines = [(prefix + line).rstrip() for line in text.split('\n')] return '\n'.join(lines) + def _format_doc(self, text, width=68): + """Wraps the single-line summary if it is too long.""" + if not text: return '' + lines = text.split('\n', 2) + if len(lines) > 1 and lines[1]: + return text + lines[:1] = textwrap.wrap(lines[0], width, + break_long_words=False, + break_on_hyphens=False) + return '\n'.join(lines) + def section(self, title, contents): """Format a section with a given heading.""" clean_contents = self.indent(contents).rstrip() @@ -1344,7 +1355,7 @@ def docmodule(self, object, name=None, mod=None, *ignored): if data: contents = [] for key, value in data: - contents.append(self.docother(value, key, name, maxlen=70)) + contents.append(self.docother(value, key, name, maxlen=76)) result = result + self.section('DATA', '\n'.join(contents)) if version := self._get_version(object): @@ -1390,6 +1401,7 @@ def makename(c, m=object.__module__): doc = getdoc(object) if doc: + doc = self._format_doc(doc) push(doc + '\n') # List the mro, if non-trivial. @@ -1466,7 +1478,7 @@ def spilldata(msg, attrs, predicate): obj = getattr(object, name) except AttributeError: obj = homecls.__dict__[name] - push(self.docother(obj, name, mod, maxlen=70, doc=doc) + + push(self.docother(obj, name, mod, maxlen=72, doc=doc) + '\n') return attrs @@ -1590,6 +1602,7 @@ def docroutine(self, object, name=None, mod=None, cl=None, homecls=None): return decl + '\n' else: doc = getdoc(object) or '' + doc = self._format_doc(doc) return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n') def docdata(self, object, name=None, mod=None, cl=None, *ignored): @@ -1602,6 +1615,7 @@ def docdata(self, object, name=None, mod=None, cl=None, *ignored): push('\n') doc = getdoc(object) or '' if doc: + doc = self._format_doc(doc) push(self.indent(doc)) push('\n') return ''.join(results) @@ -1615,12 +1629,13 @@ def docother(self, object, name=None, mod=None, parent=None, *ignored, if maxlen: line = (name and name + ' = ' or '') + repr chop = maxlen - len(line) - if chop < 0: repr = repr[:chop] + '...' + if chop < 0: repr = repr[:chop-3] + '...' line = (name and self.bold(name) + ' = ' or '') + repr if not doc: doc = getdoc(object) if doc: - line += '\n' + self.indent(str(doc)) + '\n' + doc = self._format_doc(str(doc)) + line += '\n' + self.indent(doc) + '\n' return line class _PlainTextDoc(TextDoc): diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py index 6c6d9bb6b34244e..26fcda612567ea4 100644 --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -40,6 +40,9 @@ __all__ = ["Completer"] +# Sentinel object to distinguish "missing" from "present but None" +_MISSING = sentinel("MISSING") + class Completer: def __init__(self, namespace = None): """Create a new completer for the command line. @@ -194,14 +197,14 @@ def attr_matches(self, text): and isinstance(thisobject.__dict__.get(word), types.LazyImportType) - ): + ): value = thisobject.__dict__.get(word) else: - value = getattr(thisobject, word, None) + value = getattr(thisobject, word, _MISSING) - if value is not None: + if value is not _MISSING: matches.append(self._callable_postfix(value, match)) - else: + elif word in getattr(type(thisobject), '__slots__', ()): matches.append(match) if matches or not noprefix: break diff --git a/Lib/shlex.py b/Lib/shlex.py index 5959f52dd12639d..c7ffc918d53961c 100644 --- a/Lib/shlex.py +++ b/Lib/shlex.py @@ -317,8 +317,12 @@ def join(split_command): return ' '.join(quote(arg) for arg in split_command) -def quote(s): - """Return a shell-escaped version of the string *s*.""" +def quote(s, *, force=False): + """Return a shell-escaped version of the string *s*. + + If *force* is *True*, then *s* is unconditionally quoted, + even if it is already safe for a shell without being quoted. + """ if not s: return "''" @@ -329,8 +333,10 @@ def quote(s): safe_chars = (b'%+,-./0123456789:=@' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ_' b'abcdefghijklmnopqrstuvwxyz') - # No quoting is needed if `s` is an ASCII string consisting only of `safe_chars` - if s.isascii() and not s.encode().translate(None, delete=safe_chars): + # No quoting is needed if we are not forcing quoting + # and `s` is an ASCII string consisting only of `safe_chars`. + if (not force + and s.isascii() and not s.encode().translate(None, delete=safe_chars)): return s # use single quotes, and put single quotes into double quotes diff --git a/Lib/shutil.py b/Lib/shutil.py index c8d02bbaeb80b4e..5095318da233146 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -944,8 +944,8 @@ def move(src, dst, copy_function=copy2): return real_dst def _destinsrc(src, dst): - src = os.path.abspath(src) - dst = os.path.abspath(dst) + src = os.path.realpath(src) + dst = os.path.realpath(dst) if not src.endswith(os.path.sep): src += os.path.sep if not dst.endswith(os.path.sep): @@ -1307,12 +1307,6 @@ def unregister_unpack_format(name): """Removes the pack format from the registry.""" del _UNPACK_FORMATS[name] -def _ensure_directory(path): - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - if not os.path.isdir(dirname): - os.makedirs(dirname) - def _unpack_zipfile(filename, extract_dir): """Unpack zip `filename` to `extract_dir` """ diff --git a/Lib/site.py b/Lib/site.py index b7f5c7f0246bc1b..d06549b8df800e3 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -505,6 +505,11 @@ def _exec_imports(self): # batch. In that case, PEP 829 says the import lines are # suppressed in favor of the .start's entry points. for filename, imports in self._importexecs.items(): + # Inject 'sitedir' local variable in the current frame for + # compatibility with Python 3.14. Especially, "-nspkg.pth" files + # generated by setuptools use: sys._getframe(1).f_locals['sitedir']. + sitedir = os.path.dirname(filename) + # Given "/path/to/foo.pth", check whether "/path/to/foo.start" was # registered in this same batch. name, dot, pth = filename.rpartition(".") diff --git a/Lib/ssl.py b/Lib/ssl.py index f23bcbe75e7201f..3c0361330d7e951 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -721,10 +721,9 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None, # root CA certificates for the given purpose. This may fail silently. context.load_default_certs(purpose) # OpenSSL 1.1.1 keylog file - if hasattr(context, 'keylog_filename'): - keylogfile = os.environ.get('SSLKEYLOGFILE') - if keylogfile and not sys.flags.ignore_environment: - context.keylog_filename = keylogfile + keylogfile = os.environ.get('SSLKEYLOGFILE') + if keylogfile and not sys.flags.ignore_environment: + context.keylog_filename = keylogfile return context def _create_unverified_context(protocol=None, *, cert_reqs=CERT_NONE, @@ -775,10 +774,9 @@ def _create_unverified_context(protocol=None, *, cert_reqs=CERT_NONE, # root CA certificates for the given purpose. This may fail silently. context.load_default_certs(purpose) # OpenSSL 1.1.1 keylog file - if hasattr(context, 'keylog_filename'): - keylogfile = os.environ.get('SSLKEYLOGFILE') - if keylogfile and not sys.flags.ignore_environment: - context.keylog_filename = keylogfile + keylogfile = os.environ.get('SSLKEYLOGFILE') + if keylogfile and not sys.flags.ignore_environment: + context.keylog_filename = keylogfile return context # Used by http.client if no context is explicitly passed. diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 5d5b8e415f3cd21..d26e41982deb811 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -7509,6 +7509,36 @@ def func(): self.assertEqual(out, b"a" * 8) self.assertEqual(err, b"") + @support.cpython_only + @support.subTests(("setup", "call"), [ + ("obj = _datetime.timedelta", "obj(seconds=2)"), + ("obj = _datetime.timedelta(seconds=2)", "obj.total_seconds()"), + ("obj = _datetime.date(2026, 6, 7)", "obj.isocalendar()"), + ]) + def test_static_datetime_types_outlive_collected_module(self, setup, call): + # gh-151039: This code used to crash + script = f"""if True: + import sys, gc + import _datetime + + {setup} # static C type, survives the module + del sys.modules['_datetime'] + del _datetime + sys.modules['_datetime'] = None # block re-import + gc.collect() # module object is collected + + try: + {call} # used to be a segmentation fault + except ImportError: + pass + else: + raise AssertionError("ImportError not raised") + """ + rc, out, err = script_helper.assert_python_ok("-c", script) + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + def load_tests(loader, standard_tests, pattern): standard_tests.addTest(ZoneInfoCompleteTest()) diff --git a/Lib/test/mathdata/math_testcases.txt b/Lib/test/mathdata/math_testcases.txt index 958518824376f82..4a38a3666bab208 100644 --- a/Lib/test/mathdata/math_testcases.txt +++ b/Lib/test/mathdata/math_testcases.txt @@ -631,3 +631,1619 @@ log20646 log2 2.535995592365391e+208 -> 692.30359597460460 log20647 log2 6.2011236566089916e+233 -> 776.64177576730913 log20648 log2 2.1843274820677632e+253 -> 841.57499717289647 log20649 log2 8.7493931063474791e+297 -> 989.74182713073981 + +------------ +-- acospi -- +------------ + +acospi10000 acospi 0.0 -> 0.5 +acospi10001 acospi -0.0 -> 0.5 +acospi10002 acospi 1.0 -> 0.0 +acospi10003 acospi -1.0 -> 1.0 +acospi10004 acospi 0.5 -> 0.3333333333333333 +acospi10005 acospi -0.5 -> 0.6666666666666666 +acospi10006 acospi 0.75 -> 0.23005345616261588 +acospi10007 acospi 2.0000001329864406e-17 -> 0.5 +acospi10008 acospi 1.999999967550318e-17 -> 0.5 +acospi10009 acospi 2e-17 -> 0.5 +acospi10010 acospi 1.9999999999999998e-17 -> 0.5 +acospi10011 acospi 0.0625 -> 0.48009265723071126 +acospi10012 acospi 0.9999999403953552 -> 0.00010990189460803536 +acospi10013 acospi -0.9999999403953552 -> 0.999890098105392 +acospi10014 acospi 1.0 -> 0.0 +acospi10015 acospi 0.9999999403953552 -> 0.00010990189460803536 +acospi10016 acospi 0.9999999998835847 -> 4.857023409833964e-06 +acospi10017 acospi -0.9999999403953552 -> 0.999890098105392 +acospi10018 acospi -1.0 -> 1.0 +acospi10019 acospi -0.9999999998835847 -> 0.9999951429765902 +acospi10020 acospi 1.0 -> 0.0 +acospi10021 acospi 0.9999999403953552 -> 0.00010990189460803536 +acospi10022 acospi 0.9999999999999964 -> 2.6831517105016303e-08 +acospi10023 acospi -0.9999999403953552 -> 0.999890098105392 +acospi10024 acospi -1.0 -> 1.0 +acospi10025 acospi -0.9999999999999964 -> 0.9999999731684829 +acospi10026 acospi 1.0 -> 0.0 +acospi10027 acospi 0.9999999403953552 -> 0.00010990189460803536 +acospi10028 acospi 0.9999999999999999 -> 4.743186923619966e-09 +acospi10029 acospi -0.9999999403953552 -> 0.999890098105392 +acospi10030 acospi -1.0 -> 1.0 +acospi10031 acospi -0.9999999999999999 -> 0.999999995256813 +acospi10032 acospi 1.0 -> 0.0 +acospi10033 acospi 0.9999999403953552 -> 0.00010990189460803536 +acospi10034 acospi 0.9999999999999999 -> 4.743186923619966e-09 +acospi10035 acospi -0.9999999403953552 -> 0.999890098105392 +acospi10036 acospi -1.0 -> 1.0 +acospi10037 acospi -0.9999999999999999 -> 0.999999995256813 +acospi10038 acospi 1.0 -> 0.0 +acospi10039 acospi 0.9999999403953552 -> 0.00010990189460803536 +acospi10040 acospi 0.9999999999999999 -> 4.743186923619966e-09 +acospi10041 acospi -0.9999999403953552 -> 0.999890098105392 +acospi10042 acospi -1.0 -> 1.0 +acospi10043 acospi -0.9999999999999999 -> 0.999999995256813 +acospi10044 acospi 1.0 -> 0.0 +acospi10045 acospi 0.9999999403953552 -> 0.00010990189460803536 +acospi10046 acospi 0.9999999999999999 -> 4.743186923619966e-09 +acospi10047 acospi -0.9999999403953552 -> 0.999890098105392 +acospi10048 acospi -1.0 -> 1.0 +acospi10049 acospi -0.9999999999999999 -> 0.999999995256813 +acospi10050 acospi 0.03125 -> 0.4900511963370614 +acospi10051 acospi 0.0009765625 -> 0.49968915045236545 +acospi10052 acospi 3.0517578125e-05 -> 0.4999902859531789 +acospi10053 acospi 9.5367431640625e-07 -> 0.49999969643603687 +acospi10054 acospi 2.9802322387695312e-08 -> 0.49999999051362615 +acospi10055 acospi 9.313225746154785e-10 -> 0.4999999997035508 +acospi10056 acospi 2.9103830456733704e-11 -> 0.49999999999073597 +acospi10057 acospi 9.094947017729282e-13 -> 0.4999999999997105 +acospi10058 acospi 2.842170943040401e-14 -> 0.49999999999999095 +acospi10059 acospi 8.881784197001252e-16 -> 0.4999999999999997 +acospi10060 acospi 2.7755575615628914e-17 -> 0.5 +acospi10061 acospi 8.673617379884035e-19 -> 0.5 +acospi10062 acospi 2.710505431213761e-20 -> 0.5 +acospi10063 acospi 8.470329472543003e-22 -> 0.5 +acospi10064 acospi 2.6469779601696886e-23 -> 0.5 +acospi10065 acospi 8.271806125530277e-25 -> 0.5 +acospi10066 acospi 2.5849394142282115e-26 -> 0.5 +acospi10067 acospi 8.077935669463161e-28 -> 0.5 +acospi10068 acospi 2.524354896707238e-29 -> 0.5 +acospi10069 acospi 7.888609052210118e-31 -> 0.5 +acospi10070 acospi 2.465190328815662e-32 -> 0.5 +acospi10071 acospi 7.703719777548943e-34 -> 0.5 +acospi10072 acospi 2.407412430484045e-35 -> 0.5 +acospi10073 acospi 7.52316384526264e-37 -> 0.5 +acospi10074 acospi -0.03125 -> 0.5099488036629386 +acospi10075 acospi -2.9802322387695312e-08 -> 0.5000000094863738 +acospi10076 acospi -2.842170943040401e-14 -> 0.500000000000009 +acospi10077 acospi -2.710505431213761e-20 -> 0.5 +acospi10078 acospi -2.5849394142282115e-26 -> 0.5 +acospi10079 acospi -2.465190328815662e-32 -> 0.5 +acospi10080 acospi -2.350988701644575e-38 -> 0.5 +acospi10081 acospi -0.1251312643289566 -> 0.5399352010629168 +acospi10082 acospi 0.9386433362960815 -> 0.1120835750337698 +acospi10083 acospi 0.3664908707141876 -> 0.3805590984950769 +acospi10084 acospi 0.36649084091186523 -> 0.38055910869085624 +acospi10085 acospi 0.366490841000206 -> 0.38055910866063364 +acospi10086 acospi -0.13816863298416138 -> 0.5441215931223088 +acospi10087 acospi -0.13816864788532257 -> 0.5441215979114296 +acospi10088 acospi -0.13816864007172486 -> 0.5441215954001982 +acospi10089 acospi 0.9126854538917542 -> 0.1340047775091756 +acospi10090 acospi 0.9126853942871094 -> 0.13400482393558352 +acospi10091 acospi 0.912685444573738 -> 0.13400478476703412 +acospi10092 acospi 0.9126854445737379 -> 0.1340047847670342 +acospi10093 acospi 0.880692720413208 -> 0.1570775606195134 +acospi10094 acospi 0.8806926608085632 -> 0.15707760067276577 +acospi10095 acospi 0.8806926814412734 -> 0.15707758680795558 +acospi10096 acospi 0.8806926814412733 -> 0.15707758680795567 +acospi10097 acospi 0.2435227781534195 -> 0.4216969371828132 +acospi10098 acospi 0.2435227632522583 -> 0.42169694207322506 +acospi10099 acospi 0.24352277005396675 -> 0.42169693984097245 +acospi10100 acospi 0.1279129981994629 -> 0.45917217189807447 +acospi10101 acospi -0.11572346091270447 -> 0.5369186384114879 +acospi10102 acospi 0.9999996423721313 -> 0.0002692035702405639 +acospi10103 acospi 0.9999995827674866 -> 0.000290773090413406 +acospi10104 acospi 0.9999996241289419 -> 0.0002759844303031754 +acospi10105 acospi 0.9995118975639343 -> 0.009945766966749 +acospi10106 acospi 0.9995118379592896 -> 0.009946374261451639 +acospi10107 acospi 0.9995118644629029 -> 0.009946104228281858 +acospi10108 acospi 0.9995118644629027 -> 0.009946104228282989 +acospi10109 acospi 1.1754943508222875e-38 -> 0.5 +acospi10110 acospi 2.2250738585072014e-308 -> 0.5 +acospi10111 acospi 2.004168360008973e-292 -> 0.5 +acospi10112 acospi -1.1754943508222875e-38 -> 0.5 +acospi10113 acospi -2.2250738585072014e-308 -> 0.5 +acospi10114 acospi -2.004168360008973e-292 -> 0.5 +acospi10115 acospi 1.401298464324817e-45 -> 0.5 +acospi10116 acospi 5e-324 -> 0.5 +acospi10117 acospi -1.401298464324817e-45 -> 0.5 +acospi10118 acospi -5e-324 -> 0.5 +acospi10119 acospi -0.5356916189193726 -> 0.6799490414927629 +acospi10120 acospi 0.9258930683135986 -> 0.12331439084862783 +acospi10121 acospi 0.9258930087089539 -> 0.12331444106954574 +acospi10122 acospi 0.9258930140454763 -> 0.12331443657316782 +acospi10123 acospi 0.9997028112411499 -> 0.007760542300314392 +acospi10124 acospi 0.9997027516365051 -> 0.007761320533135704 +acospi10125 acospi 0.9997027756274229 -> 0.00776100730317654 +acospi10126 acospi 0.9997027756274228 -> 0.007761007303177989 +acospi10127 acospi 0.7071993947029114 -> 0.24995830653935586 +acospi10128 acospi 0.7071993350982666 -> 0.249958333374387 +acospi10129 acospi 0.7071993911300235 -> 0.24995830814793119 +acospi10130 acospi 0.7071993911300234 -> 0.24995830814793124 + +acospi20001 acospi inf -> nan invalid +acospi20002 acospi -inf -> nan invalid +acospi20003 acospi nan -> nan + +------------ +-- asinpi -- +------------ + +asinpi10000 asinpi 0.0 -> 0.0 +asinpi10001 asinpi -0.0 -> -0.0 +asinpi10002 asinpi 0.5 -> 0.16666666666666666 +asinpi10003 asinpi -0.5 -> -0.16666666666666666 +asinpi10004 asinpi 1.0 -> 0.5 +asinpi10005 asinpi -1.0 -> -0.5 +asinpi10006 asinpi 0.75 -> 0.2699465438373841 +asinpi10007 asinpi 0.9999999403953552 -> 0.499890098105392 +asinpi10008 asinpi -0.9999999403953552 -> -0.499890098105392 +asinpi10009 asinpi 1.0 -> 0.5 +asinpi10010 asinpi 0.9999999403953552 -> 0.499890098105392 +asinpi10011 asinpi 0.9999999998835847 -> 0.49999514297659015 +asinpi10012 asinpi -0.9999999403953552 -> -0.499890098105392 +asinpi10013 asinpi -1.0 -> -0.5 +asinpi10014 asinpi -0.9999999998835847 -> -0.49999514297659015 +asinpi10015 asinpi 1.0 -> 0.5 +asinpi10016 asinpi 0.9999999403953552 -> 0.499890098105392 +asinpi10017 asinpi 0.9999999999999964 -> 0.4999999731684829 +asinpi10018 asinpi -0.9999999403953552 -> -0.499890098105392 +asinpi10019 asinpi -1.0 -> -0.5 +asinpi10020 asinpi -0.9999999999999964 -> -0.4999999731684829 +asinpi10021 asinpi 1.0 -> 0.5 +asinpi10022 asinpi 0.9999999403953552 -> 0.499890098105392 +asinpi10023 asinpi 0.9999999999999999 -> 0.4999999952568131 +asinpi10024 asinpi -0.9999999403953552 -> -0.499890098105392 +asinpi10025 asinpi -1.0 -> -0.5 +asinpi10026 asinpi -0.9999999999999999 -> -0.4999999952568131 +asinpi10027 asinpi 1.0 -> 0.5 +asinpi10028 asinpi 0.9999999403953552 -> 0.499890098105392 +asinpi10029 asinpi 0.9999999999999999 -> 0.4999999952568131 +asinpi10030 asinpi -0.9999999403953552 -> -0.499890098105392 +asinpi10031 asinpi -1.0 -> -0.5 +asinpi10032 asinpi -0.9999999999999999 -> -0.4999999952568131 +asinpi10033 asinpi 1.0 -> 0.5 +asinpi10034 asinpi 0.9999999403953552 -> 0.499890098105392 +asinpi10035 asinpi 0.9999999999999999 -> 0.4999999952568131 +asinpi10036 asinpi -0.9999999403953552 -> -0.499890098105392 +asinpi10037 asinpi -1.0 -> -0.5 +asinpi10038 asinpi -0.9999999999999999 -> -0.4999999952568131 +asinpi10039 asinpi 1.0 -> 0.5 +asinpi10040 asinpi 0.9999999403953552 -> 0.499890098105392 +asinpi10041 asinpi 0.9999999999999999 -> 0.4999999952568131 +asinpi10042 asinpi -0.9999999403953552 -> -0.499890098105392 +asinpi10043 asinpi -1.0 -> -0.5 +asinpi10044 asinpi -0.9999999999999999 -> -0.4999999952568131 +asinpi10045 asinpi 0.03125 -> 0.009948803662938608 +asinpi10046 asinpi 0.0009765625 -> 0.0003108495476345764 +asinpi10047 asinpi 3.0517578125e-05 -> 9.714046821081509e-06 +asinpi10048 asinpi 9.5367431640625e-07 -> 3.0356396311172383e-07 +asinpi10049 asinpi 2.9802322387695312e-08 -> 9.486373847239932e-09 +asinpi10050 asinpi 9.313225746154785e-10 -> 2.964491827262479e-10 +asinpi10051 asinpi 2.9103830456733704e-11 -> 9.264036960195246e-12 +asinpi10052 asinpi 9.094947017729282e-13 -> 2.8950115500610145e-13 +asinpi10053 asinpi 2.842170943040401e-14 -> 9.04691109394067e-15 +asinpi10054 asinpi 8.881784197001252e-16 -> 2.8271597168564594e-16 +asinpi10055 asinpi 2.7755575615628914e-17 -> 8.834874115176436e-18 +asinpi10056 asinpi 8.673617379884035e-19 -> 2.760898160992636e-19 +asinpi10057 asinpi 7.888609052210118e-31 -> 2.5110222495574236e-31 +asinpi10058 asinpi 1.401298464324817e-45 -> 4.460471546887532e-46 +asinpi10059 asinpi 0.0 -> 0.0 +asinpi10060 asinpi 2.409919865102884e-181 -> 7.671013179729553e-182 +asinpi10061 asinpi 1.401298464324817e-45 -> 4.460471546887532e-46 +asinpi10062 asinpi 0.0 -> 0.0 +asinpi10063 asinpi 5e-324 -> 0.0 +asinpi10064 asinpi -0.13099800050258636 -> -0.04181814856647883 +asinpi10065 asinpi -0.21591897308826447 -> -0.06927470561424247 +asinpi10066 asinpi -0.1944168210029602 -> -0.06228143288596484 +asinpi10067 asinpi -0.1944168359041214 -> -0.062281437721417 +asinpi10068 asinpi -0.19441682493723628 -> -0.06228143416264412 +asinpi10069 asinpi 0.9866708517074585 -> 0.4479704696000938 +asinpi10070 asinpi 0.9866707921028137 -> 0.4479703530089429 +asinpi10071 asinpi 0.9866708504122479 -> 0.4479704670665621 +asinpi10072 asinpi 0.9866708504122478 -> 0.44797046706656185 +asinpi10073 asinpi -0.6866101622581482 -> -0.24090205124758424 +asinpi10074 asinpi 0.8438399434089661 -> 0.3197103200989401 +asinpi10075 asinpi -0.13135038316249847 -> -0.04193129309542388 +asinpi10076 asinpi -0.5068531036376953 -> -0.16919134974732694 +asinpi10077 asinpi -0.5068531632423401 -> -0.1691913717566472 +asinpi10078 asinpi -0.5068531437412152 -> -0.16919136455575687 +asinpi10079 asinpi -0.7008922100067139 -> -0.2472146113103207 +asinpi10080 asinpi 0.12256252765655518 -> 0.03911120286288364 +asinpi10081 asinpi 0.12256252020597458 -> 0.03911120047327442 +asinpi10082 asinpi 0.12256252763528681 -> 0.03911120285606228 +asinpi10083 asinpi 1.1754943508222875e-38 -> 3.7417147301993126e-39 +asinpi10084 asinpi 2.2250738585072014e-308 -> 7.082630066519554e-309 +asinpi10085 asinpi 2.004168360008973e-292 -> 6.379466025676106e-293 +asinpi10086 asinpi -1.1754943508222875e-38 -> -3.7417147301993126e-39 +asinpi10087 asinpi -2.2250738585072014e-308 -> -7.082630066519554e-309 +asinpi10088 asinpi -2.004168360008973e-292 -> -6.379466025676106e-293 +asinpi10089 asinpi 1.401298464324817e-45 -> 4.460471546887532e-46 +asinpi10090 asinpi 5e-324 -> 0.0 +asinpi10091 asinpi -1.401298464324817e-45 -> -4.460471546887532e-46 +asinpi10092 asinpi -5e-324 -> -0.0 +asinpi10093 asinpi 0.972168505191803 -> 0.4247258559057922 +asinpi10094 asinpi -0.19141583144664764 -> -0.06130790022106249 +asinpi10095 asinpi -0.19141584634780884 -> -0.06130790505360787 +asinpi10096 asinpi -0.19141583181687138 -> -0.06130790034112851 +asinpi10097 asinpi 0.505088746547699 -> 0.16854024296386302 +asinpi10098 asinpi 0.5050886869430542 -> 0.16854022098093674 +asinpi10099 asinpi 0.5050886987499023 -> 0.1685402253354475 +asinpi10100 asinpi 0.5050886987499021 -> 0.16854022533544744 +asinpi10101 asinpi -0.6554324626922607 -> -0.2275136094679927 +asinpi10102 asinpi -0.6554325222969055 -> -0.2275136345890164 +asinpi10103 asinpi -0.6554324978014275 -> -0.22751362426513144 +asinpi10104 asinpi -0.6554324978014276 -> -0.2275136242651315 + +asinpi20001 asinpi inf -> nan invalid +asinpi20002 asinpi -inf -> nan invalid +asinpi20003 asinpi nan -> nan + +------------ +-- atanpi -- +------------ + +atanpi10000 atanpi 0.0 -> 0.0 +atanpi10001 atanpi -0.0 -> -0.0 +atanpi10002 atanpi 3.4028234663852886e+38 -> 0.5 +atanpi10003 atanpi 1.7976931348623157e+308 -> 0.5 +atanpi10004 atanpi -3.4028234663852886e+38 -> -0.5 +atanpi10005 atanpi -1.7976931348623157e+308 -> -0.5 +atanpi10006 atanpi 1.0 -> 0.25 +atanpi10007 atanpi -1.0 -> -0.25 +atanpi10008 atanpi 0.75 -> 0.20483276469913345 +atanpi10009 atanpi 0.03125 -> 0.009943947823589275 +atanpi10010 atanpi 0.0009765625 -> 0.0003108493994100204 +atanpi10011 atanpi 3.0517578125e-05 -> 9.714046816558053e-06 +atanpi10012 atanpi 9.5367431640625e-07 -> 3.0356396311158577e-07 +atanpi10013 atanpi 2.9802322387695312e-08 -> 9.486373847239929e-09 +atanpi10014 atanpi 9.313225746154785e-10 -> 2.964491827262479e-10 +atanpi10015 atanpi 2.9103830456733704e-11 -> 9.264036960195246e-12 +atanpi10016 atanpi 9.094947017729282e-13 -> 2.8950115500610145e-13 +atanpi10017 atanpi 2.842170943040401e-14 -> 9.04691109394067e-15 +atanpi10018 atanpi 8.881784197001252e-16 -> 2.8271597168564594e-16 +atanpi10019 atanpi 2.7755575615628914e-17 -> 8.834874115176436e-18 +atanpi10020 atanpi 8.673617379884035e-19 -> 2.760898160992636e-19 +atanpi10021 atanpi 2.5 -> 0.3788810584091566 +atanpi10022 atanpi 10.0 -> 0.4682744825694464 +atanpi10023 atanpi 1000000.0 -> 0.49999968169011383 +atanpi10024 atanpi 2147483648.0 -> 0.4999999998517754 +atanpi10025 atanpi 7.888609052210118e-31 -> 2.5110222495574236e-31 +atanpi10026 atanpi 1.401298464324817e-45 -> 4.460471546887532e-46 +atanpi10027 atanpi 0.0 -> 0.0 +atanpi10028 atanpi 2.409919865102884e-181 -> 7.671013179729553e-182 +atanpi10029 atanpi 1.401298464324817e-45 -> 4.460471546887532e-46 +atanpi10030 atanpi 0.0 -> 0.0 +atanpi10031 atanpi 5e-324 -> 0.0 +atanpi10032 atanpi -0.23051215708255768 -> -0.07211461946620386 +atanpi10033 atanpi -0.20305541157722473 -> -0.06376756760558985 +atanpi10034 atanpi -2.1964359283447266 -> -0.36400572992968316 +atanpi10035 atanpi -1.2119029760360718 -> -0.2804016904047878 +atanpi10036 atanpi -1.6769415140151978 -> -0.32884096476652747 +atanpi10037 atanpi -3.9201369285583496 -> -0.4204968782420327 +atanpi10038 atanpi 3.327171802520752 -> 0.40706420561165213 +atanpi10039 atanpi -1.3468046188354492 -> -0.2967010012978093 +atanpi10040 atanpi 0.692195475101471 -> 0.1927267050671652 +atanpi10041 atanpi 1.1754943508222875e-38 -> 3.7417147301993126e-39 +atanpi10042 atanpi 2.2250738585072014e-308 -> 7.082630066519554e-309 +atanpi10043 atanpi 2.004168360008973e-292 -> 6.379466025676106e-293 +atanpi10044 atanpi -1.1754943508222875e-38 -> -3.7417147301993126e-39 +atanpi10045 atanpi -2.2250738585072014e-308 -> -7.082630066519554e-309 +atanpi10046 atanpi -2.004168360008973e-292 -> -6.379466025676106e-293 +atanpi10047 atanpi 1.401298464324817e-45 -> 4.460471546887532e-46 +atanpi10048 atanpi 5e-324 -> 0.0 +atanpi10049 atanpi -1.401298464324817e-45 -> -4.460471546887532e-46 +atanpi10050 atanpi -5e-324 -> -0.0 +atanpi10051 atanpi 0.721666157245636 -> 0.19898171607590034 +atanpi10052 atanpi 0.19824542105197906 -> 0.06229575837467328 +atanpi10053 atanpi 0.19824540615081787 -> 0.06229575381085028 +atanpi10054 atanpi 0.198245408653517 -> 0.06229575457735939 +atanpi10055 atanpi 0.049094054847955704 -> 0.01561458616872582 +atanpi10056 atanpi 0.049094051122665405 -> 0.015614584985780253 +atanpi10057 atanpi 0.04909405149251647 -> 0.015614585103224438 +atanpi10058 atanpi 0.049094051492516465 -> 0.015614585103224436 +atanpi10059 atanpi 0.19859454035758972 -> 0.062402677059315244 +atanpi10060 atanpi 0.19859452545642853 -> 0.06240267249610054 +atanpi10061 atanpi 0.1985945401764544 -> 0.06240267700384578 +atanpi10062 atanpi 0.19859454017645436 -> 0.06240267700384577 + +atanpi20001 atanpi inf -> 0.5 +atanpi20002 atanpi -inf -> -0.5 +atanpi20003 atanpi nan -> nan + +------------- +-- atan2pi -- +------------- + +atan2pi10000 atan2pi 0.0 1.0 -> 0.0 +atan2pi10001 atan2pi -0.0 1.0 -> -0.0 +atan2pi10002 atan2pi 0.0 0.0 -> 0.0 +atan2pi10003 atan2pi -0.0 0.0 -> -0.0 +atan2pi10004 atan2pi 0.0 -1.0 -> 1.0 +atan2pi10005 atan2pi -0.0 -1.0 -> -1.0 +atan2pi10006 atan2pi 0.0 -0.0 -> 1.0 +atan2pi10007 atan2pi -0.0 -0.0 -> -1.0 +atan2pi10008 atan2pi 1.0 0.0 -> 0.5 +atan2pi10009 atan2pi 1.0 -0.0 -> 0.5 +atan2pi10010 atan2pi -1.0 0.0 -> -0.5 +atan2pi10011 atan2pi -1.0 -0.0 -> -0.5 +atan2pi10012 atan2pi 3.4028234663852886e+38 3.4028234663852886e+38 -> 0.25 +atan2pi10013 atan2pi 3.4028234663852886e+38 1.7976931348623157e+308 -> 6.025234948519683e-271 +atan2pi10014 atan2pi 1.7976931348623157e+308 3.4028234663852886e+38 -> 0.5 +atan2pi10015 atan2pi 1.7976931348623157e+308 1.7976931348623157e+308 -> 0.25 +atan2pi10016 atan2pi 3.4028234663852886e+38 -3.4028234663852886e+38 -> 0.75 +atan2pi10017 atan2pi 3.4028234663852886e+38 -1.7976931348623157e+308 -> 1.0 +atan2pi10018 atan2pi 1.7976931348623157e+308 -3.4028234663852886e+38 -> 0.5 +atan2pi10019 atan2pi 1.7976931348623157e+308 -1.7976931348623157e+308 -> 0.75 +atan2pi10020 atan2pi -3.4028234663852886e+38 3.4028234663852886e+38 -> -0.25 +atan2pi10021 atan2pi -3.4028234663852886e+38 1.7976931348623157e+308 -> -6.025234948519683e-271 +atan2pi10022 atan2pi -1.7976931348623157e+308 3.4028234663852886e+38 -> -0.5 +atan2pi10023 atan2pi -1.7976931348623157e+308 1.7976931348623157e+308 -> -0.25 +atan2pi10024 atan2pi -3.4028234663852886e+38 -3.4028234663852886e+38 -> -0.75 +atan2pi10025 atan2pi -3.4028234663852886e+38 -1.7976931348623157e+308 -> -1.0 +atan2pi10026 atan2pi -1.7976931348623157e+308 -3.4028234663852886e+38 -> -0.5 +atan2pi10027 atan2pi -1.7976931348623157e+308 -1.7976931348623157e+308 -> -0.75 +atan2pi10028 atan2pi 3.4028234663852886e+38 1.1754943508222875e-38 -> 0.5 +atan2pi10029 atan2pi 3.4028234663852886e+38 2.2250738585072014e-308 -> 0.5 +atan2pi10030 atan2pi 3.4028234663852886e+38 2.004168360008973e-292 -> 0.5 +atan2pi10031 atan2pi 1.7976931348623157e+308 1.1754943508222875e-38 -> 0.5 +atan2pi10032 atan2pi 1.7976931348623157e+308 2.2250738585072014e-308 -> 0.5 +atan2pi10033 atan2pi 1.7976931348623157e+308 2.004168360008973e-292 -> 0.5 +atan2pi10034 atan2pi -3.4028234663852886e+38 -1.1754943508222875e-38 -> -0.5 +atan2pi10035 atan2pi -3.4028234663852886e+38 -2.2250738585072014e-308 -> -0.5 +atan2pi10036 atan2pi -3.4028234663852886e+38 -2.004168360008973e-292 -> -0.5 +atan2pi10037 atan2pi -1.7976931348623157e+308 -1.1754943508222875e-38 -> -0.5 +atan2pi10038 atan2pi -1.7976931348623157e+308 -2.2250738585072014e-308 -> -0.5 +atan2pi10039 atan2pi -1.7976931348623157e+308 -2.004168360008973e-292 -> -0.5 +atan2pi10040 atan2pi -3.4028234663852886e+38 1.1754943508222875e-38 -> -0.5 +atan2pi10041 atan2pi -3.4028234663852886e+38 2.2250738585072014e-308 -> -0.5 +atan2pi10042 atan2pi -3.4028234663852886e+38 2.004168360008973e-292 -> -0.5 +atan2pi10043 atan2pi -1.7976931348623157e+308 1.1754943508222875e-38 -> -0.5 +atan2pi10044 atan2pi -1.7976931348623157e+308 2.2250738585072014e-308 -> -0.5 +atan2pi10045 atan2pi -1.7976931348623157e+308 2.004168360008973e-292 -> -0.5 +atan2pi10046 atan2pi 3.4028234663852886e+38 -1.1754943508222875e-38 -> 0.5 +atan2pi10047 atan2pi 3.4028234663852886e+38 -2.2250738585072014e-308 -> 0.5 +atan2pi10048 atan2pi 3.4028234663852886e+38 -2.004168360008973e-292 -> 0.5 +atan2pi10049 atan2pi 1.7976931348623157e+308 -1.1754943508222875e-38 -> 0.5 +atan2pi10050 atan2pi 1.7976931348623157e+308 -2.2250738585072014e-308 -> 0.5 +atan2pi10051 atan2pi 1.7976931348623157e+308 -2.004168360008973e-292 -> 0.5 +atan2pi10052 atan2pi 3.4028234663852886e+38 1.401298464324817e-45 -> 0.5 +atan2pi10053 atan2pi 3.4028234663852886e+38 5e-324 -> 0.5 +atan2pi10054 atan2pi 1.7976931348623157e+308 1.401298464324817e-45 -> 0.5 +atan2pi10055 atan2pi 1.7976931348623157e+308 5e-324 -> 0.5 +atan2pi10056 atan2pi -3.4028234663852886e+38 -1.401298464324817e-45 -> -0.5 +atan2pi10057 atan2pi -3.4028234663852886e+38 -5e-324 -> -0.5 +atan2pi10058 atan2pi -1.7976931348623157e+308 -1.401298464324817e-45 -> -0.5 +atan2pi10059 atan2pi -1.7976931348623157e+308 -5e-324 -> -0.5 +atan2pi10060 atan2pi -3.4028234663852886e+38 1.401298464324817e-45 -> -0.5 +atan2pi10061 atan2pi -3.4028234663852886e+38 5e-324 -> -0.5 +atan2pi10062 atan2pi -1.7976931348623157e+308 1.401298464324817e-45 -> -0.5 +atan2pi10063 atan2pi -1.7976931348623157e+308 5e-324 -> -0.5 +atan2pi10064 atan2pi 3.4028234663852886e+38 -1.401298464324817e-45 -> 0.5 +atan2pi10065 atan2pi 3.4028234663852886e+38 -5e-324 -> 0.5 +atan2pi10066 atan2pi 1.7976931348623157e+308 -1.401298464324817e-45 -> 0.5 +atan2pi10067 atan2pi 1.7976931348623157e+308 -5e-324 -> 0.5 +atan2pi10068 atan2pi 0.75 1.0 -> 0.20483276469913345 +atan2pi10069 atan2pi -0.75 1.0 -> -0.20483276469913345 +atan2pi10070 atan2pi 0.75 -1.0 -> 0.7951672353008665 +atan2pi10071 atan2pi -0.75 -1.0 -> -0.7951672353008665 +atan2pi10072 atan2pi 0.390625 0.00029000002541579306 -> 0.4997636867632018 +atan2pi10073 atan2pi 0.390625 0.0002899999963119626 -> 0.49976368678691774 +atan2pi10074 atan2pi 0.390625 0.00029 -> 0.4997636867839124 +atan2pi10075 atan2pi 0.390625 0.00028999999999999995 -> 0.4997636867839124 +atan2pi10076 atan2pi 1.390625 0.9296875 -> 0.3124206399141909 +atan2pi10077 atan2pi -0.007568269968032837 -0.0017927357694134116 -> -0.5740351606831543 +atan2pi10078 atan2pi -0.007568269968032837 -0.0017927358858287334 -> -0.574035165319273 +atan2pi10079 atan2pi -0.007568269968032837 -0.001792735857538728 -> -0.5740351641926531 +atan2pi10080 atan2pi -0.007568269968032837 -0.0017927358575387281 -> -0.5740351641926531 +atan2pi10081 atan2pi -0.007568270433694124 -0.0017927357694134116 -> -0.5740351562904277 +atan2pi10082 atan2pi -0.007568270433694124 -0.0017927358858287334 -> -0.574035160926546 +atan2pi10083 atan2pi -0.007568270433694124 -0.001792735857538728 -> -0.5740351597999263 +atan2pi10084 atan2pi -0.007568270433694124 -0.0017927358575387281 -> -0.5740351597999263 +atan2pi10085 atan2pi -0.0075682704267110625 -0.0017927357694134116 -> -0.574035156356301 +atan2pi10086 atan2pi -0.0075682704267110625 -0.0017927358858287334 -> -0.5740351609924195 +atan2pi10087 atan2pi -0.0075682704267110625 -0.001792735857538728 -> -0.5740351598657996 +atan2pi10088 atan2pi -0.0075682704267110625 -0.0017927358575387281 -> -0.5740351598657996 +atan2pi10089 atan2pi -0.007568270426711063 -0.0017927357694134116 -> -0.574035156356301 +atan2pi10090 atan2pi -0.007568270426711063 -0.0017927358858287334 -> -0.5740351609924195 +atan2pi10091 atan2pi -0.007568270426711063 -0.001792735857538728 -> -0.5740351598657996 +atan2pi10092 atan2pi -0.007568270426711063 -0.0017927358575387281 -> -0.5740351598657996 +atan2pi10093 atan2pi 1.0000001192092896 1.0000001192092896 -> 0.25 +atan2pi10094 atan2pi 1.0000001192092896 1.0 -> 0.25000001897274654 +atan2pi10095 atan2pi 1.0000001192092896 1.0000000000000002 -> 0.25000001897274654 +atan2pi10096 atan2pi 1.0 1.0000001192092896 -> 0.24999998102725343 +atan2pi10097 atan2pi 1.0 1.0 -> 0.25 +atan2pi10098 atan2pi 1.0 1.0000000000000002 -> 0.24999999999999997 +atan2pi10099 atan2pi 1.0000000000000002 1.0000001192092896 -> 0.24999998102725346 +atan2pi10100 atan2pi 1.0000000000000002 1.0 -> 0.25000000000000006 +atan2pi10101 atan2pi 1.0000000000000002 1.0000000000000002 -> 0.25 +atan2pi10102 atan2pi 0.2977333664894104 2.9490208625793457 -> 0.032028064084188616 +atan2pi10103 atan2pi -1.346861771417407e-11 1.9269377760089412e-10 -> -0.022212615773618685 +atan2pi10104 atan2pi 0.3338441550731659 2.132420539855957 -> 0.04943220711796703 +atan2pi10105 atan2pi -0.2600718140602112 1.9549157619476318 -> -0.04209909110779262 +atan2pi10106 atan2pi -11223297.0 -0.9756588935852051 -> -0.50000002767118 +atan2pi10107 atan2pi 0.2590596377849579 7.252630710601807 -> 0.011365007240777592 +atan2pi10108 atan2pi 3.7716573755879195e+20 3.019230078687783e+21 -> 0.03955871588967838 +atan2pi10109 atan2pi -0.41808438301086426 3.5622718334198 -> -0.03718816634303022 +atan2pi10110 atan2pi -0.0 3.4028234663852886e+38 -> -0.0 +atan2pi10111 atan2pi -1.401298464324817e-45 3.4028234663852886e+38 -> -1.3108148544731147e-84 +atan2pi10112 atan2pi -8.028930810726831e-218 3.4028234663852886e+38 -> -7.510492618222167e-257 +atan2pi10113 atan2pi 3.943100929260254 -1.3295949697494507 -> 0.6035214600176284 +atan2pi10114 atan2pi -9.648418597407726e-08 1.6104578133839705e-15 -> -0.49999999468695683 +atan2pi10115 atan2pi -1112287276433408.0 4415830896934912.0 -> -0.07854398572055855 +atan2pi10116 atan2pi 9.642213451703619e-17 9.633302400400708e-17 -> 0.2501471543249841 +atan2pi10117 atan2pi 9.642213451703619e-17 9.633301738656218e-17 -> 0.25014716525787717 +atan2pi10118 atan2pi 9.642213451703619e-17 9.633302010283342e-17 -> 0.2501471607702382 +atan2pi10119 atan2pi 9.642212789959129e-17 9.633302400400708e-17 -> 0.25014714340219485 +atan2pi10120 atan2pi 9.642212789959129e-17 9.633301738656218e-17 -> 0.25014715433508794 +atan2pi10121 atan2pi 9.642212789959129e-17 9.633302010283342e-17 -> 0.25014714984744896 +atan2pi10122 atan2pi 9.642213402663379e-17 9.633302400400708e-17 -> 0.25014715351552336 +atan2pi10123 atan2pi 9.642213402663379e-17 9.633301738656218e-17 -> 0.25014716444841645 +atan2pi10124 atan2pi 9.642213402663379e-17 9.633302010283342e-17 -> 0.25014715996077747 +atan2pi10125 atan2pi 1.401298464324817e-45 1.401298464324817e-45 -> 0.25 +atan2pi10126 atan2pi 1.401298464324817e-45 0.0 -> 0.5 +atan2pi10127 atan2pi 1.401298464324817e-45 2.6248243660802892e-105 -> 0.5 +atan2pi10128 atan2pi 0.0 1.401298464324817e-45 -> 0.0 +atan2pi10129 atan2pi 0.0 0.0 -> 0.0 +atan2pi10130 atan2pi 0.0 2.6248243660802892e-105 -> 0.0 +atan2pi10131 atan2pi 2.841564668406762e-105 1.401298464324817e-45 -> 6.454714318268012e-61 +atan2pi10132 atan2pi 2.841564668406762e-105 0.0 -> 0.5 +atan2pi10133 atan2pi 2.841564668406762e-105 2.6248243660802892e-105 -> 0.262614261697575 +atan2pi10134 atan2pi 1.401298464324817e-45 1.401298464324817e-45 -> 0.25 +atan2pi10135 atan2pi 1.401298464324817e-45 0.0 -> 0.5 +atan2pi10136 atan2pi 1.401298464324817e-45 1.6955960445645656e-177 -> 0.5 +atan2pi10137 atan2pi 0.0 1.401298464324817e-45 -> 0.0 +atan2pi10138 atan2pi 0.0 0.0 -> 0.0 +atan2pi10139 atan2pi 0.0 1.6955960445645656e-177 -> 0.0 +atan2pi10140 atan2pi 1.697410900901164e-177 1.401298464324817e-45 -> 3.855728700404359e-133 +atan2pi10141 atan2pi 1.697410900901164e-177 0.0 -> 0.5 +atan2pi10142 atan2pi 1.697410900901164e-177 1.6955960445645656e-177 -> 0.2501702580242645 +atan2pi10143 atan2pi 1.401298464324817e-45 1.401298464324817e-45 -> 0.25 +atan2pi10144 atan2pi 1.401298464324817e-45 0.0 -> 0.5 +atan2pi10145 atan2pi 1.401298464324817e-45 4.642262744535978e-191 -> 0.5 +atan2pi10146 atan2pi 0.0 1.401298464324817e-45 -> 0.0 +atan2pi10147 atan2pi 0.0 0.0 -> 0.0 +atan2pi10148 atan2pi 0.0 4.642262744535978e-191 -> 0.0 +atan2pi10149 atan2pi 4.6493548767531986e-191 1.401298464324817e-45 -> 1.0561173506747795e-146 +atan2pi10150 atan2pi 4.6493548767531986e-191 0.0 -> 0.5 +atan2pi10151 atan2pi 4.6493548767531986e-191 4.642262744535978e-191 -> 0.2502429604243814 +atan2pi10152 atan2pi 1.401298464324817e-45 1.401298464324817e-45 -> 0.25 +atan2pi10153 atan2pi 1.401298464324817e-45 0.0 -> 0.5 +atan2pi10154 atan2pi 1.401298464324817e-45 5e-324 -> 0.5 +atan2pi10155 atan2pi 0.0 1.401298464324817e-45 -> 0.0 +atan2pi10156 atan2pi 0.0 0.0 -> 0.0 +atan2pi10157 atan2pi 0.0 5e-324 -> 0.0 +atan2pi10158 atan2pi 5e-324 1.401298464324817e-45 -> 1.122287531877252e-279 +atan2pi10159 atan2pi 5e-324 0.0 -> 0.5 +atan2pi10160 atan2pi 5e-324 5e-324 -> 0.25 +atan2pi10161 atan2pi 1.1754943508222875e-38 1.1754943508222875e-38 -> 0.25 +atan2pi10162 atan2pi 1.1754943508222875e-38 2.2250738585072014e-308 -> 0.5 +atan2pi10163 atan2pi 1.1754943508222875e-38 2.004168360008973e-292 -> 0.5 +atan2pi10164 atan2pi 2.2250738585072014e-308 1.1754943508222875e-38 -> 6.025235307651693e-271 +atan2pi10165 atan2pi 2.2250738585072014e-308 2.2250738585072014e-308 -> 0.25 +atan2pi10166 atan2pi 2.2250738585072014e-308 2.004168360008973e-292 -> 3.533949646070574e-17 +atan2pi10167 atan2pi 2.004168360008973e-292 1.1754943508222875e-38 -> 5.427049497271944e-255 +atan2pi10168 atan2pi 2.004168360008973e-292 2.2250738585072014e-308 -> 0.49999999999999994 +atan2pi10169 atan2pi 2.004168360008973e-292 2.004168360008973e-292 -> 0.25 +atan2pi10170 atan2pi 1.1754943508222875e-38 -1.1754943508222875e-38 -> 0.75 +atan2pi10171 atan2pi 1.1754943508222875e-38 -2.2250738585072014e-308 -> 0.5 +atan2pi10172 atan2pi 1.1754943508222875e-38 -2.004168360008973e-292 -> 0.5 +atan2pi10173 atan2pi 2.2250738585072014e-308 -1.1754943508222875e-38 -> 1.0 +atan2pi10174 atan2pi 2.2250738585072014e-308 -2.2250738585072014e-308 -> 0.75 +atan2pi10175 atan2pi 2.2250738585072014e-308 -2.004168360008973e-292 -> 1.0 +atan2pi10176 atan2pi 2.004168360008973e-292 -1.1754943508222875e-38 -> 1.0 +atan2pi10177 atan2pi 2.004168360008973e-292 -2.2250738585072014e-308 -> 0.5 +atan2pi10178 atan2pi 2.004168360008973e-292 -2.004168360008973e-292 -> 0.75 +atan2pi10179 atan2pi -1.1754943508222875e-38 1.1754943508222875e-38 -> -0.25 +atan2pi10180 atan2pi -1.1754943508222875e-38 2.2250738585072014e-308 -> -0.5 +atan2pi10181 atan2pi -1.1754943508222875e-38 2.004168360008973e-292 -> -0.5 +atan2pi10182 atan2pi -2.2250738585072014e-308 1.1754943508222875e-38 -> -6.025235307651693e-271 +atan2pi10183 atan2pi -2.2250738585072014e-308 2.2250738585072014e-308 -> -0.25 +atan2pi10184 atan2pi -2.2250738585072014e-308 2.004168360008973e-292 -> -3.533949646070574e-17 +atan2pi10185 atan2pi -2.004168360008973e-292 1.1754943508222875e-38 -> -5.427049497271944e-255 +atan2pi10186 atan2pi -2.004168360008973e-292 2.2250738585072014e-308 -> -0.49999999999999994 +atan2pi10187 atan2pi -2.004168360008973e-292 2.004168360008973e-292 -> -0.25 +atan2pi10188 atan2pi -1.1754943508222875e-38 -1.1754943508222875e-38 -> -0.75 +atan2pi10189 atan2pi -1.1754943508222875e-38 -2.2250738585072014e-308 -> -0.5 +atan2pi10190 atan2pi -1.1754943508222875e-38 -2.004168360008973e-292 -> -0.5 +atan2pi10191 atan2pi -2.2250738585072014e-308 -1.1754943508222875e-38 -> -1.0 +atan2pi10192 atan2pi -2.2250738585072014e-308 -2.2250738585072014e-308 -> -0.75 +atan2pi10193 atan2pi -2.2250738585072014e-308 -2.004168360008973e-292 -> -1.0 +atan2pi10194 atan2pi -2.004168360008973e-292 -1.1754943508222875e-38 -> -1.0 +atan2pi10195 atan2pi -2.004168360008973e-292 -2.2250738585072014e-308 -> -0.5 +atan2pi10196 atan2pi -2.004168360008973e-292 -2.004168360008973e-292 -> -0.75 +atan2pi10197 atan2pi 1.401298464324817e-45 1.401298464324817e-45 -> 0.25 +atan2pi10198 atan2pi 1.401298464324817e-45 5e-324 -> 0.5 +atan2pi10199 atan2pi 5e-324 1.401298464324817e-45 -> 1.122287531877252e-279 +atan2pi10200 atan2pi 5e-324 5e-324 -> 0.25 +atan2pi10201 atan2pi 1.401298464324817e-45 -1.401298464324817e-45 -> 0.75 +atan2pi10202 atan2pi 1.401298464324817e-45 -5e-324 -> 0.5 +atan2pi10203 atan2pi 5e-324 -1.401298464324817e-45 -> 1.0 +atan2pi10204 atan2pi 5e-324 -5e-324 -> 0.75 +atan2pi10205 atan2pi -1.401298464324817e-45 1.401298464324817e-45 -> -0.25 +atan2pi10206 atan2pi -1.401298464324817e-45 5e-324 -> -0.5 +atan2pi10207 atan2pi -5e-324 1.401298464324817e-45 -> -1.122287531877252e-279 +atan2pi10208 atan2pi -5e-324 5e-324 -> -0.25 +atan2pi10209 atan2pi -1.401298464324817e-45 -1.401298464324817e-45 -> -0.75 +atan2pi10210 atan2pi -1.401298464324817e-45 -5e-324 -> -0.5 +atan2pi10211 atan2pi -5e-324 -1.401298464324817e-45 -> -1.0 +atan2pi10212 atan2pi -5e-324 -5e-324 -> -0.75 +atan2pi10213 atan2pi 1.1754943508222875e-38 1.401298464324817e-45 -> 0.4999999620545046 +atan2pi10214 atan2pi 1.1754943508222875e-38 5e-324 -> 0.5 +atan2pi10215 atan2pi 2.2250738585072014e-308 1.401298464324817e-45 -> 5.054333710364945e-264 +atan2pi10216 atan2pi 2.2250738585072014e-308 5e-324 -> 0.49999999999999994 +atan2pi10217 atan2pi 2.004168360008973e-292 1.401298464324817e-45 -> 4.552539082921141e-248 +atan2pi10218 atan2pi 2.004168360008973e-292 5e-324 -> 0.5 +atan2pi10219 atan2pi 1.1754943508222875e-38 -1.401298464324817e-45 -> 0.5000000379454954 +atan2pi10220 atan2pi 1.1754943508222875e-38 -5e-324 -> 0.5 +atan2pi10221 atan2pi 2.2250738585072014e-308 -1.401298464324817e-45 -> 1.0 +atan2pi10222 atan2pi 2.2250738585072014e-308 -5e-324 -> 0.5000000000000001 +atan2pi10223 atan2pi 2.004168360008973e-292 -1.401298464324817e-45 -> 1.0 +atan2pi10224 atan2pi 2.004168360008973e-292 -5e-324 -> 0.5 +atan2pi10225 atan2pi -1.1754943508222875e-38 1.401298464324817e-45 -> -0.4999999620545046 +atan2pi10226 atan2pi -1.1754943508222875e-38 5e-324 -> -0.5 +atan2pi10227 atan2pi -2.2250738585072014e-308 1.401298464324817e-45 -> -5.054333710364945e-264 +atan2pi10228 atan2pi -2.2250738585072014e-308 5e-324 -> -0.49999999999999994 +atan2pi10229 atan2pi -2.004168360008973e-292 1.401298464324817e-45 -> -4.552539082921141e-248 +atan2pi10230 atan2pi -2.004168360008973e-292 5e-324 -> -0.5 +atan2pi10231 atan2pi -1.1754943508222875e-38 -1.401298464324817e-45 -> -0.5000000379454954 +atan2pi10232 atan2pi -1.1754943508222875e-38 -5e-324 -> -0.5 +atan2pi10233 atan2pi -2.2250738585072014e-308 -1.401298464324817e-45 -> -1.0 +atan2pi10234 atan2pi -2.2250738585072014e-308 -5e-324 -> -0.5000000000000001 +atan2pi10235 atan2pi -2.004168360008973e-292 -1.401298464324817e-45 -> -1.0 +atan2pi10236 atan2pi -2.004168360008973e-292 -5e-324 -> -0.5 +atan2pi10237 atan2pi 1.401298464324817e-45 1.1754943508222875e-38 -> 3.7945495388959543e-08 +atan2pi10238 atan2pi 1.401298464324817e-45 2.2250738585072014e-308 -> 0.5 +atan2pi10239 atan2pi 1.401298464324817e-45 2.004168360008973e-292 -> 0.5 +atan2pi10240 atan2pi 5e-324 1.1754943508222875e-38 -> 1.3378709934678696e-286 +atan2pi10241 atan2pi 5e-324 2.2250738585072014e-308 -> 7.067899292141149e-17 +atan2pi10242 atan2pi 5e-324 2.004168360008973e-292 -> 7.846944529866949e-33 +atan2pi10243 atan2pi 1.401298464324817e-45 -1.1754943508222875e-38 -> 0.9999999620545046 +atan2pi10244 atan2pi 1.401298464324817e-45 -2.2250738585072014e-308 -> 0.5 +atan2pi10245 atan2pi 1.401298464324817e-45 -2.004168360008973e-292 -> 0.5 +atan2pi10246 atan2pi 5e-324 -1.1754943508222875e-38 -> 1.0 +atan2pi10247 atan2pi 5e-324 -2.2250738585072014e-308 -> 0.9999999999999999 +atan2pi10248 atan2pi 5e-324 -2.004168360008973e-292 -> 1.0 +atan2pi10249 atan2pi -1.401298464324817e-45 1.1754943508222875e-38 -> -3.7945495388959543e-08 +atan2pi10250 atan2pi -1.401298464324817e-45 2.2250738585072014e-308 -> -0.5 +atan2pi10251 atan2pi -1.401298464324817e-45 2.004168360008973e-292 -> -0.5 +atan2pi10252 atan2pi -5e-324 1.1754943508222875e-38 -> -1.3378709934678696e-286 +atan2pi10253 atan2pi -5e-324 2.2250738585072014e-308 -> -7.067899292141149e-17 +atan2pi10254 atan2pi -5e-324 2.004168360008973e-292 -> -7.846944529866949e-33 +atan2pi10255 atan2pi -1.401298464324817e-45 -1.1754943508222875e-38 -> -0.9999999620545046 +atan2pi10256 atan2pi -1.401298464324817e-45 -2.2250738585072014e-308 -> -0.5 +atan2pi10257 atan2pi -1.401298464324817e-45 -2.004168360008973e-292 -> -0.5 +atan2pi10258 atan2pi -5e-324 -1.1754943508222875e-38 -> -1.0 +atan2pi10259 atan2pi -5e-324 -2.2250738585072014e-308 -> -0.9999999999999999 +atan2pi10260 atan2pi -5e-324 -2.004168360008973e-292 -> -1.0 +atan2pi10261 atan2pi 1.0 -3.4028234663852886e+38 -> 1.0 +atan2pi10262 atan2pi 1.0 -1.7976931348623157e+308 -> 1.0 +atan2pi10263 atan2pi -1.0 -3.4028234663852886e+38 -> -1.0 +atan2pi10264 atan2pi -1.0 -1.7976931348623157e+308 -> -1.0 +atan2pi10265 atan2pi 1.1754943508222875e-38 -3.4028234663852886e+38 -> 1.0 +atan2pi10266 atan2pi 1.1754943508222875e-38 -1.7976931348623157e+308 -> 1.0 +atan2pi10267 atan2pi 2.2250738585072014e-308 -3.4028234663852886e+38 -> 1.0 +atan2pi10268 atan2pi 2.2250738585072014e-308 -1.7976931348623157e+308 -> 1.0 +atan2pi10269 atan2pi 2.004168360008973e-292 -3.4028234663852886e+38 -> 1.0 +atan2pi10270 atan2pi 2.004168360008973e-292 -1.7976931348623157e+308 -> 1.0 +atan2pi10271 atan2pi -1.1754943508222875e-38 -3.4028234663852886e+38 -> -1.0 +atan2pi10272 atan2pi -1.1754943508222875e-38 -1.7976931348623157e+308 -> -1.0 +atan2pi10273 atan2pi -2.2250738585072014e-308 -3.4028234663852886e+38 -> -1.0 +atan2pi10274 atan2pi -2.2250738585072014e-308 -1.7976931348623157e+308 -> -1.0 +atan2pi10275 atan2pi -2.004168360008973e-292 -3.4028234663852886e+38 -> -1.0 +atan2pi10276 atan2pi -2.004168360008973e-292 -1.7976931348623157e+308 -> -1.0 +atan2pi10277 atan2pi 1.401298464324817e-45 -3.4028234663852886e+38 -> 1.0 +atan2pi10278 atan2pi 1.401298464324817e-45 -1.7976931348623157e+308 -> 1.0 +atan2pi10279 atan2pi 5e-324 -3.4028234663852886e+38 -> 1.0 +atan2pi10280 atan2pi 5e-324 -1.7976931348623157e+308 -> 1.0 +atan2pi10281 atan2pi -1.401298464324817e-45 -3.4028234663852886e+38 -> -1.0 +atan2pi10282 atan2pi -1.401298464324817e-45 -1.7976931348623157e+308 -> -1.0 +atan2pi10283 atan2pi -5e-324 -3.4028234663852886e+38 -> -1.0 +atan2pi10284 atan2pi -5e-324 -1.7976931348623157e+308 -> -1.0 +atan2pi10285 atan2pi 1.0 3.4028234663852886e+38 -> 9.354287383057258e-40 +atan2pi10286 atan2pi 1.0 1.7976931348623157e+308 -> 1.770657516629887e-309 +atan2pi10287 atan2pi -1.0 3.4028234663852886e+38 -> -9.354287383057258e-40 +atan2pi10288 atan2pi -1.0 1.7976931348623157e+308 -> -1.770657516629887e-309 +atan2pi10289 atan2pi 1.1754943508222875e-38 3.4028234663852886e+38 -> 1.0995911974752006e-77 +atan2pi10290 atan2pi 1.1754943508222875e-38 1.7976931348623157e+308 -> 0.0 +atan2pi10291 atan2pi 2.2250738585072014e-308 3.4028234663852886e+38 -> 0.0 +atan2pi10292 atan2pi 2.2250738585072014e-308 1.7976931348623157e+308 -> 0.0 +atan2pi10293 atan2pi 2.004168360008973e-292 3.4028234663852886e+38 -> 0.0 +atan2pi10294 atan2pi 2.004168360008973e-292 1.7976931348623157e+308 -> 0.0 +atan2pi10295 atan2pi -1.1754943508222875e-38 3.4028234663852886e+38 -> -1.0995911974752006e-77 +atan2pi10296 atan2pi -1.1754943508222875e-38 1.7976931348623157e+308 -> -0.0 +atan2pi10297 atan2pi -2.2250738585072014e-308 3.4028234663852886e+38 -> -0.0 +atan2pi10298 atan2pi -2.2250738585072014e-308 1.7976931348623157e+308 -> -0.0 +atan2pi10299 atan2pi -2.004168360008973e-292 3.4028234663852886e+38 -> -0.0 +atan2pi10300 atan2pi -2.004168360008973e-292 1.7976931348623157e+308 -> -0.0 +atan2pi10301 atan2pi 1.401298464324817e-45 3.4028234663852886e+38 -> 1.3108148544731147e-84 +atan2pi10302 atan2pi 1.401298464324817e-45 1.7976931348623157e+308 -> 0.0 +atan2pi10303 atan2pi 5e-324 3.4028234663852886e+38 -> 0.0 +atan2pi10304 atan2pi 5e-324 1.7976931348623157e+308 -> 0.0 +atan2pi10305 atan2pi -1.401298464324817e-45 3.4028234663852886e+38 -> -1.3108148544731147e-84 +atan2pi10306 atan2pi -1.401298464324817e-45 1.7976931348623157e+308 -> -0.0 +atan2pi10307 atan2pi -5e-324 3.4028234663852886e+38 -> -0.0 +atan2pi10308 atan2pi -5e-324 1.7976931348623157e+308 -> -0.0 +atan2pi10309 atan2pi 1.1754943508222875e-38 1.0 -> 3.7417147301993126e-39 +atan2pi10310 atan2pi 2.2250738585072014e-308 1.0 -> 7.082630066519554e-309 +atan2pi10311 atan2pi 2.004168360008973e-292 1.0 -> 6.379466025676106e-293 +atan2pi10312 atan2pi -1.1754943508222875e-38 1.0 -> -3.7417147301993126e-39 +atan2pi10313 atan2pi -2.2250738585072014e-308 1.0 -> -7.082630066519554e-309 +atan2pi10314 atan2pi -2.004168360008973e-292 1.0 -> -6.379466025676106e-293 +atan2pi10315 atan2pi 1.401298464324817e-45 1.0 -> 4.460471546887532e-46 +atan2pi10316 atan2pi 5e-324 1.0 -> 0.0 +atan2pi10317 atan2pi -1.401298464324817e-45 1.0 -> -4.460471546887532e-46 +atan2pi10318 atan2pi -5e-324 1.0 -> -0.0 +atan2pi10319 atan2pi 1.1754943508222875e-38 -1.0 -> 1.0 +atan2pi10320 atan2pi 2.2250738585072014e-308 -1.0 -> 1.0 +atan2pi10321 atan2pi 2.004168360008973e-292 -1.0 -> 1.0 +atan2pi10322 atan2pi -1.1754943508222875e-38 -1.0 -> -1.0 +atan2pi10323 atan2pi -2.2250738585072014e-308 -1.0 -> -1.0 +atan2pi10324 atan2pi -2.004168360008973e-292 -1.0 -> -1.0 +atan2pi10325 atan2pi 1.401298464324817e-45 -1.0 -> 1.0 +atan2pi10326 atan2pi 5e-324 -1.0 -> 1.0 +atan2pi10327 atan2pi -1.401298464324817e-45 -1.0 -> -1.0 +atan2pi10328 atan2pi -5e-324 -1.0 -> -1.0 +atan2pi10329 atan2pi -4.3609299609670416e-05 0.05748599022626877 -> -0.0002414722000586593 +atan2pi10330 atan2pi -3.4028234663852886e+38 3.4028234663852886e+38 -> -0.25 +atan2pi10331 atan2pi -3.4028234663852886e+38 2.8061581043948965e+103 -> -3.8599120576714543e-66 +atan2pi10332 atan2pi -9.822050856552661e+114 3.4028234663852886e+38 -> -0.5 +atan2pi10333 atan2pi -9.822050856552661e+114 2.8061581043948965e+103 -> -0.4999999999990906 +atan2pi10334 atan2pi 3.4028234663852886e+38 3.4028234663852886e+38 -> 0.25 +atan2pi10335 atan2pi 3.4028234663852886e+38 1.7976931348623157e+308 -> 6.025234948519683e-271 +atan2pi10336 atan2pi 2.962077767429005e+64 3.4028234663852886e+38 -> 0.5 +atan2pi10337 atan2pi 2.962077767429005e+64 1.7976931348623157e+308 -> 5.244825263740446e-245 +atan2pi10338 atan2pi 2.9620777674290047e+64 3.4028234663852886e+38 -> 0.5 +atan2pi10339 atan2pi 2.9620777674290047e+64 1.7976931348623157e+308 -> 5.244825263740445e-245 +atan2pi10340 atan2pi -3.4028234663852886e+38 3.4028234663852886e+38 -> -0.25 +atan2pi10341 atan2pi -3.4028234663852886e+38 1.7976931348623157e+308 -> -6.025234948519683e-271 +atan2pi10342 atan2pi -1.7976931348623157e+308 3.4028234663852886e+38 -> -0.5 +atan2pi10343 atan2pi -1.7976931348623157e+308 1.7976931348623157e+308 -> -0.25 + +atan2pi20000 atan2pi inf 0 -> 0.5 +atan2pi20001 atan2pi -inf 0 -> -0.5 +atan2pi20002 atan2pi nan 0 -> nan + +atan2pi20000 atan2pi inf -0 -> 0.5 +atan2pi20001 atan2pi -inf -0 -> -0.5 +atan2pi20002 atan2pi nan -0 -> nan + +atan2pi20003 atan2pi inf 1 -> 0.5 +atan2pi20004 atan2pi -inf 1 -> -0.5 +atan2pi20005 atan2pi nan 1 -> nan + +atan2pi20006 atan2pi inf -1 -> 0.5 +atan2pi20007 atan2pi -inf -1 -> -0.5 +atan2pi20008 atan2pi nan -1 -> nan + +atan2pi20009 atan2pi inf inf -> 0.25 +atan2pi20010 atan2pi -inf inf -> -0.25 +atan2pi20011 atan2pi nan inf -> nan + +atan2pi20012 atan2pi inf -inf -> .75 +atan2pi20013 atan2pi -inf -inf -> -.75 +atan2pi20014 atan2pi nan -inf -> nan + +atan2pi20015 atan2pi inf nan -> nan +atan2pi20016 atan2pi -inf nan -> nan +atan2pi20017 atan2pi nan nan -> nan + +atan2pi30000 atan2pi 0 inf -> 0.0 +atan2pi30001 atan2pi 0 -inf -> 1.0 +atan2pi30002 atan2pi 0 nan -> nan + +atan2pi30000 atan2pi -0 inf -> -0.0 +atan2pi30001 atan2pi -0 -inf -> -1.0 +atan2pi30002 atan2pi -0 nan -> nan + +atan2pi30003 atan2pi 1 inf -> 0.0 +atan2pi30004 atan2pi 1 -inf -> 1.0 +atan2pi30005 atan2pi 1 nan -> nan + +atan2pi30006 atan2pi -1 inf -> -0.0 +atan2pi30007 atan2pi -1 -inf -> -1.0 +atan2pi30008 atan2pi -1 nan -> nan + +----------- +-- cospi -- +----------- + +cospi10000 cospi 0.0 -> 1.0 +cospi10001 cospi -0.0 -> 1.0 +cospi10002 cospi 1.1754943508222875e-38 -> 1.0 +cospi10003 cospi 2.2250738585072014e-308 -> 1.0 +cospi10004 cospi 2.004168360008973e-292 -> 1.0 +cospi10005 cospi -1.1754943508222875e-38 -> 1.0 +cospi10006 cospi -2.2250738585072014e-308 -> 1.0 +cospi10007 cospi -2.004168360008973e-292 -> 1.0 +cospi10008 cospi 1.401298464324817e-45 -> 1.0 +cospi10009 cospi 5e-324 -> 1.0 +cospi10010 cospi -1.401298464324817e-45 -> 1.0 +cospi10011 cospi -5e-324 -> 1.0 +cospi10012 cospi 3.4028234663852886e+38 -> 1.0 +cospi10013 cospi 1.7976931348623157e+308 -> 1.0 +cospi10014 cospi -3.4028234663852886e+38 -> 1.0 +cospi10015 cospi -1.7976931348623157e+308 -> 1.0 +cospi10016 cospi 1.0 -> -1.0 +cospi10017 cospi -1.0 -> -1.0 +cospi10018 cospi 2.0 -> 1.0 +cospi10019 cospi -2.0 -> 1.0 +cospi10020 cospi 3.0 -> -1.0 +cospi10021 cospi -3.0 -> -1.0 +cospi10022 cospi 0.10000000149011612 -> 0.9510565148485406 +cospi10023 cospi 0.09999999403953552 -> 0.9510565220816052 +cospi10024 cospi 0.1 -> 0.9510565162951535 +cospi10025 cospi 0.09999999999999999 -> 0.9510565162951535 +cospi10026 cospi -0.09999999403953552 -> 0.9510565220816052 +cospi10027 cospi -0.10000000149011612 -> 0.9510565148485406 +cospi10028 cospi -0.09999999999999999 -> 0.9510565162951535 +cospi10029 cospi -0.1 -> 0.9510565162951535 +cospi10030 cospi 0.20000000298023224 -> 0.8090169888717047 +cospi10031 cospi 0.19999998807907104 -> 0.8090170163879177 +cospi10032 cospi 0.2 -> 0.8090169943749475 +cospi10033 cospi 0.19999999999999998 -> 0.8090169943749475 +cospi10034 cospi -0.19999998807907104 -> 0.8090170163879177 +cospi10035 cospi -0.20000000298023224 -> 0.8090169888717047 +cospi10036 cospi -0.19999999999999998 -> 0.8090169943749475 +cospi10037 cospi -0.2 -> 0.8090169943749475 +cospi10038 cospi 0.30000001192092896 -> 0.5877852219942177 +cospi10039 cospi 0.29999998211860657 -> 0.5877852977398548 +cospi10040 cospi 0.30000000000000004 -> 0.587785252292473 +cospi10041 cospi 0.3 -> 0.5877852522924731 +cospi10042 cospi -0.29999998211860657 -> 0.5877852977398548 +cospi10043 cospi -0.30000001192092896 -> 0.5877852219942177 +cospi10044 cospi -0.3 -> 0.5877852522924731 +cospi10045 cospi -0.30000000000000004 -> 0.587785252292473 +cospi10046 cospi 0.4000000059604645 -> 0.3090169765660799 +cospi10047 cospi 0.3999999761581421 -> 0.3090170656104165 +cospi10048 cospi 0.4 -> 0.30901699437494734 +cospi10049 cospi 0.39999999999999997 -> 0.3090169943749475 +cospi10050 cospi -0.3999999761581421 -> 0.3090170656104165 +cospi10051 cospi -0.4000000059604645 -> 0.3090169765660799 +cospi10052 cospi -0.39999999999999997 -> 0.3090169943749475 +cospi10053 cospi -0.4 -> 0.30901699437494734 +cospi10054 cospi 0.5 -> 0.0 +cospi10055 cospi -0.5 -> 0.0 +cospi10056 cospi 0.6000000238418579 -> -0.3090170656104165 +cospi10057 cospi 0.5999999642372131 -> -0.30901688752174056 +cospi10058 cospi 0.6000000000000001 -> -0.3090169943749477 +cospi10059 cospi 0.6 -> -0.30901699437494734 +cospi10060 cospi -0.5999999642372131 -> -0.30901688752174056 +cospi10061 cospi -0.6000000238418579 -> -0.3090170656104165 +cospi10062 cospi -0.6 -> -0.30901699437494734 +cospi10063 cospi -0.6000000000000001 -> -0.3090169943749477 +cospi10064 cospi 0.7000000476837158 -> -0.5877853734854867 +cospi10065 cospi 0.699999988079071 -> -0.5877852219942177 +cospi10066 cospi 0.7000000000000001 -> -0.5877852522924732 +cospi10067 cospi 0.7 -> -0.587785252292473 +cospi10068 cospi -0.699999988079071 -> -0.5877852219942177 +cospi10069 cospi -0.7000000476837158 -> -0.5877853734854867 +cospi10070 cospi -0.7 -> -0.587785252292473 +cospi10071 cospi -0.7000000000000001 -> -0.5877852522924732 +cospi10072 cospi 0.800000011920929 -> -0.8090170163879177 +cospi10073 cospi 0.7999999523162842 -> -0.8090169063230551 +cospi10074 cospi 0.8 -> -0.8090169943749475 +cospi10075 cospi 0.7999999999999999 -> -0.8090169943749473 +cospi10076 cospi -0.7999999523162842 -> -0.8090169063230551 +cospi10077 cospi -0.800000011920929 -> -0.8090170163879177 +cospi10078 cospi -0.7999999999999999 -> -0.8090169943749473 +cospi10079 cospi -0.8 -> -0.8090169943749475 +cospi10080 cospi 0.9000000357627869 -> -0.9510565510138584 +cospi10081 cospi 0.8999999761581421 -> -0.9510564931493437 +cospi10082 cospi 0.9 -> -0.9510565162951536 +cospi10083 cospi 0.8999999999999999 -> -0.9510565162951535 +cospi10084 cospi -0.8999999761581421 -> -0.9510564931493437 +cospi10085 cospi -0.9000000357627869 -> -0.9510565510138584 +cospi10086 cospi -0.8999999999999999 -> -0.9510565162951535 +cospi10087 cospi -0.9 -> -0.9510565162951536 +cospi10088 cospi 1.100000023841858 -> -0.9510564931493437 +cospi10089 cospi 1.0999999046325684 -> -0.9510566088783399 +cospi10090 cospi 1.1 -> -0.9510565162951535 +cospi10091 cospi 1.0999999999999999 -> -0.9510565162951538 +cospi10092 cospi -1.0999999046325684 -> -0.9510566088783399 +cospi10093 cospi -1.100000023841858 -> -0.9510564931493437 +cospi10094 cospi -1.0999999999999999 -> -0.9510565162951538 +cospi10095 cospi -1.1 -> -0.9510565162951535 +cospi10096 cospi 1.2000000476837158 -> -0.8090169063230551 +cospi10097 cospi 1.1999999284744263 -> -0.8090171264527518 +cospi10098 cospi 1.2000000000000002 -> -0.8090169943749471 +cospi10099 cospi 1.2 -> -0.8090169943749475 +cospi10100 cospi -1.1999999284744263 -> -0.8090171264527518 +cospi10101 cospi -1.2000000476837158 -> -0.8090169063230551 +cospi10102 cospi -1.2 -> -0.8090169943749475 +cospi10103 cospi -1.2000000000000002 -> -0.8090169943749471 +cospi10104 cospi 1.3000000715255737 -> -0.587785070502928 +cospi10105 cospi 1.2999999523162842 -> -0.5877853734854867 +cospi10106 cospi 1.3 -> -0.587785252292473 +cospi10107 cospi 1.2999999999999998 -> -0.5877852522924736 +cospi10108 cospi -1.2999999523162842 -> -0.5877853734854867 +cospi10109 cospi -1.3000000715255737 -> -0.587785070502928 +cospi10110 cospi -1.2999999999999998 -> -0.5877852522924736 +cospi10111 cospi -1.3 -> -0.587785252292473 +cospi10112 cospi 1.4000000953674316 -> -0.3090167094330538 +cospi10113 cospi 1.399999976158142 -> -0.3090170656104165 +cospi10114 cospi 1.4000000000000001 -> -0.309016994374947 +cospi10115 cospi 1.4 -> -0.3090169943749477 +cospi10116 cospi -1.399999976158142 -> -0.3090170656104165 +cospi10117 cospi -1.4000000953674316 -> -0.3090167094330538 +cospi10118 cospi -1.4 -> -0.3090169943749477 +cospi10119 cospi -1.4000000000000001 -> -0.309016994374947 +cospi10120 cospi 1.5 -> 0.0 +cospi10121 cospi -1.5 -> 0.0 +cospi10122 cospi 2.5 -> 0.0 +cospi10123 cospi -2.5 -> 0.0 +cospi10124 cospi 3.5 -> 0.0 +cospi10125 cospi -3.5 -> 0.0 +cospi10126 cospi 4.5 -> 0.0 +cospi10127 cospi -4.5 -> 0.0 +cospi10128 cospi 0.24000000953674316 -> 0.728968606911995 +cospi10129 cospi 0.23999999463558197 -> 0.728968638957958 +cospi10130 cospi 0.24000000000000002 -> 0.7289686274214114 +cospi10131 cospi 0.24 -> 0.7289686274214116 +cospi10132 cospi -0.23999999463558197 -> 0.728968638957958 +cospi10133 cospi -0.24000000953674316 -> 0.728968606911995 +cospi10134 cospi -0.24 -> 0.7289686274214116 +cospi10135 cospi -0.24000000000000002 -> 0.7289686274214114 +cospi10136 cospi 0.49000000953674316 -> 0.03141072913234975 +cospi10137 cospi 0.4899999797344208 -> 0.03141082271290761 +cospi10138 cospi 0.49000000000000005 -> 0.031410759078128146 +cospi10139 cospi 0.49 -> 0.03141075907812832 +cospi10140 cospi -0.4899999797344208 -> 0.03141082271290761 +cospi10141 cospi -0.49000000953674316 -> 0.03141072913234975 +cospi10142 cospi -0.49 -> 0.03141075907812832 +cospi10143 cospi -0.49000000000000005 -> 0.031410759078128146 +cospi10144 cospi 0.5100000500679016 -> -0.031410916293465214 +cospi10145 cospi 0.5099999904632568 -> -0.03141072913234975 +cospi10146 cospi 0.51 -> -0.03141075907812832 +cospi10147 cospi 0.5099999999999999 -> -0.03141075907812797 +cospi10148 cospi -0.5099999904632568 -> -0.03141072913234975 +cospi10149 cospi -0.5100000500679016 -> -0.031410916293465214 +cospi10150 cospi -0.5099999999999999 -> -0.03141075907812797 +cospi10151 cospi -0.51 -> -0.03141075907812832 +cospi10152 cospi 0.7600000500679016 -> -0.7289687350958375 +cospi10153 cospi 0.7599999904632568 -> -0.728968606911995 +cospi10154 cospi 0.76 -> -0.7289686274214116 +cospi10155 cospi 0.7599999999999999 -> -0.7289686274214113 +cospi10156 cospi -0.7599999904632568 -> -0.728968606911995 +cospi10157 cospi -0.7600000500679016 -> -0.7289687350958375 +cospi10158 cospi -0.7599999999999999 -> -0.7289686274214113 +cospi10159 cospi -0.76 -> -0.7289686274214116 +cospi10160 cospi 1.2400000095367432 -> -0.728968606911995 +cospi10161 cospi 1.2399998903274536 -> -0.7289688632796544 +cospi10162 cospi 1.2400000000000002 -> -0.7289686274214111 +cospi10163 cospi 1.24 -> -0.7289686274214116 +cospi10164 cospi -1.2399998903274536 -> -0.7289688632796544 +cospi10165 cospi -1.2400000095367432 -> -0.728968606911995 +cospi10166 cospi -1.24 -> -0.7289686274214116 +cospi10167 cospi -1.2400000000000002 -> -0.7289686274214111 +cospi10168 cospi 1.4900000095367432 -> -0.03141072913234975 +cospi10169 cospi 1.4899998903274536 -> -0.03141110345457958 +cospi10170 cospi 1.4900000000000002 -> -0.031410759078127626 +cospi10171 cospi 1.49 -> -0.03141075907812832 +cospi10172 cospi -1.4899998903274536 -> -0.03141110345457958 +cospi10173 cospi -1.4900000095367432 -> -0.03141072913234975 +cospi10174 cospi -1.49 -> -0.03141075907812832 +cospi10175 cospi -1.4900000000000002 -> -0.031410759078127626 +cospi10176 cospi 1.5100001096725464 -> 0.03141110345457958 +cospi10177 cospi 1.5099999904632568 -> 0.03141072913234975 +cospi10178 cospi 1.51 -> 0.03141075907812832 +cospi10179 cospi 1.5099999999999998 -> 0.031410759078127626 +cospi10180 cospi -1.5099999904632568 -> 0.03141072913234975 +cospi10181 cospi -1.5100001096725464 -> 0.03141110345457958 +cospi10182 cospi -1.5099999999999998 -> 0.031410759078127626 +cospi10183 cospi -1.51 -> 0.03141075907812832 +cospi10184 cospi 1.7600001096725464 -> 0.7289688632796544 +cospi10185 cospi 1.7599999904632568 -> 0.728968606911995 +cospi10186 cospi 1.76 -> 0.7289686274214116 +cospi10187 cospi 1.7599999999999998 -> 0.7289686274214111 +cospi10188 cospi -1.7599999904632568 -> 0.728968606911995 +cospi10189 cospi -1.7600001096725464 -> 0.7289688632796544 +cospi10190 cospi -1.7599999999999998 -> 0.7289686274214111 +cospi10191 cospi -1.76 -> 0.7289686274214116 +cospi10192 cospi 100.24000549316406 -> 0.7289568138891386 +cospi10193 cospi 100.23999786376953 -> 0.7289732215142216 +cospi10194 cospi 100.24000000000001 -> 0.728968627421392 +cospi10195 cospi 100.24 -> 0.7289686274214225 +cospi10196 cospi -100.23999786376953 -> 0.7289732215142216 +cospi10197 cospi -100.24000549316406 -> 0.7289568138891386 +cospi10198 cospi -100.24 -> 0.7289686274214225 +cospi10199 cospi -100.24000000000001 -> 0.728968627421392 +cospi10200 cospi 100.49000549316406 -> 0.031393510305016 +cospi10201 cospi 100.48999786376953 -> 0.031417466931812604 +cospi10202 cospi 100.49000000000001 -> 0.03141075907809974 +cospi10203 cospi 100.49 -> 0.031410759078144355 +cospi10204 cospi -100.48999786376953 -> 0.031417466931812604 +cospi10205 cospi -100.49000549316406 -> 0.031393510305016 +cospi10206 cospi -100.49 -> 0.031410759078144355 +cospi10207 cospi -100.49000000000001 -> 0.03141075907809974 +cospi10208 cospi 100.51000213623047 -> -0.031417466931812604 +cospi10209 cospi 100.50999450683594 -> -0.031393510305016 +cospi10210 cospi 100.51 -> -0.031410759078144355 +cospi10211 cospi 100.50999999999999 -> -0.03141075907809974 +cospi10212 cospi -100.50999450683594 -> -0.031393510305016 +cospi10213 cospi -100.51000213623047 -> -0.031417466931812604 +cospi10214 cospi -100.50999999999999 -> -0.03141075907809974 +cospi10215 cospi -100.51 -> -0.031410759078144355 +cospi10216 cospi 100.76000213623047 -> -0.7289732215142216 +cospi10217 cospi 100.75999450683594 -> -0.7289568138891386 +cospi10218 cospi 100.76 -> -0.7289686274214225 +cospi10219 cospi 100.75999999999999 -> -0.728968627421392 +cospi10220 cospi -100.75999450683594 -> -0.7289568138891386 +cospi10221 cospi -100.76000213623047 -> -0.7289732215142216 +cospi10222 cospi -100.75999999999999 -> -0.728968627421392 +cospi10223 cospi -100.76 -> -0.7289686274214225 +cospi10224 cospi 1234.56005859375 -> -0.1875621285825296 +cospi10225 cospi 1234.5599365234375 -> -0.18718542559099033 +cospi10226 cospi 1234.5600000000002 -> -0.1873813145862579 +cospi10227 cospi 1234.56 -> -0.18738131458555624 +cospi10228 cospi -1234.5599365234375 -> -0.18718542559099033 +cospi10229 cospi -1234.56005859375 -> -0.1875621285825296 +cospi10230 cospi -1234.56 -> -0.18738131458555624 +cospi10231 cospi -1234.5600000000002 -> -0.1873813145862579 +cospi10232 cospi 2097151.375 -> -0.3826834323650898 +cospi10233 cospi -2097151.375 -> -0.3826834323650898 +cospi10234 cospi 2097151.625 -> 0.3826834323650898 +cospi10235 cospi -2097151.625 -> 0.3826834323650898 +cospi10236 cospi 1125899906842624.0 -> 1.0 +cospi10237 cospi 1125899839733760.0 -> 1.0 +cospi10238 cospi 1125899906842623.4 -> -0.3826834323650898 +cospi10239 cospi -1125899839733760.0 -> 1.0 +cospi10240 cospi -1125899906842624.0 -> 1.0 +cospi10241 cospi -1125899906842623.4 -> -0.3826834323650898 +cospi10242 cospi 1125899906842624.0 -> 1.0 +cospi10243 cospi 1125899839733760.0 -> 1.0 +cospi10244 cospi 1125899906842623.6 -> 0.3826834323650898 +cospi10245 cospi -1125899839733760.0 -> 1.0 +cospi10246 cospi -1125899906842624.0 -> 1.0 +cospi10247 cospi -1125899906842623.6 -> 0.3826834323650898 +cospi10248 cospi 2.305843009213694e+18 -> 1.0 +cospi10249 cospi 2.3058428717747405e+18 -> 1.0 +cospi10250 cospi 2.3058430092136937e+18 -> 1.0 +cospi10251 cospi -2.3058428717747405e+18 -> 1.0 +cospi10252 cospi -2.305843009213694e+18 -> 1.0 +cospi10253 cospi -2.3058430092136937e+18 -> 1.0 +cospi10254 cospi 2.305843009213694e+18 -> 1.0 +cospi10255 cospi 2.3058428717747405e+18 -> 1.0 +cospi10256 cospi 2.3058430092136937e+18 -> 1.0 +cospi10257 cospi -2.3058428717747405e+18 -> 1.0 +cospi10258 cospi -2.305843009213694e+18 -> 1.0 +cospi10259 cospi -2.3058430092136937e+18 -> 1.0 +cospi10260 cospi 1.298074214633707e+33 -> 1.0 +cospi10261 cospi 1.2980741372624545e+33 -> 1.0 +cospi10262 cospi 1.2980742146337068e+33 -> 1.0 +cospi10263 cospi -1.2980741372624545e+33 -> 1.0 +cospi10264 cospi -1.298074214633707e+33 -> 1.0 +cospi10265 cospi -1.2980742146337068e+33 -> 1.0 +cospi10266 cospi 1.298074214633707e+33 -> 1.0 +cospi10267 cospi 1.2980741372624545e+33 -> 1.0 +cospi10268 cospi 1.2980742146337068e+33 -> 1.0 +cospi10269 cospi -1.2980741372624545e+33 -> 1.0 +cospi10270 cospi -1.298074214633707e+33 -> 1.0 +cospi10271 cospi -1.2980742146337068e+33 -> 1.0 +cospi10272 cospi 0.419987291097641 -> 0.24872855880609973 +cospi10273 cospi -70.50994110107422 -> -0.031225813413226215 +cospi10274 cospi -70.50994873046875 -> -0.031249770165979865 +cospi10275 cospi -70.50994733870746 -> -0.03124539995406979 +cospi10276 cospi 0.4801006019115448 -> 0.06247508982524335 +cospi10277 cospi 0.4801005721092224 -> 0.06247518326910248 +cospi10278 cospi 0.48010059600345173 -> 0.062475108349807 +cospi10279 cospi 0.4801005960034517 -> 0.06247510834980717 +cospi10280 cospi -629430784.0 -> 1.0 +cospi10281 cospi -629430848.0 -> 1.0 +cospi10282 cospi -629430785.4800935 -> -0.06249742289199851 +cospi10283 cospi -629430785.4800936 -> -0.06249704911708015 + +cospi20001 cospi inf -> nan invalid +cospi20002 cospi -inf -> nan invalid +cospi20003 cospi nan -> nan + +----------- +-- sinpi -- +----------- + +sinpi10000 sinpi 0.0 -> 0.0 +sinpi10001 sinpi -0.0 -> -0.0 +sinpi10002 sinpi 1.1754943508222875e-38 -> 3.6929244168796014e-38 +sinpi10003 sinpi 2.2250738585072014e-308 -> 6.990275687580919e-308 +sinpi10004 sinpi 2.004168360008973e-292 -> 6.296280596361293e-292 +sinpi10005 sinpi -1.1754943508222875e-38 -> -3.6929244168796014e-38 +sinpi10006 sinpi -2.2250738585072014e-308 -> -6.990275687580919e-308 +sinpi10007 sinpi -2.004168360008973e-292 -> -6.296280596361293e-292 +sinpi10008 sinpi 1.401298464324817e-45 -> 4.402308961009504e-45 +sinpi10009 sinpi 5e-324 -> 1.5e-323 +sinpi10010 sinpi -1.401298464324817e-45 -> -4.402308961009504e-45 +sinpi10011 sinpi -5e-324 -> -1.5e-323 +sinpi10012 sinpi 3.4028234663852886e+38 -> 0.0 +sinpi10013 sinpi 1.7976931348623157e+308 -> 0.0 +sinpi10014 sinpi -3.4028234663852886e+38 -> -0.0 +sinpi10015 sinpi -1.7976931348623157e+308 -> -0.0 +sinpi10016 sinpi 1.0 -> 0.0 +sinpi10017 sinpi -1.0 -> -0.0 +sinpi10018 sinpi 2.0 -> 0.0 +sinpi10019 sinpi -2.0 -> -0.0 +sinpi10020 sinpi 3.0 -> 0.0 +sinpi10021 sinpi -3.0 -> -0.0 +sinpi10022 sinpi 0.10000000149011612 -> 0.30901699882716427 +sinpi10023 sinpi 0.09999999403953552 -> 0.3090169765660799 +sinpi10024 sinpi 0.1 -> 0.30901699437494745 +sinpi10025 sinpi 0.09999999999999999 -> 0.3090169943749474 +sinpi10026 sinpi -0.09999999403953552 -> -0.3090169765660799 +sinpi10027 sinpi -0.10000000149011612 -> -0.30901699882716427 +sinpi10028 sinpi -0.09999999999999999 -> -0.3090169943749474 +sinpi10029 sinpi -0.1 -> -0.30901699437494745 +sinpi10030 sinpi 0.20000000298023224 -> 0.5877852598670369 +sinpi10031 sinpi 0.19999998807907104 -> 0.5877852219942177 +sinpi10032 sinpi 0.2 -> 0.5877852522924731 +sinpi10033 sinpi 0.19999999999999998 -> 0.5877852522924731 +sinpi10034 sinpi -0.19999998807907104 -> -0.5877852219942177 +sinpi10035 sinpi -0.20000000298023224 -> -0.5877852598670369 +sinpi10036 sinpi -0.19999999999999998 -> -0.5877852522924731 +sinpi10037 sinpi -0.2 -> -0.5877852522924731 +sinpi10038 sinpi 0.30000001192092896 -> 0.8090170163879177 +sinpi10039 sinpi 0.29999998211860657 -> 0.80901696135549 +sinpi10040 sinpi 0.30000000000000004 -> 0.8090169943749475 +sinpi10041 sinpi 0.3 -> 0.8090169943749475 +sinpi10042 sinpi -0.29999998211860657 -> -0.80901696135549 +sinpi10043 sinpi -0.30000001192092896 -> -0.8090170163879177 +sinpi10044 sinpi -0.3 -> -0.8090169943749475 +sinpi10045 sinpi -0.30000000000000004 -> -0.8090169943749475 +sinpi10046 sinpi 0.4000000059604645 -> 0.9510565220816052 +sinpi10047 sinpi 0.3999999761581421 -> 0.9510564931493437 +sinpi10048 sinpi 0.4 -> 0.9510565162951536 +sinpi10049 sinpi 0.39999999999999997 -> 0.9510565162951535 +sinpi10050 sinpi -0.3999999761581421 -> -0.9510564931493437 +sinpi10051 sinpi -0.4000000059604645 -> -0.9510565220816052 +sinpi10052 sinpi -0.39999999999999997 -> -0.9510565162951535 +sinpi10053 sinpi -0.4 -> -0.9510565162951536 +sinpi10054 sinpi 0.5 -> 1.0 +sinpi10055 sinpi -0.5 -> -1.0 +sinpi10056 sinpi 0.6000000238418579 -> 0.9510564931493437 +sinpi10057 sinpi 0.5999999642372131 -> 0.9510565510138584 +sinpi10058 sinpi 0.6000000000000001 -> 0.9510565162951535 +sinpi10059 sinpi 0.6 -> 0.9510565162951536 +sinpi10060 sinpi -0.5999999642372131 -> -0.9510565510138584 +sinpi10061 sinpi -0.6000000238418579 -> -0.9510564931493437 +sinpi10062 sinpi -0.6 -> -0.9510565162951536 +sinpi10063 sinpi -0.6000000000000001 -> -0.9510565162951535 +sinpi10064 sinpi 0.7000000476837158 -> 0.8090169063230551 +sinpi10065 sinpi 0.699999988079071 -> 0.8090170163879177 +sinpi10066 sinpi 0.7000000000000001 -> 0.8090169943749473 +sinpi10067 sinpi 0.7 -> 0.8090169943749475 +sinpi10068 sinpi -0.699999988079071 -> -0.8090170163879177 +sinpi10069 sinpi -0.7000000476837158 -> -0.8090169063230551 +sinpi10070 sinpi -0.7 -> -0.8090169943749475 +sinpi10071 sinpi -0.7000000000000001 -> -0.8090169943749473 +sinpi10072 sinpi 0.800000011920929 -> 0.5877852219942177 +sinpi10073 sinpi 0.7999999523162842 -> 0.5877853734854867 +sinpi10074 sinpi 0.8 -> 0.587785252292473 +sinpi10075 sinpi 0.7999999999999999 -> 0.5877852522924732 +sinpi10076 sinpi -0.7999999523162842 -> -0.5877853734854867 +sinpi10077 sinpi -0.800000011920929 -> -0.5877852219942177 +sinpi10078 sinpi -0.7999999999999999 -> -0.5877852522924732 +sinpi10079 sinpi -0.8 -> -0.587785252292473 +sinpi10080 sinpi 0.9000000357627869 -> 0.30901688752174056 +sinpi10081 sinpi 0.8999999761581421 -> 0.3090170656104165 +sinpi10082 sinpi 0.9 -> 0.30901699437494734 +sinpi10083 sinpi 0.8999999999999999 -> 0.3090169943749477 +sinpi10084 sinpi -0.8999999761581421 -> -0.3090170656104165 +sinpi10085 sinpi -0.9000000357627869 -> -0.30901688752174056 +sinpi10086 sinpi -0.8999999999999999 -> -0.3090169943749477 +sinpi10087 sinpi -0.9 -> -0.30901699437494734 +sinpi10088 sinpi 1.100000023841858 -> -0.3090170656104165 +sinpi10089 sinpi 1.0999999046325684 -> -0.3090167094330538 +sinpi10090 sinpi 1.1 -> -0.3090169943749477 +sinpi10091 sinpi 1.0999999999999999 -> -0.309016994374947 +sinpi10092 sinpi -1.0999999046325684 -> 0.3090167094330538 +sinpi10093 sinpi -1.100000023841858 -> 0.3090170656104165 +sinpi10094 sinpi -1.0999999999999999 -> 0.309016994374947 +sinpi10095 sinpi -1.1 -> 0.3090169943749477 +sinpi10096 sinpi 1.2000000476837158 -> -0.5877853734854867 +sinpi10097 sinpi 1.1999999284744263 -> -0.587785070502928 +sinpi10098 sinpi 1.2000000000000002 -> -0.5877852522924736 +sinpi10099 sinpi 1.2 -> -0.587785252292473 +sinpi10100 sinpi -1.1999999284744263 -> 0.587785070502928 +sinpi10101 sinpi -1.2000000476837158 -> 0.5877853734854867 +sinpi10102 sinpi -1.2 -> 0.587785252292473 +sinpi10103 sinpi -1.2000000000000002 -> 0.5877852522924736 +sinpi10104 sinpi 1.3000000715255737 -> -0.8090171264527518 +sinpi10105 sinpi 1.2999999523162842 -> -0.8090169063230551 +sinpi10106 sinpi 1.3 -> -0.8090169943749475 +sinpi10107 sinpi 1.2999999999999998 -> -0.8090169943749471 +sinpi10108 sinpi -1.2999999523162842 -> 0.8090169063230551 +sinpi10109 sinpi -1.3000000715255737 -> 0.8090171264527518 +sinpi10110 sinpi -1.2999999999999998 -> 0.8090169943749471 +sinpi10111 sinpi -1.3 -> 0.8090169943749475 +sinpi10112 sinpi 1.4000000953674316 -> -0.9510566088783399 +sinpi10113 sinpi 1.399999976158142 -> -0.9510564931493437 +sinpi10114 sinpi 1.4000000000000001 -> -0.9510565162951538 +sinpi10115 sinpi 1.4 -> -0.9510565162951535 +sinpi10116 sinpi -1.399999976158142 -> 0.9510564931493437 +sinpi10117 sinpi -1.4000000953674316 -> 0.9510566088783399 +sinpi10118 sinpi -1.4 -> 0.9510565162951535 +sinpi10119 sinpi -1.4000000000000001 -> 0.9510565162951538 +sinpi10120 sinpi 1.5 -> -1.0 +sinpi10121 sinpi -1.5 -> 1.0 +sinpi10122 sinpi 2.5 -> 1.0 +sinpi10123 sinpi -2.5 -> -1.0 +sinpi10124 sinpi 3.5 -> -1.0 +sinpi10125 sinpi -3.5 -> 1.0 +sinpi10126 sinpi 4.5 -> 1.0 +sinpi10127 sinpi -4.5 -> -1.0 +sinpi10128 sinpi 0.24000000953674316 -> 0.6845471277689983 +sinpi10129 sinpi 0.23999999463558197 -> 0.6845470936435142 +sinpi10130 sinpi 0.24000000000000002 -> 0.6845471059286887 +sinpi10131 sinpi 0.24 -> 0.6845471059286886 +sinpi10132 sinpi -0.23999999463558197 -> -0.6845470936435142 +sinpi10133 sinpi -0.24000000953674316 -> -0.6845471277689983 +sinpi10134 sinpi -0.24 -> -0.6845471059286886 +sinpi10135 sinpi -0.24000000000000002 -> -0.6845471059286887 +sinpi10136 sinpi 0.49000000953674316 -> 0.9995065613068151 +sinpi10137 sinpi 0.4899999797344208 -> 0.9995065583659261 +sinpi10138 sinpi 0.49000000000000005 -> 0.9995065603657316 +sinpi10139 sinpi 0.49 -> 0.9995065603657316 +sinpi10140 sinpi -0.4899999797344208 -> -0.9995065583659261 +sinpi10141 sinpi -0.49000000953674316 -> -0.9995065613068151 +sinpi10142 sinpi -0.49 -> -0.9995065603657316 +sinpi10143 sinpi -0.49000000000000005 -> -0.9995065603657316 +sinpi10144 sinpi 0.5100000500679016 -> 0.9995065554250282 +sinpi10145 sinpi 0.5099999904632568 -> 0.9995065613068151 +sinpi10146 sinpi 0.51 -> 0.9995065603657316 +sinpi10147 sinpi 0.5099999999999999 -> 0.9995065603657316 +sinpi10148 sinpi -0.5099999904632568 -> -0.9995065613068151 +sinpi10149 sinpi -0.5100000500679016 -> -0.9995065554250282 +sinpi10150 sinpi -0.5099999999999999 -> -0.9995065603657316 +sinpi10151 sinpi -0.51 -> -0.9995065603657316 +sinpi10152 sinpi 0.7600000500679016 -> 0.684546991267053 +sinpi10153 sinpi 0.7599999904632568 -> 0.6845471277689983 +sinpi10154 sinpi 0.76 -> 0.6845471059286886 +sinpi10155 sinpi 0.7599999999999999 -> 0.684547105928689 +sinpi10156 sinpi -0.7599999904632568 -> -0.6845471277689983 +sinpi10157 sinpi -0.7600000500679016 -> -0.684546991267053 +sinpi10158 sinpi -0.7599999999999999 -> -0.684547105928689 +sinpi10159 sinpi -0.76 -> -0.6845471059286886 +sinpi10160 sinpi 1.2400000095367432 -> -0.6845471277689983 +sinpi10161 sinpi 1.2399998903274536 -> -0.6845468547650836 +sinpi10162 sinpi 1.2400000000000002 -> -0.6845471059286892 +sinpi10163 sinpi 1.24 -> -0.6845471059286886 +sinpi10164 sinpi -1.2399998903274536 -> 0.6845468547650836 +sinpi10165 sinpi -1.2400000095367432 -> 0.6845471277689983 +sinpi10166 sinpi -1.24 -> 0.6845471059286886 +sinpi10167 sinpi -1.2400000000000002 -> 0.6845471059286892 +sinpi10168 sinpi 1.4900000095367432 -> -0.9995065613068151 +sinpi10169 sinpi 1.4899998903274536 -> -0.9995065495432062 +sinpi10170 sinpi 1.4900000000000002 -> -0.9995065603657316 +sinpi10171 sinpi 1.49 -> -0.9995065603657316 +sinpi10172 sinpi -1.4899998903274536 -> 0.9995065495432062 +sinpi10173 sinpi -1.4900000095367432 -> 0.9995065613068151 +sinpi10174 sinpi -1.49 -> 0.9995065603657316 +sinpi10175 sinpi -1.4900000000000002 -> 0.9995065603657316 +sinpi10176 sinpi 1.5100001096725464 -> -0.9995065495432062 +sinpi10177 sinpi 1.5099999904632568 -> -0.9995065613068151 +sinpi10178 sinpi 1.51 -> -0.9995065603657316 +sinpi10179 sinpi 1.5099999999999998 -> -0.9995065603657316 +sinpi10180 sinpi -1.5099999904632568 -> 0.9995065613068151 +sinpi10181 sinpi -1.5100001096725464 -> 0.9995065495432062 +sinpi10182 sinpi -1.5099999999999998 -> 0.9995065603657316 +sinpi10183 sinpi -1.51 -> 0.9995065603657316 +sinpi10184 sinpi 1.7600001096725464 -> -0.6845468547650836 +sinpi10185 sinpi 1.7599999904632568 -> -0.6845471277689983 +sinpi10186 sinpi 1.76 -> -0.6845471059286886 +sinpi10187 sinpi 1.7599999999999998 -> -0.6845471059286892 +sinpi10188 sinpi -1.7599999904632568 -> 0.6845471277689983 +sinpi10189 sinpi -1.7600001096725464 -> 0.6845468547650836 +sinpi10190 sinpi -1.7599999999999998 -> 0.6845471059286892 +sinpi10191 sinpi -1.76 -> 0.6845471059286886 +sinpi10192 sinpi 100.24000549316406 -> 0.6845596858452854 +sinpi10193 sinpi 100.23999786376953 -> 0.684542213683844 +sinpi10194 sinpi 100.24000000000001 -> 0.6845471059287095 +sinpi10195 sinpi 100.24 -> 0.684547105928677 +sinpi10196 sinpi -100.23999786376953 -> -0.684542213683844 +sinpi10197 sinpi -100.24000549316406 -> -0.6845596858452854 +sinpi10198 sinpi -100.24 -> -0.684547105928677 +sinpi10199 sinpi -100.24000000000001 -> -0.6845471059287095 +sinpi10200 sinpi 100.49000549316406 -> 0.9995071022812839 +sinpi10201 sinpi 100.48999786376953 -> 0.9995063495404061 +sinpi10202 sinpi 100.49000000000001 -> 0.9995065603657325 +sinpi10203 sinpi 100.49 -> 0.999506560365731 +sinpi10204 sinpi -100.48999786376953 -> -0.9995063495404061 +sinpi10205 sinpi -100.49000549316406 -> -0.9995071022812839 +sinpi10206 sinpi -100.49 -> -0.999506560365731 +sinpi10207 sinpi -100.49000000000001 -> -0.9995065603657325 +sinpi10208 sinpi 100.51000213623047 -> 0.9995063495404061 +sinpi10209 sinpi 100.50999450683594 -> 0.9995071022812839 +sinpi10210 sinpi 100.51 -> 0.999506560365731 +sinpi10211 sinpi 100.50999999999999 -> 0.9995065603657325 +sinpi10212 sinpi -100.50999450683594 -> -0.9995071022812839 +sinpi10213 sinpi -100.51000213623047 -> -0.9995063495404061 +sinpi10214 sinpi -100.50999999999999 -> -0.9995065603657325 +sinpi10215 sinpi -100.51 -> -0.999506560365731 +sinpi10216 sinpi 100.76000213623047 -> 0.684542213683844 +sinpi10217 sinpi 100.75999450683594 -> 0.6845596858452854 +sinpi10218 sinpi 100.76 -> 0.684547105928677 +sinpi10219 sinpi 100.75999999999999 -> 0.6845471059287095 +sinpi10220 sinpi -100.75999450683594 -> -0.6845596858452854 +sinpi10221 sinpi -100.76000213623047 -> -0.684542213683844 +sinpi10222 sinpi -100.75999999999999 -> -0.6845471059287095 +sinpi10223 sinpi -100.76 -> -0.684547105928677 +sinpi10224 sinpi 1234.56005859375 -> 0.9822527413662894 +sinpi10225 sinpi 1234.5599365234375 -> 0.9823245983107213 +sinpi10226 sinpi 1234.5600000000002 -> 0.9822872507285869 +sinpi10227 sinpi 1234.56 -> 0.9822872507287208 +sinpi10228 sinpi -1234.5599365234375 -> -0.9823245983107213 +sinpi10229 sinpi -1234.56005859375 -> -0.9822527413662894 +sinpi10230 sinpi -1234.56 -> -0.9822872507287208 +sinpi10231 sinpi -1234.5600000000002 -> -0.9822872507285869 +sinpi10232 sinpi 2097151.125 -> -0.3826834323650898 +sinpi10233 sinpi -2097151.125 -> 0.3826834323650898 +sinpi10234 sinpi 2097151.875 -> -0.3826834323650898 +sinpi10235 sinpi -2097151.875 -> 0.3826834323650898 +sinpi10236 sinpi 1125899906842624.0 -> 0.0 +sinpi10237 sinpi 1125899839733760.0 -> 0.0 +sinpi10238 sinpi 1125899906842623.1 -> -0.3826834323650898 +sinpi10239 sinpi -1125899839733760.0 -> -0.0 +sinpi10240 sinpi -1125899906842624.0 -> -0.0 +sinpi10241 sinpi -1125899906842623.1 -> 0.3826834323650898 +sinpi10242 sinpi 1125899906842624.0 -> 0.0 +sinpi10243 sinpi 1125899839733760.0 -> 0.0 +sinpi10244 sinpi 1125899906842623.9 -> -0.3826834323650898 +sinpi10245 sinpi -1125899839733760.0 -> -0.0 +sinpi10246 sinpi -1125899906842624.0 -> -0.0 +sinpi10247 sinpi -1125899906842623.9 -> 0.3826834323650898 +sinpi10248 sinpi 2.305843009213694e+18 -> 0.0 +sinpi10249 sinpi 2.3058428717747405e+18 -> 0.0 +sinpi10250 sinpi 2.3058430092136937e+18 -> 0.0 +sinpi10251 sinpi -2.3058428717747405e+18 -> -0.0 +sinpi10252 sinpi -2.305843009213694e+18 -> -0.0 +sinpi10253 sinpi -2.3058430092136937e+18 -> -0.0 +sinpi10254 sinpi 2.305843009213694e+18 -> 0.0 +sinpi10255 sinpi 2.3058428717747405e+18 -> 0.0 +sinpi10256 sinpi 2.3058430092136937e+18 -> 0.0 +sinpi10257 sinpi -2.3058428717747405e+18 -> -0.0 +sinpi10258 sinpi -2.305843009213694e+18 -> -0.0 +sinpi10259 sinpi -2.3058430092136937e+18 -> -0.0 +sinpi10260 sinpi 1.298074214633707e+33 -> 0.0 +sinpi10261 sinpi 1.2980741372624545e+33 -> 0.0 +sinpi10262 sinpi 1.2980742146337068e+33 -> 0.0 +sinpi10263 sinpi -1.2980741372624545e+33 -> -0.0 +sinpi10264 sinpi -1.298074214633707e+33 -> -0.0 +sinpi10265 sinpi -1.2980742146337068e+33 -> -0.0 +sinpi10266 sinpi 1.298074214633707e+33 -> 0.0 +sinpi10267 sinpi 1.2980741372624545e+33 -> 0.0 +sinpi10268 sinpi 1.2980742146337068e+33 -> 0.0 +sinpi10269 sinpi -1.2980741372624545e+33 -> -0.0 +sinpi10270 sinpi -1.298074214633707e+33 -> -0.0 +sinpi10271 sinpi -1.2980742146337068e+33 -> -0.0 +sinpi10272 sinpi 2.938735877055719e-39 -> 9.232311042199004e-39 +sinpi10273 sinpi -2.938735877055719e-39 -> -9.232311042199004e-39 +sinpi10274 sinpi 1.401298464324817e-45 -> 4.402308961009504e-45 +sinpi10275 sinpi 0.0 -> 0.0 +sinpi10276 sinpi 5.010420900022432e-293 -> 1.5740701490903231e-292 +sinpi10277 sinpi -0.0 -> -0.0 +sinpi10278 sinpi -1.401298464324817e-45 -> -4.402308961009504e-45 +sinpi10279 sinpi -5.010420900022432e-293 -> -1.5740701490903231e-292 +sinpi10280 sinpi 1.401298464324817e-45 -> 4.402308961009504e-45 +sinpi10281 sinpi 0.0 -> 0.0 +sinpi10282 sinpi 5.562684646268003e-309 -> 1.7475689218952297e-308 +sinpi10283 sinpi -0.0 -> -0.0 +sinpi10284 sinpi -1.401298464324817e-45 -> -4.402308961009504e-45 +sinpi10285 sinpi -5.562684646268003e-309 -> -1.7475689218952297e-308 +sinpi10286 sinpi 1.401298464324817e-45 -> 4.402308961009504e-45 +sinpi10287 sinpi 0.0 -> 0.0 +sinpi10288 sinpi 5e-324 -> 1.5e-323 +sinpi10289 sinpi -0.0 -> -0.0 +sinpi10290 sinpi -1.401298464324817e-45 -> -4.402308961009504e-45 +sinpi10291 sinpi -5e-324 -> -1.5e-323 +sinpi10292 sinpi 1.401298464324817e-45 -> 4.402308961009504e-45 +sinpi10293 sinpi 0.0 -> 0.0 +sinpi10294 sinpi 5e-324 -> 1.5e-323 +sinpi10295 sinpi -0.0 -> -0.0 +sinpi10296 sinpi -1.401298464324817e-45 -> -4.402308961009504e-45 +sinpi10297 sinpi -5e-324 -> -1.5e-323 +sinpi10298 sinpi 0.039865780621767044 -> 0.12491488475763585 +sinpi10299 sinpi -0.009947286918759346 -> -0.03124523733449905 +sinpi10300 sinpi -0.00994728785008192 -> -0.03124524025890666 +sinpi10301 sinpi -0.009947287497407154 -> -0.03124523915148717 +sinpi10302 sinpi 0.009947438724339008 -> 0.03124571401293662 +sinpi10303 sinpi 0.009947437793016434 -> 0.03124571108852905 +sinpi10304 sinpi 0.009947437917099084 -> 0.03124571147815586 +sinpi10305 sinpi 0.009947437917099082 -> 0.031245711478155854 +sinpi10306 sinpi -0.0049737198278307915 -> -0.015624765847977973 +sinpi10307 sinpi -0.004973720293492079 -> -0.015624767310717469 +sinpi10308 sinpi -0.004973719955059152 -> -0.015624766247628864 +sinpi10309 sinpi -0.004973719955059153 -> -0.015624766247628865 + +sinpi20001 sinpi inf -> nan invalid +sinpi20002 sinpi -inf -> nan invalid +sinpi20003 sinpi nan -> nan + +----------- +-- tanpi -- +----------- + +tanpi10000 tanpi 0.0 -> 0.0 +tanpi10001 tanpi -0.0 -> -0.0 +tanpi10002 tanpi 1.1754943508222875e-38 -> 3.6929244168796014e-38 +tanpi10003 tanpi 2.2250738585072014e-308 -> 6.990275687580919e-308 +tanpi10004 tanpi 2.004168360008973e-292 -> 6.296280596361293e-292 +tanpi10005 tanpi -1.1754943508222875e-38 -> -3.6929244168796014e-38 +tanpi10006 tanpi -2.2250738585072014e-308 -> -6.990275687580919e-308 +tanpi10007 tanpi -2.004168360008973e-292 -> -6.296280596361293e-292 +tanpi10008 tanpi 1.401298464324817e-45 -> 4.402308961009504e-45 +tanpi10009 tanpi 5e-324 -> 1.5e-323 +tanpi10010 tanpi -1.401298464324817e-45 -> -4.402308961009504e-45 +tanpi10011 tanpi -5e-324 -> -1.5e-323 +tanpi10012 tanpi 3.4028234663852886e+38 -> 0.0 +tanpi10013 tanpi 1.7976931348623157e+308 -> 0.0 +tanpi10014 tanpi -3.4028234663852886e+38 -> -0.0 +tanpi10015 tanpi -1.7976931348623157e+308 -> -0.0 +tanpi10016 tanpi 1.0 -> -0.0 +tanpi10017 tanpi -1.0 -> 0.0 +tanpi10018 tanpi 2.0 -> 0.0 +tanpi10019 tanpi -2.0 -> -0.0 +tanpi10020 tanpi 3.0 -> -0.0 +tanpi10021 tanpi -3.0 -> 0.0 +tanpi10022 tanpi 4.0 -> 0.0 +tanpi10023 tanpi -4.0 -> -0.0 +tanpi10024 tanpi 0.10000000149011612 -> 0.32491970140846616 +tanpi10025 tanpi 0.09999999403953552 -> 0.3249196755306671 +tanpi10026 tanpi 0.1 -> 0.32491969623290634 +tanpi10027 tanpi 0.09999999999999999 -> 0.3249196962329063 +tanpi10028 tanpi -0.09999999403953552 -> -0.3249196755306671 +tanpi10029 tanpi -0.10000000149011612 -> -0.32491970140846616 +tanpi10030 tanpi -0.09999999999999999 -> -0.3249196962329063 +tanpi10031 tanpi -0.1 -> -0.32491969623290634 +tanpi10032 tanpi 0.20000000298023224 -> 0.7265425423102566 +tanpi10033 tanpi 0.19999998807907104 -> 0.7265424707857802 +tanpi10034 tanpi 0.2 -> 0.7265425280053609 +tanpi10035 tanpi 0.19999999999999998 -> 0.7265425280053608 +tanpi10036 tanpi -0.19999998807907104 -> -0.7265424707857802 +tanpi10037 tanpi -0.20000000298023224 -> -0.7265425423102566 +tanpi10038 tanpi -0.19999999999999998 -> -0.7265425280053608 +tanpi10039 tanpi -0.2 -> -0.7265425280053609 +tanpi10040 tanpi 0.30000001192092896 -> 1.3763820288695117 +tanpi10041 tanpi 0.29999998211860657 -> 1.3763817578736872 +tanpi10042 tanpi 0.30000000000000004 -> 1.376381920471174 +tanpi10043 tanpi 0.3 -> 1.3763819204711734 +tanpi10044 tanpi -0.29999998211860657 -> -1.3763817578736872 +tanpi10045 tanpi -0.30000001192092896 -> -1.3763820288695117 +tanpi10046 tanpi -0.3 -> -1.3763819204711734 +tanpi10047 tanpi -0.30000000000000004 -> -1.376381920471174 +tanpi10048 tanpi 0.4000000059604645 -> 3.0776837332696907 +tanpi10049 tanpi 0.3999999761581421 -> 3.077682752797731 +tanpi10050 tanpi 0.4 -> 3.077683537175254 +tanpi10051 tanpi 0.39999999999999997 -> 3.0776835371752522 +tanpi10052 tanpi -0.3999999761581421 -> -3.077682752797731 +tanpi10053 tanpi -0.4000000059604645 -> -3.0776837332696907 +tanpi10054 tanpi -0.39999999999999997 -> -3.0776835371752522 +tanpi10055 tanpi -0.4 -> -3.077683537175254 +tanpi10056 tanpi 0.6000000238418579 -> -3.077682752797731 +tanpi10057 tanpi 0.5999999642372131 -> -3.077684713742215 +tanpi10058 tanpi 0.6000000000000001 -> -3.0776835371752504 +tanpi10059 tanpi 0.6 -> -3.077683537175254 +tanpi10060 tanpi -0.5999999642372131 -> 3.077684713742215 +tanpi10061 tanpi -0.6000000238418579 -> 3.077682752797731 +tanpi10062 tanpi -0.6 -> 3.077683537175254 +tanpi10063 tanpi -0.6000000000000001 -> 3.0776835371752504 +tanpi10064 tanpi 0.7000000476837158 -> -1.3763814868779325 +tanpi10065 tanpi 0.699999988079071 -> -1.3763820288695117 +tanpi10066 tanpi 0.7000000000000001 -> -1.376381920471173 +tanpi10067 tanpi 0.7 -> -1.376381920471174 +tanpi10068 tanpi -0.699999988079071 -> 1.3763820288695117 +tanpi10069 tanpi -0.7000000476837158 -> 1.3763814868779325 +tanpi10070 tanpi -0.7 -> 1.376381920471174 +tanpi10071 tanpi -0.7000000000000001 -> 1.376381920471173 +tanpi10072 tanpi 0.800000011920929 -> -0.7265424707857802 +tanpi10073 tanpi 0.7999999523162842 -> -0.7265427568837151 +tanpi10074 tanpi 0.8 -> -0.7265425280053607 +tanpi10075 tanpi 0.7999999999999999 -> -0.7265425280053612 +tanpi10076 tanpi -0.7999999523162842 -> 0.7265427568837151 +tanpi10077 tanpi -0.800000011920929 -> 0.7265424707857802 +tanpi10078 tanpi -0.7999999999999999 -> 0.7265425280053612 +tanpi10079 tanpi -0.8 -> 0.7265425280053607 +tanpi10080 tanpi 0.9000000357627869 -> -0.3249195720194747 +tanpi10081 tanpi 0.8999999761581421 -> -0.3249197790418658 +tanpi10082 tanpi 0.9 -> -0.32491969623290623 +tanpi10083 tanpi 0.8999999999999999 -> -0.3249196962329066 +tanpi10084 tanpi -0.8999999761581421 -> 0.3249197790418658 +tanpi10085 tanpi -0.9000000357627869 -> 0.3249195720194747 +tanpi10086 tanpi -0.8999999999999999 -> 0.3249196962329066 +tanpi10087 tanpi -0.9 -> 0.32491969623290623 +tanpi10088 tanpi 1.100000023841858 -> 0.3249197790418658 +tanpi10089 tanpi 1.0999999046325684 -> 0.3249193649971088 +tanpi10090 tanpi 1.1 -> 0.3249196962329066 +tanpi10091 tanpi 1.0999999999999999 -> 0.32491969623290584 +tanpi10092 tanpi -1.0999999046325684 -> -0.3249193649971088 +tanpi10093 tanpi -1.100000023841858 -> -0.3249197790418658 +tanpi10094 tanpi -1.0999999999999999 -> -0.32491969623290584 +tanpi10095 tanpi -1.1 -> -0.3249196962329066 +tanpi10096 tanpi 1.2000000476837158 -> 0.7265427568837151 +tanpi10097 tanpi 1.1999999284744263 -> 0.7265421846879231 +tanpi10098 tanpi 1.2000000000000002 -> 0.7265425280053618 +tanpi10099 tanpi 1.2 -> 0.7265425280053607 +tanpi10100 tanpi -1.1999999284744263 -> -0.7265421846879231 +tanpi10101 tanpi -1.2000000476837158 -> -0.7265427568837151 +tanpi10102 tanpi -1.2 -> -0.7265425280053607 +tanpi10103 tanpi -1.2000000000000002 -> -0.7265425280053618 +tanpi10104 tanpi 1.3000000715255737 -> 1.3763825708613702 +tanpi10105 tanpi 1.2999999523162842 -> 1.3763814868779325 +tanpi10106 tanpi 1.3 -> 1.376381920471174 +tanpi10107 tanpi 1.2999999999999998 -> 1.376381920471172 +tanpi10108 tanpi -1.2999999523162842 -> -1.3763814868779325 +tanpi10109 tanpi -1.3000000715255737 -> -1.3763825708613702 +tanpi10110 tanpi -1.2999999999999998 -> -1.376381920471172 +tanpi10111 tanpi -1.3 -> -1.376381920471174 +tanpi10112 tanpi 1.4000000953674316 -> 3.0776866746889597 +tanpi10113 tanpi 1.399999976158142 -> 3.077682752797731 +tanpi10114 tanpi 1.4000000000000001 -> 3.077683537175258 +tanpi10115 tanpi 1.4 -> 3.0776835371752504 +tanpi10116 tanpi -1.399999976158142 -> -3.077682752797731 +tanpi10117 tanpi -1.4000000953674316 -> -3.0776866746889597 +tanpi10118 tanpi -1.4 -> -3.0776835371752504 +tanpi10119 tanpi -1.4000000000000001 -> -3.077683537175258 +tanpi10120 tanpi 0.24000000953674316 -> 0.9390625621984302 +tanpi10121 tanpi 0.23999999463558197 -> 0.9390624741032162 +tanpi10122 tanpi 0.24000000000000002 -> 0.9390625058174925 +tanpi10123 tanpi 0.24 -> 0.9390625058174923 +tanpi10124 tanpi -0.23999999463558197 -> -0.9390624741032162 +tanpi10125 tanpi -0.24000000953674316 -> -0.9390625621984302 +tanpi10126 tanpi -0.24 -> -0.9390625058174923 +tanpi10127 tanpi -0.24000000000000002 -> -0.9390625058174925 +tanpi10128 tanpi 0.49000000953674316 -> 31.820546320188043 +tanpi10129 tanpi 0.4899999797344208 -> 31.82045142533627 +tanpi10130 tanpi 0.49000000000000005 -> 31.820515953774105 +tanpi10131 tanpi 0.49 -> 31.82051595377393 +tanpi10132 tanpi -0.4899999797344208 -> -31.82045142533627 +tanpi10133 tanpi -0.49000000953674316 -> -31.820546320188043 +tanpi10134 tanpi -0.49 -> -31.82051595377393 +tanpi10135 tanpi -0.49000000000000005 -> -31.820515953774105 +tanpi10136 tanpi 0.5100000500679016 -> -31.820356531049924 +tanpi10137 tanpi 0.5099999904632568 -> -31.820546320188043 +tanpi10138 tanpi 0.51 -> -31.82051595377393 +tanpi10139 tanpi 0.5099999999999999 -> -31.820515953774283 +tanpi10140 tanpi -0.5099999904632568 -> 31.820546320188043 +tanpi10141 tanpi -0.5100000500679016 -> 31.820356531049924 +tanpi10142 tanpi -0.5099999999999999 -> 31.820515953774283 +tanpi10143 tanpi -0.51 -> 31.82051595377393 +tanpi10144 tanpi 0.7600000500679016 -> -0.9390622098176208 +tanpi10145 tanpi 0.7599999904632568 -> -0.9390625621984302 +tanpi10146 tanpi 0.76 -> -0.9390625058174923 +tanpi10147 tanpi 0.7599999999999999 -> -0.939062505817493 +tanpi10148 tanpi -0.7599999904632568 -> 0.9390625621984302 +tanpi10149 tanpi -0.7600000500679016 -> 0.9390622098176208 +tanpi10150 tanpi -0.7599999999999999 -> 0.939062505817493 +tanpi10151 tanpi -0.76 -> 0.9390625058174923 +tanpi10152 tanpi 1.2400000095367432 -> 0.9390625621984302 +tanpi10153 tanpi 1.2399998903274536 -> 0.9390618574369353 +tanpi10154 tanpi 1.2400000000000002 -> 0.9390625058174936 +tanpi10155 tanpi 1.24 -> 0.9390625058174923 +tanpi10156 tanpi -1.2399998903274536 -> -0.9390618574369353 +tanpi10157 tanpi -1.2400000095367432 -> -0.9390625621984302 +tanpi10158 tanpi -1.24 -> -0.9390625058174923 +tanpi10159 tanpi -1.2400000000000002 -> -0.9390625058174936 +tanpi10160 tanpi 1.4900000095367432 -> 31.820546320188043 +tanpi10161 tanpi 1.4899998903274536 -> 31.820166744173495 +tanpi10162 tanpi 1.4900000000000002 -> 31.82051595377464 +tanpi10163 tanpi 1.49 -> 31.82051595377393 +tanpi10164 tanpi -1.4899998903274536 -> -31.820166744173495 +tanpi10165 tanpi -1.4900000095367432 -> -31.820546320188043 +tanpi10166 tanpi -1.49 -> -31.82051595377393 +tanpi10167 tanpi -1.4900000000000002 -> -31.82051595377464 +tanpi10168 tanpi 1.5100001096725464 -> -31.820166744173495 +tanpi10169 tanpi 1.5099999904632568 -> -31.820546320188043 +tanpi10170 tanpi 1.51 -> -31.82051595377393 +tanpi10171 tanpi 1.5099999999999998 -> -31.82051595377464 +tanpi10172 tanpi -1.5099999904632568 -> 31.820546320188043 +tanpi10173 tanpi -1.5100001096725464 -> 31.820166744173495 +tanpi10174 tanpi -1.5099999999999998 -> 31.82051595377464 +tanpi10175 tanpi -1.51 -> 31.82051595377393 +tanpi10176 tanpi 1.7600001096725464 -> -0.9390618574369353 +tanpi10177 tanpi 1.7599999904632568 -> -0.9390625621984302 +tanpi10178 tanpi 1.76 -> -0.9390625058174923 +tanpi10179 tanpi 1.7599999999999998 -> -0.9390625058174936 +tanpi10180 tanpi -1.7599999904632568 -> 0.9390625621984302 +tanpi10181 tanpi -1.7600001096725464 -> 0.9390618574369353 +tanpi10182 tanpi -1.7599999999999998 -> 0.9390625058174936 +tanpi10183 tanpi -1.76 -> 0.9390625058174923 +tanpi10184 tanpi 100.24000549316406 -> 0.9390949817630689 +tanpi10185 tanpi 100.23999786376953 -> 0.9390498765673647 +tanpi10186 tanpi 100.24000000000001 -> 0.9390625058175461 +tanpi10187 tanpi 100.24 -> 0.9390625058174621 +tanpi10188 tanpi -100.23999786376953 -> -0.9390498765673647 +tanpi10189 tanpi -100.24000549316406 -> -0.9390949817630689 +tanpi10190 tanpi -100.24 -> -0.9390625058174621 +tanpi10191 tanpi -100.24000000000001 -> -0.9390625058175461 +tanpi10192 tanpi 100.49000549316406 -> 31.83801660184476 +tanpi10193 tanpi 100.48999786376953 -> 31.81371533579395 +tanpi10194 tanpi 100.49000000000001 -> 31.820515953802918 +tanpi10195 tanpi 100.49 -> 31.820515953757667 +tanpi10196 tanpi -100.48999786376953 -> -31.81371533579395 +tanpi10197 tanpi -100.49000549316406 -> -31.83801660184476 +tanpi10198 tanpi -100.49 -> -31.820515953757667 +tanpi10199 tanpi -100.49000000000001 -> -31.820515953802918 +tanpi10200 tanpi 100.51000213623047 -> -31.81371533579395 +tanpi10201 tanpi 100.50999450683594 -> -31.83801660184476 +tanpi10202 tanpi 100.51 -> -31.820515953757667 +tanpi10203 tanpi 100.50999999999999 -> -31.820515953802918 +tanpi10204 tanpi -100.50999450683594 -> 31.83801660184476 +tanpi10205 tanpi -100.51000213623047 -> 31.81371533579395 +tanpi10206 tanpi -100.50999999999999 -> 31.820515953802918 +tanpi10207 tanpi -100.51 -> 31.820515953757667 +tanpi10208 tanpi 100.76000213623047 -> -0.9390498765673647 +tanpi10209 tanpi 100.75999450683594 -> -0.9390949817630689 +tanpi10210 tanpi 100.76 -> -0.9390625058174621 +tanpi10211 tanpi 100.75999999999999 -> -0.9390625058175461 +tanpi10212 tanpi -100.75999450683594 -> 0.9390949817630689 +tanpi10213 tanpi -100.76000213623047 -> 0.9390498765673647 +tanpi10214 tanpi -100.75999999999999 -> 0.9390625058175461 +tanpi10215 tanpi -100.76 -> 0.9390625058174621 +tanpi10216 tanpi 1234.56005859375 -> -5.236946012446678 +tanpi10217 tanpi 1234.5599365234375 -> -5.247869032587774 +tanpi10218 tanpi 1234.5600000000002 -> -5.2421835810977155 +tanpi10219 tanpi 1234.56 -> -5.242183581118059 +tanpi10220 tanpi -1234.5599365234375 -> 5.247869032587774 +tanpi10221 tanpi -1234.56005859375 -> 5.236946012446678 +tanpi10222 tanpi -1234.56 -> 5.242183581118059 +tanpi10223 tanpi -1234.5600000000002 -> 5.2421835810977155 +tanpi10224 tanpi 2097151.375 -> 2.414213562373095 +tanpi10225 tanpi -2097151.375 -> -2.414213562373095 +tanpi10226 tanpi 2097151.625 -> -2.414213562373095 +tanpi10227 tanpi -2097151.625 -> 2.414213562373095 +tanpi10228 tanpi 1125899906842624.0 -> 0.0 +tanpi10229 tanpi 1125899839733760.0 -> 0.0 +tanpi10230 tanpi 1125899906842623.4 -> 2.414213562373095 +tanpi10231 tanpi -1125899839733760.0 -> -0.0 +tanpi10232 tanpi -1125899906842624.0 -> -0.0 +tanpi10233 tanpi -1125899906842623.4 -> -2.414213562373095 +tanpi10234 tanpi 1125899906842624.0 -> 0.0 +tanpi10235 tanpi 1125899839733760.0 -> 0.0 +tanpi10236 tanpi 1125899906842623.6 -> -2.414213562373095 +tanpi10237 tanpi -1125899839733760.0 -> -0.0 +tanpi10238 tanpi -1125899906842624.0 -> -0.0 +tanpi10239 tanpi -1125899906842623.6 -> 2.414213562373095 +tanpi10240 tanpi 2.305843009213694e+18 -> 0.0 +tanpi10241 tanpi 2.3058428717747405e+18 -> 0.0 +tanpi10242 tanpi 2.3058430092136937e+18 -> 0.0 +tanpi10243 tanpi -2.3058428717747405e+18 -> -0.0 +tanpi10244 tanpi -2.305843009213694e+18 -> -0.0 +tanpi10245 tanpi -2.3058430092136937e+18 -> -0.0 +tanpi10246 tanpi 2.305843009213694e+18 -> 0.0 +tanpi10247 tanpi 2.3058428717747405e+18 -> 0.0 +tanpi10248 tanpi 2.3058430092136937e+18 -> 0.0 +tanpi10249 tanpi -2.3058428717747405e+18 -> -0.0 +tanpi10250 tanpi -2.305843009213694e+18 -> -0.0 +tanpi10251 tanpi -2.3058430092136937e+18 -> -0.0 +tanpi10252 tanpi 1.298074214633707e+33 -> 0.0 +tanpi10253 tanpi 1.2980741372624545e+33 -> 0.0 +tanpi10254 tanpi 1.2980742146337068e+33 -> 0.0 +tanpi10255 tanpi -1.2980741372624545e+33 -> -0.0 +tanpi10256 tanpi -1.298074214633707e+33 -> -0.0 +tanpi10257 tanpi -1.2980742146337068e+33 -> -0.0 +tanpi10258 tanpi 1.298074214633707e+33 -> 0.0 +tanpi10259 tanpi 1.2980741372624545e+33 -> 0.0 +tanpi10260 tanpi 1.2980742146337068e+33 -> 0.0 +tanpi10261 tanpi -1.2980741372624545e+33 -> -0.0 +tanpi10262 tanpi -1.298074214633707e+33 -> -0.0 +tanpi10263 tanpi -1.2980742146337068e+33 -> -0.0 +tanpi10264 tanpi 0.48004481196403503 -> 15.930332115434627 +tanpi10265 tanpi -0.4950249195098877 -> -63.97564155226383 +tanpi10266 tanpi -0.4950249493122101 -> -63.97602485152189 +tanpi10267 tanpi -0.49502493342943843 -> -63.97582057644752 +tanpi10268 tanpi -3.659269094467163 -> 1.828928514937406 +tanpi10269 tanpi -3.659269332885742 -> 1.8289252604911337 +tanpi10270 tanpi -3.659269111498701 -> 1.8289282824542836 +tanpi10271 tanpi -3.6592691114987015 -> 1.8289282824542774 +tanpi10272 tanpi -1.6591962575912476 -> 1.829923165916756 +tanpi10273 tanpi -1.659196376800537 -> 1.8299215373295707 +tanpi10274 tanpi -1.6591963470121214 -> 1.8299219442861712 +tanpi10275 tanpi -1.6591963470121216 -> 1.829921944286168 + +tanpi20001 tanpi inf -> nan invalid +tanpi20002 tanpi -inf -> nan invalid +tanpi20003 tanpi nan -> nan diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index cd85ef60a80f4bf..e9966e1f7a6d495 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -3159,7 +3159,7 @@ def in_systemd_nspawn_sync_suppressed() -> bool: with open("/run/systemd/container", "rb") as fp: if fp.read().rstrip() != b"systemd-nspawn": return False - except FileNotFoundError: + except (FileNotFoundError, PermissionError): return False # If systemd-nspawn is used, O_SYNC flag will immediately diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 0112c9163fd0cdb..fd3b33bab7f8336 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -625,7 +625,7 @@ def test_invalid_identifier(self): ast.fix_missing_locations(m) with self.assertRaises(TypeError) as cm: compile(m, "", "exec") - self.assertIn("identifier must be of type str", str(cm.exception)) + self.assertIn("expecting a string object", str(cm.exception)) def test_invalid_constant(self): for invalid_constant in int, (1, 2, int), frozenset((1, 2, int)): @@ -1081,6 +1081,30 @@ def test_none_checks(self) -> None: for node, attr, source in tests: self.assert_none_check(node, attr, source) + def test_required_field_messages(self): + binop = ast.BinOp( + left=ast.Constant(value=2), + right=ast.Constant(value=2), + op=ast.Add(), + ) + expr_without_position = ast.Expression(body=binop) + expr_with_wrong_body = ast.Expression(body=[binop]) + + with self.assertRaisesRegex(TypeError, "required field") as cm: + compile(expr_without_position, "", "eval") + with self.assertRaisesRegex( + TypeError, + "field 'body' was expecting node of type 'expr', got 'list'", + ): + compile(expr_with_wrong_body, "", "eval") + + constant = ast.parse("u'test'", mode="eval") + constant.body.kind = 0xFF + with self.assertRaisesRegex( + TypeError, "field 'kind' was expecting a string or bytes object" + ): + compile(constant, "", "eval") + def test_repr(self) -> None: snapshots = AST_REPR_DATA_FILE.read_text().split("\n") for test, snapshot in zip(ast_repr_get_test_cases(), snapshots, strict=True): diff --git a/Lib/test/test_asyncio/test_ssl.py b/Lib/test/test_asyncio/test_ssl.py index ca15fc3bdd42dd7..784c784d261dc66 100644 --- a/Lib/test/test_asyncio/test_ssl.py +++ b/Lib/test/test_asyncio/test_ssl.py @@ -1544,6 +1544,9 @@ async def client(addr): # This triggers bug gh-115514, also tested using mocks in # test.test_asyncio.test_selector_events.SelectorSocketTransportTests.test_write_buffer_after_close socket_transport = writer.transport._ssl_protocol._transport + # connection_lost may have already cleared _transport. + if socket_transport is None: + return class SocketWrapper: def __init__(self, sock) -> None: diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index d2b3de3b9a4cb61..118cb866997c51c 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -1333,5 +1333,45 @@ async def child_main(): self.assertEqual(result.value, 0) + +@unittest.skipUnless( + unix_events.can_use_pidfd(), + "operating system does not support pidfd", +) +class PidfdChildWatcherTests(test_utils.TestCase): + + def setUp(self): + super().setUp() + self.loop = asyncio.new_event_loop() + self.set_event_loop(self.loop) + + def test_pidfd_closed_when_waitpid_raises(self): + # _do_wait() must close the pidfd even when waitpid() + # fails with something other than ChildProcessError, otherwise the + # pidfd is leaked + self.loop.set_exception_handler(lambda loop, context: None) + + async def coro(): + before = os_helper.fd_count() + proc = await asyncio.create_subprocess_exec( + sys.executable, '-c', 'import sys; sys.stdin.read()', + stdin=asyncio.subprocess.PIPE + ) + + with mock.patch.object(os, 'waitpid', + side_effect=OSError('unexpected')) as m: + proc.stdin.close() + while not m.called: + await asyncio.sleep(0) + + os.waitpid(proc.pid, 0) + proc._transport._process_exited(0) + await proc.wait() + + self.assertEqual(os_helper.fd_count(), before) + + self.loop.run_until_complete(coro()) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index e0e8dd4eccfb1b2..e211c3d15a4ed20 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -645,6 +645,32 @@ def test_join(self): with self.assertRaises(TypeError): dot_join([memoryview(b"ab"), "cd", b"ef"]) + def test_join_concurrent_buffer_mutation(self): + # __buffer__() can release the GIL, letting another thread concurrently + # mutate the joined sequence (simulated here by mutating in __buffer__). + # See: https://github.com/python/cpython/issues/151295 + def make_seq(mutate): + # Item is only referenced from the list slot, so mutate() frees it. + class Item: + def __buffer__(self, flags): + mutate(seq) + return memoryview(b'x') + seq = [b'a', Item(), b'c'] + return seq + + for sep in (self.type2test(b''), self.type2test(b'::')): + with self.subTest(sep=sep): + # Changing the list length is reported as a RuntimeError. + seq = make_seq(lambda seq: seq.clear()) + self.assertRaises(RuntimeError, sep.join, seq) + + # The list length is unchanged, so the size-change recheck + # cannot fire: only keeping the item alive avoids the crash. + def replace(seq): + seq[1] = b'z' + seq = make_seq(replace) + self.assertEqual(sep.join(seq), sep.join([b'a', b'x', b'c'])) + def test_count(self): b = self.type2test(b'mississippi') i = 105 diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index d8e3b671ec229f9..64293d757331d75 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -1032,6 +1032,21 @@ def test_failure(self): # Previously, a second call could crash due to internal inconsistency self.assertRaises(Exception, bzd.decompress, self.BAD_DATA * 30) + def test_decompress_after_data_error(self): + data = bytes.fromhex( + "425a6839314159265359000000000000007fffff000000000000000000000000" + "00000000000000000000000000000000000000e0370000000000000000000000" + "000000000000000000000000000000000000000000000000000083f3" + ) + bzd = BZ2Decompressor() + with self.assertRaisesRegex(OSError, "Invalid data stream"): + bzd.decompress(data) + # Previously, a second call could crash due to internal inconsistency + self.assertFalse(bzd.needs_input) + self.assertFalse(bzd.eof) + with self.assertRaisesRegex(ValueError, "previous error"): + bzd.decompress(b'\x00' * 18) + @support.refcount_test def test_refleaks_in___init__(self): gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') diff --git a/Lib/test/test_capi/test_config.py b/Lib/test/test_capi/test_config.py index f10ad50d3bea7e9..c750a6c2a477abd 100644 --- a/Lib/test/test_capi/test_config.py +++ b/Lib/test/test_capi/test_config.py @@ -356,9 +356,11 @@ def expect_bool_not(value): for value in new_values: expected, expect_flag = expect_func(value) + old_flags = sys.flags config_set(name, value) self.assertEqual(config_get(name), expected) self.assertEqual(getattr(sys.flags, sys_flag), expect_flag) + self.assertIsNot(sys.flags, old_flags) if name == "write_bytecode": self.assertEqual(getattr(sys, "dont_write_bytecode"), expect_flag) diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index 3debc6369e89fb4..6d84f0b8c305dfb 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -924,7 +924,7 @@ def test_tp_bases_slot(self): def test_tp_bases_slot_none(self): self.assertRaisesRegex( TypeError, - "metaclass conflict", + "bases must be types", _testcapi.create_heapctype_with_none_bases_slot ) diff --git a/Lib/test/test_capi/test_object.py b/Lib/test/test_capi/test_object.py index e5c50902a0118d4..433afac875aa7bf 100644 --- a/Lib/test/test_capi/test_object.py +++ b/Lib/test/test_capi/test_object.py @@ -178,11 +178,17 @@ class EnableDeferredRefcountingTest(unittest.TestCase): @support.requires_resource("cpu") def test_enable_deferred_refcount(self): from threading import Thread + import gc self.assertEqual(_testcapi.pyobject_enable_deferred_refcount("not tracked"), 0) foo = [] self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(foo), int(support.Py_GIL_DISABLED)) + # The object must be tracked by the GC + not_gc_tracked = tuple([1, 2]) + self.assertFalse(gc.is_tracked(not_gc_tracked)) + self.assertEqual(_testcapi.pyobject_enable_deferred_refcount(not_gc_tracked), 0) + # Make sure reference counting works on foo now self.assertEqual(foo, []) if support.Py_GIL_DISABLED: diff --git a/Lib/test/test_capi/test_slots.py b/Lib/test/test_capi/test_slots.py index c78b118712b11d5..b8b6d00b5f84d55 100644 --- a/Lib/test/test_capi/test_slots.py +++ b/Lib/test/test_capi/test_slots.py @@ -312,3 +312,38 @@ def test_repeat_error(self): _testlimitedcapi.module_from_slots("repeat_exec", FakeSpec()) with self.assertRaisesRegex(SystemError, "multiple"): _testlimitedcapi.module_from_slots("repeat_gil", FakeSpec()) + + def test_bases_slots(self): + create = _testlimitedcapi.type_from_base_slots + + # Py_tp_bases overrides Py_tp_base + cls = create(base=int, bases=float) + self.assertEqual(cls.mro(), [cls, float, object]) + + # type is equivalent to one-element tuple + cls = create(base=None, bases=int) + self.assertEqual(cls.mro(), [cls, int, object]) + + cls = create(base=None, bases=(int,)) + self.assertEqual(cls.mro(), [cls, int, object]) + + cls = create(base=int) + self.assertEqual(cls.mro(), [cls, int, object]) + + cls = create(base=(int,)) + self.assertEqual(cls.mro(), [cls, int, object]) + + # Tuple of bases works + class Custom: + pass + cls = create(bases=int) + sub = create(base=float, bases=(Custom, cls, int)) + self.assertEqual(sub.mro(), [sub, Custom, cls, int, object]) + + # Reasonable error message for non-types + with self.assertRaisesRegex(TypeError, + "bases must be types; got 'NoneType'"): + create(base=None) + with self.assertRaisesRegex(TypeError, + "bases must be types; got 'str'"): + create(bases="a string") diff --git a/Lib/test/test_capi/test_unicode.py b/Lib/test/test_capi/test_unicode.py index 5dee25756fe2893..0dcd8a25ad0128d 100644 --- a/Lib/test/test_capi/test_unicode.py +++ b/Lib/test/test_capi/test_unicode.py @@ -842,9 +842,7 @@ def test_fromwidechar(self): if SIZEOF_WCHAR_T == 2: self.assertEqual(fromwidechar('a\U0001f600'.encode(encoding), 2), 'a\ud83d') - self.assertRaises(MemoryError, fromwidechar, b'', PY_SSIZE_T_MAX) self.assertRaises(SystemError, fromwidechar, b'\0'*SIZEOF_WCHAR_T, -2) - self.assertRaises(SystemError, fromwidechar, b'\0'*SIZEOF_WCHAR_T, PY_SSIZE_T_MIN) self.assertEqual(fromwidechar(NULL, 0), '') self.assertRaises(SystemError, fromwidechar, NULL, 1) self.assertRaises(SystemError, fromwidechar, NULL, PY_SSIZE_T_MAX) @@ -852,6 +850,10 @@ def test_fromwidechar(self): self.assertRaises(SystemError, fromwidechar, NULL, -2) self.assertRaises(SystemError, fromwidechar, NULL, PY_SSIZE_T_MIN) + # The following tests are skipped since they rely on undefined behavior + #self.assertRaises(MemoryError, fromwidechar, b'', PY_SSIZE_T_MAX) + #self.assertRaises(SystemError, fromwidechar, b'\0'*SIZEOF_WCHAR_T, PY_SSIZE_T_MIN) + @support.cpython_only @unittest.skipIf(_testlimitedcapi is None, 'need _testlimitedcapi module') def test_aswidechar(self): diff --git a/Lib/test/test_capi/test_weakref.py b/Lib/test/test_capi/test_weakref.py new file mode 100644 index 000000000000000..7c9e97f571979dc --- /dev/null +++ b/Lib/test/test_capi/test_weakref.py @@ -0,0 +1,138 @@ +import weakref +import unittest +from test.support import import_helper + +_testcapi = import_helper.import_module('_testcapi') +_testlimitedcapi = import_helper.import_module('_testlimitedcapi') +NULL = None + +class Object: + pass + +class Ref(weakref.ReferenceType): + pass + + +class CAPIWeakrefTest(unittest.TestCase): + def test_pyweakref_check(self): + # Test PyWeakref_Check() + check = _testlimitedcapi.pyweakref_check + obj = Object() + self.assertEqual(check(obj), 0) + self.assertEqual(check(weakref.ref(obj)), 1) + self.assertEqual(check(Ref(obj)), 1) + self.assertEqual(check(weakref.proxy(obj)), 1) + + # CRASHES check(NULL) + + def test_pyweakref_checkref(self): + # Test PyWeakref_CheckRef() + checkref = _testlimitedcapi.pyweakref_checkref + obj = Object() + self.assertEqual(checkref(obj), 0) + self.assertEqual(checkref(weakref.ref(obj)), 1) + self.assertEqual(checkref(Ref(obj)), 1) + self.assertEqual(checkref(weakref.proxy(obj)), 0) + + # CRASHES checkref(NULL) + + def test_pyweakref_checkrefexact(self): + # Test PyWeakref_CheckRefExact() + checkrefexact = _testlimitedcapi.pyweakref_checkrefexact + obj = Object() + self.assertEqual(checkrefexact(obj), 0) + self.assertEqual(checkrefexact(weakref.ref(obj)), 1) + self.assertEqual(checkrefexact(Ref(obj)), 0) + self.assertEqual(checkrefexact(weakref.proxy(obj)), 0) + + # CRASHES checkrefexact(NULL) + + def test_pyweakref_checkproxy(self): + # Test PyWeakref_CheckProxy() + checkproxy = _testlimitedcapi.pyweakref_checkproxy + obj = Object() + self.assertEqual(checkproxy(obj), 0) + self.assertEqual(checkproxy(weakref.ref(obj)), 0) + self.assertEqual(checkproxy(Ref(obj)), 0) + self.assertEqual(checkproxy(weakref.proxy(obj)), 1) + + # CRASHES checkproxy(NULL) + + def test_pyweakref_getref(self): + # Test PyWeakref_GetRef() + getref = _testcapi.pyweakref_getref + obj = Object() + wr = weakref.ref(obj) + wp = weakref.proxy(obj) + self.assertEqual(getref(wr), (1, obj)) + self.assertEqual(getref(wp), (1, obj)) + del obj + self.assertEqual(getref(wr), 0) + self.assertEqual(getref(wp), 0) + + self.assertRaises(TypeError, getref, 42) + self.assertRaises(SystemError, getref, NULL) + + def test_pyweakref_isdead(self): + # Test PyWeakref_IsDead() + isdead = _testcapi.pyweakref_isdead + obj = Object() + wr = weakref.ref(obj) + wp = weakref.proxy(obj) + self.assertEqual(isdead(wr), 0) + self.assertEqual(isdead(wp), 0) + del obj + self.assertEqual(isdead(wr), 1) + self.assertEqual(isdead(wp), 1) + + self.assertRaises(TypeError, isdead, 42) + self.assertRaises(SystemError, isdead, NULL) + + def test_pyweakref_newref(self): + # Test PyWeakref_NewRef() + newref = _testlimitedcapi.pyweakref_newref + obj = Object() + wr = newref(obj) + self.assertIs(type(wr), weakref.ReferenceType) + # PyWeakref_NewRef() handles None callback as NULL callback + wr = newref(obj, None) + self.assertIs(type(wr), weakref.ReferenceType) + self.assertRaises(TypeError, newref, obj, 42) + log = [] + wr = newref(obj, log.append) + self.assertIs(type(wr), weakref.ReferenceType) + self.assertEqual(log, []) + del obj + self.assertEqual(log, [wr]) + + self.assertRaises(TypeError, newref, []) + # CRASHES newref(NULL) + + def test_pyweakref_newproxy(self): + # Test PyWeakref_NewProxy() + newproxy = _testlimitedcapi.pyweakref_newproxy + obj = Object() + wp = newproxy(obj) + self.assertIs(type(wp), weakref.ProxyType) + # PyWeakref_NewProxy() handles None callback as NULL callback + wp = newproxy(obj, None) + self.assertIs(type(wp), weakref.ProxyType) + self.assertRaises(TypeError, newproxy, obj, 42) + log = [] + wp = newproxy(obj, log.append) + self.assertIs(type(wp), weakref.ProxyType) + self.assertEqual(log, []) + del obj + self.assertEqual(log, [wp]) + + def func(): + pass + wp = newproxy(func) + self.assertIs(type(wp), weakref.CallableProxyType) + + self.assertRaises(TypeError, newproxy, []) + # CRASHES newproxy(NULL) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 3b556ec31445dfb..a8645af26b25d87 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -1314,6 +1314,17 @@ def test_presite(self): proc = assert_python_ok("-X", f"presite={entrypoint}", "-c", "pass") self.assertEqual(proc.out.rstrip(), b"presite func") + def test_dump_path_config(self): + # gh-151253: At the first import (import encodings) during Python + # startup, if the import fails, dump the Python path configuration. + nonexistent = '/nonexistent-python-path' + # Use -X frozen_modules=off to disable frozen encodings module + # on release build. + cmd = ["-X", "frozen_modules=off", "-c", "pass"] + proc = assert_python_failure(*cmd, PYTHONHOME=nonexistent) + self.assertIn(b'Python path configuration:', proc.err) + self.assertIn(f"PYTHONHOME = '{nonexistent}'".encode(), proc.err) + @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -I tests when PYTHON env vars are required.') diff --git a/Lib/test/test_concurrent_futures/test_process_pool.py b/Lib/test/test_concurrent_futures/test_process_pool.py index da70d910dc35614..45cfd46fb7befbf 100644 --- a/Lib/test/test_concurrent_futures/test_process_pool.py +++ b/Lib/test/test_concurrent_futures/test_process_pool.py @@ -3,6 +3,7 @@ import sys import threading import time +import traceback import unittest import unittest.mock from concurrent import futures @@ -62,6 +63,32 @@ def test_killed_child(self): # Submitting other jobs fails as well. self.assertRaises(BrokenProcessPool, self.executor.submit, pow, 2, 8) + @warnings_helper.ignore_fork_in_thread_deprecation_warnings() + def test_broken_process_pool_traceback(self): + # When a child process is abruptly terminated, the whole pool gets + # "broken", and a BrokenProcessPool exception should be created + # for each future instead of sharing one exception among all futures. + event = self.create_event() + futures = [self.executor.submit(event.wait) for _ in range(3)] + p = next(iter(self.executor._processes.values())) + p.terminate() + for fut in futures: + # Don't use assertRaises(): it clears the traceback off exc. + try: + fut.result() + except BrokenProcessPool as exc: + tb = exc.__traceback__ + else: + self.fail("BrokenProcessPool not raised") + count = sum( + 1 + for frame_summary in traceback.extract_tb(tb) + if frame_summary.filename == __file__ + ) + # This code file should appear exactly once in the traceback. + # A shared exception would accumulate a frame per result() call. + self.assertEqual(count, 1) + @warnings_helper.ignore_fork_in_thread_deprecation_warnings() def test_map_chunksize(self): def bad_map(): diff --git a/Lib/test/test_ctypes/test_as_parameter.py b/Lib/test/test_ctypes/test_as_parameter.py index 2da1acfcf2989ee..c9d728e9ae2f9cb 100644 --- a/Lib/test/test_ctypes/test_as_parameter.py +++ b/Lib/test/test_ctypes/test_as_parameter.py @@ -5,7 +5,7 @@ c_short, c_int, c_long, c_longlong, c_byte, c_wchar, c_float, c_double, ArgumentError) -from test.support import import_helper, skip_if_sanitizer +from test.support import import_helper, skip_if_sanitizer, skip_emscripten_stack_overflow _ctypes_test = import_helper.import_module("_ctypes_test") @@ -193,6 +193,7 @@ class S8I(Structure): (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) @skip_if_sanitizer('requires deep stack', thread=True) + @skip_emscripten_stack_overflow() def test_recursive_as_param(self): class A: pass diff --git a/Lib/test/test_ctypes/test_structures.py b/Lib/test/test_ctypes/test_structures.py index 92d4851d739d47b..65ccc12625f72be 100644 --- a/Lib/test/test_ctypes/test_structures.py +++ b/Lib/test/test_ctypes/test_structures.py @@ -299,9 +299,16 @@ class X(Structure): self.assertEqual(s.first, got.first) self.assertEqual(s.second, got.second) + @unittest.skipIf(support.is_wasm32, "wasm ABI is incompatible with test expectations") def _test_issue18060(self, Vector): # Regression tests for gh-62260 + # This test passes a struct of two doubles by value to atan2(), whose C + # signature is atan2(double, double), so it only works on platforms + # where the abi of a function that takes a struct with two doubles + # matches the abi of a function that takes two doubles. The wasm32 ABI + # does not satisfy this condition and the test breaks. + # The call to atan2() should succeed if the # class fields were correctly cloned in the # subclasses. Otherwise, it will segfault. diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 2468e3e64dd621c..423247c92ce3c29 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -2792,6 +2792,55 @@ def __eq__(self, other): self.assertEqual(C(1), 5) self.assertNotEqual(C(1), 1) + def test_eq_field_by_field(self): + @dataclasses.dataclass + class Point: + x: int + y: int + + p1 = Point(1, 2) + p2 = Point(1, 2) + p3 = Point(2, 1) + self.assertEqual(p1, p2) + self.assertNotEqual(p1, p3) + + def test_eq_type_check(self): + @dataclasses.dataclass + class A: + x: int + + @dataclasses.dataclass + class B: + x: int + + a = A(1) + b = B(1) + self.assertNotEqual(a, b) + + def test_eq_custom_field(self): + class AlwaysEqual(int): + def __eq__(self, other): + return True + + @dataclasses.dataclass + class Foo: + x: AlwaysEqual + y: int + + f1 = Foo(AlwaysEqual(1), 2) + f2 = Foo(AlwaysEqual(2), 2) + self.assertEqual(f1, f2) + + def test_eq_nan_field(self): + @dataclasses.dataclass + class D: + x: float + + nan = float('nan') + d1 = D(nan) + d2 = D(nan) + self.assertNotEqual(d1, d2) + class TestOrdering(unittest.TestCase): def test_functools_total_ordering(self): diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py index 4e1a489205a6855..3c45032cda91387 100644 --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -287,6 +287,22 @@ def test_index(self): else: self.assertEqual(d.index(element, start, stop), target) + # Test stop argument + for elem in d: + index = d.index(elem) + self.assertEqual( + index, + d.index(elem, 0), + ) + self.assertEqual( + index, + d.index(elem, 0, len(d)), + ) + self.assertEqual( + index, + d.index(elem, 0, len(d) + 100), + ) + # Test large start argument d = deque(range(0, 10000, 10)) for step in range(100): diff --git a/Lib/test/test_dtrace.py b/Lib/test/test_dtrace.py index 61320a472f3e02c..592f59d77f92217 100644 --- a/Lib/test/test_dtrace.py +++ b/Lib/test/test_dtrace.py @@ -1,6 +1,7 @@ import dis import os.path import re +import signal import subprocess import sys import sysconfig @@ -50,6 +51,24 @@ def normalize_trace_output(output): ) +USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg")) + +def create_process_group(*args, **kwargs): + if USE_PROCESS_GROUP: + kwargs['start_new_session'] = True + return subprocess.Popen(*args, **kwargs) + +def kill_process_group(proc): + if USE_PROCESS_GROUP: + try: + os.killpg(proc.pid, signal.SIGKILL) + except ProcessLookupError: + pass + else: + proc.kill() + proc.communicate() # Clean up + + class TraceBackend: EXTENSION = None COMMAND = None @@ -205,7 +224,7 @@ def run_case(self, name, optimize_python=None): program = self.PROGRAMS[name].format(python=sys.executable) try: - proc = subprocess.Popen( + proc = create_process_group( ["bpftrace", "-e", program, "-c", " ".join(subcommand)], stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -213,7 +232,7 @@ def run_case(self, name, optimize_python=None): ) stdout, stderr = proc.communicate(timeout=60) except subprocess.TimeoutExpired: - proc.kill() + kill_process_group(proc) raise AssertionError("bpftrace timed out") except (FileNotFoundError, PermissionError) as e: raise unittest.SkipTest(f"bpftrace not available: {e}") @@ -243,7 +262,7 @@ def assert_usable(self): # Check if bpftrace is available and can attach to USDT probes program = f'usdt:{sys.executable}:python:function__entry {{ printf("probe: success\\n"); exit(); }}' try: - proc = subprocess.Popen( + proc = create_process_group( ["bpftrace", "-e", program, "-c", f"{sys.executable} -c pass"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -251,8 +270,7 @@ def assert_usable(self): ) stdout, stderr = proc.communicate(timeout=10) except subprocess.TimeoutExpired: - proc.kill() - proc.communicate() # Clean up + kill_process_group(proc) raise unittest.SkipTest("bpftrace timed out during usability check") except OSError as e: raise unittest.SkipTest(f"bpftrace not available: {e}") @@ -378,11 +396,14 @@ def setUpClass(cls): def get_readelf_version(): try: cmd = ["readelf", "--version"] + # Force the C locale to disable localization. + env = dict(os.environ, LC_ALL="C") proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, + env=env, ) with proc: version, stderr = proc.communicate() @@ -405,12 +426,36 @@ def get_readelf_version(): return int(match.group(1)), int(match.group(2)) def get_readelf_output(self): - command = ["readelf", "-n", sys.executable] + binary = sys.executable + if sysconfig.get_config_var("Py_ENABLE_SHARED"): + lib_dir = sysconfig.get_config_var("LIBDIR") + if not lib_dir or sysconfig.is_python_build(): + lib_dir = os.path.abspath(os.path.dirname(sys.executable)) + + lib_names = [] + for name in ( + sysconfig.get_config_var("INSTSONAME"), + sysconfig.get_config_var("LDLIBRARY"), + ): + if name and name not in lib_names: + lib_names.append(name) + + if lib_dir: + for name in lib_names: + libpython_path = os.path.join(lib_dir, name) + if os.path.exists(libpython_path): + binary = libpython_path + break + + command = ["readelf", "-n", binary] + # Force the C locale to disable localization. + env = dict(os.environ, LC_ALL="C") stdout, _ = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, + env=env, ).communicate() return stdout diff --git a/Lib/test/test_email/test_asian_codecs.py b/Lib/test/test_email/test_asian_codecs.py index 85979ffd8169a75..59013f087199e3a 100644 --- a/Lib/test/test_email/test_asian_codecs.py +++ b/Lib/test/test_email/test_asian_codecs.py @@ -83,15 +83,15 @@ def test_chinese_codecs(self): h.append(s, Charset('big5hkscs')) eq(h.encode(), """\ Chinese =?gb2312?b?1tDOxA==?= =?gbk?b?1tDOxA==?= =?gb18030?b?1tDOxA==?= - =?hz?b?fntWUE5Efn0=?= =?big5?b?pKSk5Q==?= =?big5hkscs?b?pKSk5Q==?=""") + =?hz-gb-2312?b?fntWUE5Efn0=?= =?big5?b?pKSk5Q==?= =?big5-hkscs?b?pKSk5Q==?=""") eq(decode_header(h.encode()), [(b'Chinese ', None), (b'\xd6\xd0\xce\xc4', 'gb2312'), (b'\xd6\xd0\xce\xc4', 'gbk'), (b'\xd6\xd0\xce\xc4', 'gb18030'), - (b'~{VPND~}', 'hz'), + (b'~{VPND~}', 'hz-gb-2312'), (b'\xa4\xa4\xa4\xe5', 'big5'), - (b'\xa4\xa4\xa4\xe5', 'big5hkscs'), + (b'\xa4\xa4\xa4\xe5', 'big5-hkscs'), ]) def test_korean_codecs(self): diff --git a/Lib/test/test_email/test_contentmanager.py b/Lib/test/test_email/test_contentmanager.py index dceb54f15e48f4e..3115941f8703194 100644 --- a/Lib/test/test_email/test_contentmanager.py +++ b/Lib/test/test_email/test_contentmanager.py @@ -342,6 +342,66 @@ def test_set_text_charset_latin_1(self): self.assertEqual(m.get_payload(decode=True).decode('utf-8'), content) self.assertEqual(m.get_content(), content) + def test_set_text_charset_cp949(self): + m = self._make_message() + content = "\ud55c\uad6d\uc5b4\n\uac02\n" + raw_data_manager.set_content(m, content, charset='cp949') + self.assertEqual(str(m), textwrap.dedent("""\ + Content-Type: text/plain; charset="ks_c_5601-1987" + Content-Transfer-Encoding: base64 + + x9Gxub7uCoFBCg== + """)) + self.assertEqual(bytes(m), textwrap.dedent("""\ + Content-Type: text/plain; charset="ks_c_5601-1987" + Content-Transfer-Encoding: 8bit + + \ud55c\uad6d\uc5b4 + \uac02 + """).encode('ks_c_5601-1987')) + self.assertEqual(m.get_payload(decode=True), content.encode('ks_c_5601-1987')) + self.assertEqual(m.get_content(), content) + + def test_set_text_charset_shift_jis(self): + m = self._make_message() + content = "\u65e5\u672c\u8a9e\n" + raw_data_manager.set_content(m, content, charset='shift_jis') + self.assertEqual(m['Content-Type'], 'text/plain; charset="iso-2022-jp"') + self.assertEqual(m.get_payload(decode=True), content.encode('iso-2022-jp')) + self.assertEqual(m.get_content(), content) + self.assertEqual(str(m), textwrap.dedent("""\ + Content-Type: text/plain; charset="iso-2022-jp" + Content-Transfer-Encoding: 7bit + + \x1b$BF|K\\8l\x1b(B + """)) + self.assertEqual(bytes(m), textwrap.dedent("""\ + Content-Type: text/plain; charset="iso-2022-jp" + Content-Transfer-Encoding: 7bit + + \u65e5\u672c\u8a9e + """).encode('iso-2022-jp')) + + def test_set_text_charset_euc_jp(self): + m = self._make_message() + content = "\u65e5\u672c\u8a9e\n" + raw_data_manager.set_content(m, content, charset='euc-jp') + self.assertEqual(m['Content-Type'], 'text/plain; charset="iso-2022-jp"') + self.assertEqual(m.get_payload(decode=True), content.encode('iso-2022-jp')) + self.assertEqual(m.get_content(), content) + self.assertEqual(str(m), textwrap.dedent("""\ + Content-Type: text/plain; charset="iso-2022-jp" + Content-Transfer-Encoding: 7bit + + \x1b$BF|K\\8l\x1b(B + """)) + self.assertEqual(bytes(m), textwrap.dedent("""\ + Content-Type: text/plain; charset="iso-2022-jp" + Content-Transfer-Encoding: 7bit + + \u65e5\u672c\u8a9e + """).encode('iso-2022-jp')) + def test_set_text_plain_long_line_heuristics(self): m = self._make_message() content = ("Simple but long message that is over 78 characters" diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py index d2c2261edbe04e1..19555d87085e176 100644 --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -4970,6 +4970,128 @@ def tearDown(self): except KeyError: pass + def test_attributes(self): + from email import charset + c = Charset() + self.assertEqual(c.input_charset, 'us-ascii') + self.assertEqual(c.header_encoding, None) + self.assertEqual(c.body_encoding, None) + self.assertEqual(c.output_charset, 'us-ascii') + self.assertEqual(c.input_codec, None) + self.assertEqual(c.output_codec, None) + + c = Charset('us-ascii') + self.assertEqual(c.input_charset, 'us-ascii') + self.assertEqual(c.header_encoding, None) + self.assertEqual(c.body_encoding, None) + self.assertEqual(c.output_charset, 'us-ascii') + self.assertEqual(c.input_codec, None) + self.assertEqual(c.output_codec, None) + + c = Charset('utf8') + self.assertEqual(c.input_charset, 'utf-8') + self.assertEqual(c.header_encoding, charset.SHORTEST) + self.assertEqual(c.body_encoding, charset.BASE64) + self.assertEqual(c.output_charset, 'utf-8') + self.assertEqual(c.input_codec, 'utf-8') + self.assertEqual(c.output_codec, 'utf-8') + + c = Charset('latin1') + self.assertEqual(c.input_charset, 'iso-8859-1') + self.assertEqual(c.header_encoding, charset.QP) + self.assertEqual(c.body_encoding, charset.QP) + self.assertEqual(c.output_charset, 'iso-8859-1') + self.assertEqual(c.input_codec, 'iso-8859-1') + self.assertEqual(c.output_codec, 'iso-8859-1') + + c = Charset('latin9') + self.assertEqual(c.input_charset, 'iso-8859-15') + self.assertEqual(c.header_encoding, charset.QP) + self.assertEqual(c.body_encoding, charset.QP) + self.assertEqual(c.output_charset, 'iso-8859-15') + self.assertEqual(c.input_codec, 'iso-8859-15') + self.assertEqual(c.output_codec, 'iso-8859-15') + + c = Charset('cyrillic') + self.assertEqual(c.input_charset, 'iso-8859-5') + self.assertEqual(c.header_encoding, charset.SHORTEST) + self.assertEqual(c.body_encoding, charset.BASE64) + self.assertEqual(c.output_charset, 'iso-8859-5') + self.assertEqual(c.input_codec, 'iso-8859-5') + self.assertEqual(c.output_codec, 'iso-8859-5') + + c = Charset('cp1251') + self.assertEqual(c.input_charset, 'windows-1251') + self.assertEqual(c.header_encoding, charset.SHORTEST) + self.assertEqual(c.body_encoding, charset.BASE64) + self.assertEqual(c.output_charset, 'windows-1251') + self.assertEqual(c.input_codec, 'windows-1251') + self.assertEqual(c.output_codec, 'windows-1251') + + c = Charset('cp1252') + self.assertEqual(c.input_charset, 'windows-1252') + self.assertEqual(c.header_encoding, charset.QP) + self.assertEqual(c.body_encoding, charset.QP) + self.assertEqual(c.output_charset, 'windows-1252') + self.assertEqual(c.input_codec, 'windows-1252') + self.assertEqual(c.output_codec, 'windows-1252') + + c = Charset('eucjp') + self.assertEqual(c.input_charset, 'euc-jp') + self.assertEqual(c.header_encoding, charset.BASE64) + self.assertEqual(c.body_encoding, None) + self.assertEqual(c.output_charset, 'iso-2022-jp') + self.assertEqual(c.input_codec, 'euc-jp') + self.assertEqual(c.output_codec, 'iso-2022-jp') + + c = Charset('cp949') + self.assertEqual(c.input_charset, 'ks_c_5601-1987') + self.assertEqual(c.header_encoding, charset.SHORTEST) + self.assertEqual(c.body_encoding, charset.BASE64) + self.assertEqual(c.output_charset, 'ks_c_5601-1987') + self.assertEqual(c.input_codec, 'ks_c_5601-1987') + self.assertEqual(c.output_codec, 'ks_c_5601-1987') + + c = Charset('gb2312') + self.assertEqual(c.input_charset, 'gb2312') + self.assertEqual(c.header_encoding, charset.BASE64) + self.assertEqual(c.body_encoding, charset.BASE64) + self.assertEqual(c.output_charset, 'gb2312') + self.assertEqual(c.input_codec, 'gb2312') + self.assertEqual(c.output_codec, 'gb2312') + + c = Charset('big5') + self.assertEqual(c.input_charset, 'big5') + self.assertEqual(c.header_encoding, charset.BASE64) + self.assertEqual(c.body_encoding, charset.BASE64) + self.assertEqual(c.output_charset, 'big5') + self.assertEqual(c.input_codec, 'big5') + self.assertEqual(c.output_codec, 'big5') + + def test_user_charsets(self): + from email import charset + c = Charset('fake0') + self.assertEqual(c.input_charset, 'fake0') + self.assertEqual(c.header_encoding, charset.SHORTEST) + self.assertEqual(c.body_encoding, charset.BASE64) + self.assertEqual(c.output_charset, 'fake0') + self.assertEqual(c.input_codec, 'fake0') + self.assertEqual(c.output_codec, 'fake0') + + charset.add_alias('fake1', 'mime-fake') + charset.add_alias('output-mime-fake', 'output-mime-fake-alias') + charset.add_codec('mime-fake', 'fakecodec') + charset.add_codec('output-mime-fake-alias', 'outputfakecodec') + charset.add_charset('mime-fake', charset.QP, None, 'output-mime-fake') + + c = Charset('fake1') + self.assertEqual(c.input_charset, 'mime-fake') + self.assertEqual(c.header_encoding, charset.QP) + self.assertEqual(c.body_encoding, None) + self.assertEqual(c.output_charset, 'output-mime-fake-alias') + self.assertEqual(c.input_codec, 'fakecodec') + self.assertEqual(c.output_codec, 'outputfakecodec') + def test_codec_encodeable(self): eq = self.assertEqual # Make sure us-ascii = no Unicode conversion @@ -5010,6 +5132,11 @@ def test_unicode_charset_name(self): self.assertEqual(str(charset), 'us-ascii') self.assertRaises(errors.CharsetError, Charset, 'asc\xffii') + def test_bytes_charset_name(self): + charset = Charset(b'us-ascii') + self.assertEqual(str(charset), 'us-ascii') + self.assertRaises(errors.CharsetError, Charset, b'asc\xffii') + # Test multilingual MIME headers. diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 3f5fcb29b442dec..df7a04273b9b41c 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1714,6 +1714,20 @@ def inner(): gc_collect() # For PyPy or other GCs. self.assertEqual(wr(), None) + def test_oserror_reinit_leak(self): + # gh-150988: Check for memory leak when re-initializing OSError. + # Previously, setting OSError attributes in a subclass + # before calling super().__init__() leaked memory. + class LeakingOSError(OSError): + def __init__(self, code, message, filename, filename2): + self.strerror = message + self.filename = filename + self.filename2 = filename2 + super().__init__(code, message, filename, None, filename2) + + exc = LeakingOSError(1, "some message", "filename.py", "filename2.py") + exc.__init__(2, "another message", "filename3.py", "filename4.py") + def test_errno_ENOTDIR(self): # Issue #12802: "not a directory" errors are ENOTDIR even on Windows with self.assertRaises(OSError) as cm: diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 11df59f2346f316..5a493a4fd956802 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -33,6 +33,11 @@ CURRENT_THREAD_HEADER = fr'{CURRENT_THREAD_ID} \(most recent call first\):' +def skip_if_sanitizer_signal(signame): + return support.skip_if_sanitizer(f"TSAN/UBSan itercepts {signame}", + thread=True, ub=True) + + def expected_traceback(lineno1, lineno2, header, min_count=1): regex = header regex += ' File "", line %s in func\n' % lineno1 @@ -224,7 +229,7 @@ def test_fatal_error_c_thread(self): func='faulthandler_fatal_error_thread', py_fatal_error=True) - @support.skip_if_sanitizer("TSAN itercepts SIGABRT", thread=True) + @skip_if_sanitizer_signal("SIGABRT") def test_sigabrt(self): self.check_fatal_error(""" import faulthandler @@ -236,7 +241,7 @@ def test_sigabrt(self): @unittest.skipIf(sys.platform == 'win32', "SIGFPE cannot be caught on Windows") - @support.skip_if_sanitizer("TSAN itercepts SIGFPE", thread=True) + @skip_if_sanitizer_signal("SIGFPE") def test_sigfpe(self): self.check_fatal_error(""" import faulthandler @@ -248,7 +253,7 @@ def test_sigfpe(self): @unittest.skipIf(_testcapi is None, 'need _testcapi') @unittest.skipUnless(hasattr(signal, 'SIGBUS'), 'need signal.SIGBUS') - @support.skip_if_sanitizer("TSAN itercepts SIGBUS", thread=True) + @skip_if_sanitizer_signal("SIGBUS") @skip_segfault_on_android def test_sigbus(self): self.check_fatal_error(""" @@ -263,7 +268,7 @@ def test_sigbus(self): @unittest.skipIf(_testcapi is None, 'need _testcapi') @unittest.skipUnless(hasattr(signal, 'SIGILL'), 'need signal.SIGILL') - @support.skip_if_sanitizer("TSAN itercepts SIGILL", thread=True) + @skip_if_sanitizer_signal("SIGILL") @skip_segfault_on_android def test_sigill(self): self.check_fatal_error(""" diff --git a/Lib/test/test_free_threading/test_collections.py b/Lib/test/test_free_threading/test_collections.py index 3a413ccf396d4ba..849b0480e232fc2 100644 --- a/Lib/test/test_free_threading/test_collections.py +++ b/Lib/test/test_free_threading/test_collections.py @@ -24,6 +24,30 @@ def copy_loop(): threading_helper.run_concurrently([mutate, copy_loop]) + def test_index_race_in_ac(self): + # gh-150750: There was a c_default specified as `Py_SIZE(self)`, + # it was used without a critical section. + + d = deque(range(100)) + + def index(): + for _ in range(10000): + try: + d.index(50) + except ValueError: + pass + + def mutate(): + for _ in range(10000): + d.append(0) + d.clear() + d.extend(range(100)) + d.appendleft(-1) + + threading_helper.run_concurrently( + [index, *[mutate for _ in range(3)]], + ) + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_free_threading/test_dict.py b/Lib/test/test_free_threading/test_dict.py index dfe0634211d4b02..ad23290a92ab345 100644 --- a/Lib/test/test_free_threading/test_dict.py +++ b/Lib/test/test_free_threading/test_dict.py @@ -296,6 +296,24 @@ def reader(): threading_helper.run_concurrently([clearer, reader, reader]) + def test_racing_embedded_values_clear_and_lookup(self): + class C: + pass + + obj = C() + def writer(): + for _ in range(1000): + obj.x = 1 + obj.y = 2 + obj.z = 3 + obj.__dict__.clear() + + def reader(): + for _ in range(1000): + obj.__dict__.get('x') + + threading_helper.run_concurrently([writer, reader, reader]) + def test_racing_dict_update_and_method_lookup(self): # gh-144295: test race between dict modifications and method lookups. # Uses BytesIO because the race requires a type without Py_TPFLAGS_INLINE_VALUES diff --git a/Lib/test/test_free_threading/test_gc.py b/Lib/test/test_free_threading/test_gc.py index 8b45b6e2150c288..399010234509408 100644 --- a/Lib/test/test_free_threading/test_gc.py +++ b/Lib/test/test_free_threading/test_gc.py @@ -94,6 +94,65 @@ def evil(): thread.start() thread.join() + def test_set_threshold(self): + # GH-148613: Setting the GC threshold from another thread could cause a + # race between the `gc_should_collect` and `gc_set_threshold` functions. + NUM_THREADS = 8 + NUM_ITERS = 100_000 + barrier = threading.Barrier(NUM_THREADS) + + class CyclicReference: + def __init__(self): + self.r = self + + def allocator(): + barrier.wait() + for _ in range(NUM_ITERS): + CyclicReference() + + def setter(): + barrier.wait() + for i in range(NUM_ITERS): + gc.set_threshold(100 + (i % 100), 10 + (i % 10), 10 + (i % 10)) + + current_threshold = gc.get_threshold() + try: + threads = [Thread(target=allocator) for _ in range(NUM_THREADS - 1)] + threads.append(Thread(target=setter)) + with threading_helper.start_threads(threads): + pass + finally: + gc.set_threshold(*current_threshold) + + def test_get_count(self): + class CyclicReference: + def __init__(self): + self.ref = self + + NUM_ALLOCATORS = 7 + NUM_READERS = 1 + NUM_THREADS = NUM_ALLOCATORS + NUM_READERS + NUM_ITERS = 1000 + + barrier = threading.Barrier(NUM_THREADS) + + def allocator(): + barrier.wait() + for _ in range(NUM_ITERS): + CyclicReference() + + + def reader(): + barrier.wait() + for _ in range(NUM_ITERS): + gc.get_count() + + threads = [Thread(target=allocator) for _ in range(NUM_ALLOCATORS)] + threads.extend(Thread(target=reader) for _ in range(NUM_READERS)) + + with threading_helper.start_threads(threads): + pass + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_free_threading/test_sys.py b/Lib/test/test_free_threading/test_sys.py new file mode 100644 index 000000000000000..37b53bd723fd767 --- /dev/null +++ b/Lib/test/test_free_threading/test_sys.py @@ -0,0 +1,28 @@ +import sys +import unittest +from test.support import threading_helper + + +class SysModuleTest(unittest.TestCase): + def test_int_max_str_digits_thread(self): + # gh-151218: Check that it's safe to call get_int_max_str_digits() and + # set_int_max_str_digits() in parallel. Previously, this test triggered + # warnings in TSan on a free threaded build. + + old_limit = sys.get_int_max_str_digits() + self.addCleanup(sys.set_int_max_str_digits, old_limit) + + def worker(worker_id): + if not worker_id: + for i in range (20_000): + sys.get_int_max_str_digits() + else: + for i in range (20_000): + sys.set_int_max_str_digits(4300 + (i & 7)) + + workers = [lambda: worker(i) for i in range(5)] + threading_helper.run_concurrently(workers) + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 05d0cbd2445c4cb..5cc02c30ec2ba33 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -593,6 +593,17 @@ def test_compile_time_concat_errors(self): r"""b'' f''""", ]) + def test_concat_decode_failure_does_not_crash(self): + script = r''' +import builtins +builtins.__import__ = builtins # Breaks warning machinery so _get_resized_exprs returns NULL +try: + compile('"x"f"\]"b""', '', 'exec') +except Exception: + pass +''' + assert_python_ok('-c', script) + def test_literal(self): self.assertEqual(f'', '') self.assertEqual(f'a', 'a') diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index c905c0da0a12327..9f3df8010d32339 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -364,6 +364,15 @@ def test_import_raises_ModuleNotFoundError(self): with self.assertRaises(ModuleNotFoundError): import something_that_should_not_exist_anywhere + def test_import_null_byte_in_name_raises_ModuleNotFoundError(self): + # gh-150633: module names containing null bytes should not + # lead to duplicates in sys.modules + before = set(sys.modules) + with self.assertRaises(ModuleNotFoundError): + __import__('zipimport\x00junk') + + self.assertEqual(set(sys.modules), before) + def test_from_import_missing_module_raises_ModuleNotFoundError(self): with self.assertRaises(ModuleNotFoundError): from something_that_should_not_exist_anywhere import blah diff --git a/Lib/test/test_io/test_textio.py b/Lib/test/test_io/test_textio.py index d725f9212ceaaef..82096ab09873955 100644 --- a/Lib/test/test_io/test_textio.py +++ b/Lib/test/test_io/test_textio.py @@ -1560,6 +1560,56 @@ def closed(self): wrapper = self.TextIOWrapper(raw) wrapper.close() # should not crash + def test_reentrant_detach_during_flush(self): + # gh-143008: Reentrant detach() during flush should not crash. + + class DetachOnce(self.BufferedRandom): + wrapper = None + + def detach_once(self): + original = self.wrapper + self.wrapper = None + if original is not None: + original.detach() + original.flush() + + class DetachOnFlush(DetachOnce): + def flush(self): + self.detach_once() + + class DetachOnWrite(DetachOnce): + def write(self, b): + self.detach_once() + return len(b) + + # Separate reference for after detach_once. + wrapper = None + + def make_text(buffer): + nonlocal wrapper + buffer.wrapper = self.TextIOWrapper(buffer, encoding='utf-8') + wrapper = buffer.wrapper + + # Many calls could result in the same null self->buffer crash. + tests = [ + ('truncate', lambda: wrapper.truncate(0)), + ('close', lambda: wrapper.close()), + ('detach', lambda: wrapper.detach()), + ('seek', lambda: wrapper.seek(0)), + ('tell', lambda: wrapper.tell()), + ('reconfigure', lambda: wrapper.reconfigure(line_buffering=True)), + ] + for name, method in tests: + with self.subTest(name): + make_text(DetachOnFlush(self.MockRawIO())) + self.assertRaisesRegex(ValueError, "detached", method) + + # Should not crash. + with self.subTest('read via writeflush'): + make_text(DetachOnWrite(self.MockRawIO())) + wrapper.write('x') + self.assertRaisesRegex(ValueError, "detached", wrapper.read) + class PyTextIOWrapperTest(TextIOWrapperTest, PyTestCase): shutdown_error = "LookupError: unknown encoding: ascii" diff --git a/Lib/test/test_json/test_recursion.py b/Lib/test/test_json/test_recursion.py index ffd3404e6f77a07..d732fc80cf1cf30 100644 --- a/Lib/test/test_json/test_recursion.py +++ b/Lib/test/test_json/test_recursion.py @@ -68,6 +68,7 @@ def default(self, o): self.fail("didn't raise ValueError on default recursion") + @support.skip_if_pgo_task # fails during PGO training w/ some stack sizes @support.skip_if_unlimited_stack_size @support.skip_emscripten_stack_overflow() @support.skip_wasi_stack_overflow() diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 321733a4fdf1705..1724beb8ce69517 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -21,8 +21,10 @@ _testcapi = None -class LazyImportTests(unittest.TestCase): - """Tests for basic lazy import functionality.""" +class LazyImportTestCase(unittest.TestCase): + def setUp(self): + self.lazy_imports_filter = sys.get_lazy_imports_filter() + self.lazy_imports = sys.get_lazy_imports() def tearDown(self): """Clean up any test modules from sys.modules.""" @@ -30,10 +32,14 @@ def tearDown(self): if key.startswith('test.test_lazy_import.data'): del sys.modules[key] - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") + sys.set_lazy_imports_filter(self.lazy_imports_filter) + sys.set_lazy_imports(self.lazy_imports) sys.lazy_modules.clear() + +class LazyImportTests(LazyImportTestCase): + """Tests for basic lazy import functionality.""" + def test_basic_unused(self): """Lazy imported module should not be loaded if never accessed.""" import test.test_lazy_import.data.basic_unused @@ -162,17 +168,9 @@ def test_from_import_with_imported_module_getattr(self): assert_python_ok("-c", code) -class GlobalLazyImportModeTests(unittest.TestCase): +class GlobalLazyImportModeTests(LazyImportTestCase): """Tests for sys.set_lazy_imports() global mode control.""" - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_global_off_rejected(self): """Mode 'none' is not supported.""" with self.assertRaises(ValueError): @@ -204,17 +202,9 @@ def test_global_filter_from_true(self): self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) -class CompatibilityModeTests(unittest.TestCase): +class CompatibilityModeTests(LazyImportTestCase): """Tests for __lazy_modules__ compatibility mode.""" - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_compatibility_mode(self): """__lazy_modules__ should enable lazy imports for listed modules.""" import test.test_lazy_import.data.basic_compatibility_mode @@ -241,17 +231,9 @@ def test_compatibility_mode_relative(self): self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) -class ModuleIntrospectionTests(unittest.TestCase): +class ModuleIntrospectionTests(LazyImportTestCase): """Tests for module dict and getattr behavior with lazy imports.""" - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_modules_dict(self): """Accessing module.__dict__ should not trigger reification.""" import test.test_lazy_import.data.modules_dict @@ -268,17 +250,9 @@ def test_modules_getattr_other(self): self.assertNotIn("test.test_lazy_import.data.basic2", sys.modules) -class LazyImportTypeTests(unittest.TestCase): +class LazyImportTypeTests(LazyImportTestCase): """Tests for the LazyImportType and its resolve() method.""" - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_lazy_value_resolve(self): """resolve() method should force the lazy import to load.""" import test.test_lazy_import.data.lazy_get_value @@ -304,17 +278,9 @@ def test_lazy_import_type_attributes_accessible(self): self.assertIn(b" bool """ - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def _run_subprocess_with_modules(self, code, files): with tempfile.TemporaryDirectory() as tmpdir: for relpath, contents in files.items(): @@ -1611,17 +1501,9 @@ def my_filter(importer, name, fromlist): self.assertIn("OK", result.stdout) -class AdditionalSyntaxRestrictionTests(unittest.TestCase): +class AdditionalSyntaxRestrictionTests(LazyImportTestCase): """Additional syntax restriction tests per PEP 810.""" - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_lazy_import_inside_class_raises_syntax_error(self): """lazy import inside class body should raise SyntaxError.""" # PEP 810: "The soft keyword is only allowed at the global (module) level, @@ -1631,7 +1513,7 @@ def test_lazy_import_inside_class_raises_syntax_error(self): @support.requires_subprocess() -class MixedLazyEagerImportTests(unittest.TestCase): +class MixedLazyEagerImportTests(LazyImportTestCase): """Tests for mixing lazy and eager imports of the same module. PEP 810: "If module foo is imported both lazily and eagerly in the same @@ -1639,14 +1521,6 @@ class MixedLazyEagerImportTests(unittest.TestCase): the same module object." """ - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_eager_import_before_lazy_resolves_to_same_module(self): """Eager import before lazy should make lazy resolve to same module.""" code = textwrap.dedent(""" @@ -1692,17 +1566,9 @@ def test_lazy_import_before_eager_resolves_to_same_module(self): self.assertIn("OK", result.stdout) -class RelativeImportTests(unittest.TestCase): +class RelativeImportTests(LazyImportTestCase): """Tests for relative imports with lazy keyword.""" - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_relative_lazy_import(self): """lazy from . import submodule should work.""" from test.test_lazy_import.data import relative_lazy @@ -1727,21 +1593,13 @@ def test_relative_lazy_from_import(self): self.assertIn("test.test_lazy_import.data.basic2", sys.modules) -class LazyModulesCompatibilityFromImportTests(unittest.TestCase): +class LazyModulesCompatibilityFromImportTests(LazyImportTestCase): """Tests for __lazy_modules__ with from imports. PEP 810: "When a module is made lazy this way, from-imports using that module are also lazy" """ - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_lazy_modules_makes_from_imports_lazy(self): """__lazy_modules__ should make from imports of listed modules lazy.""" from test.test_lazy_import.data import lazy_compat_from @@ -1756,7 +1614,7 @@ def test_lazy_modules_makes_from_imports_lazy(self): @support.requires_subprocess() -class ImportStateAtReificationTests(unittest.TestCase): +class ImportStateAtReificationTests(LazyImportTestCase): """Tests for import system state at reification time. PEP 810: "Reification still calls __import__ to resolve the import, which uses @@ -1765,14 +1623,6 @@ class ImportStateAtReificationTests(unittest.TestCase): statement was evaluated." """ - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_sys_path_at_reification_time_is_used(self): """sys.path changes after lazy import should affect reification.""" code = textwrap.dedent(""" @@ -1815,17 +1665,9 @@ def test_sys_path_at_reification_time_is_used(self): @support.requires_subprocess() -class ThreadSafetyTests(unittest.TestCase): +class ThreadSafetyTests(LazyImportTestCase): """Tests for thread-safety of lazy imports.""" - def tearDown(self): - for key in list(sys.modules.keys()): - if key.startswith('test.test_lazy_import.data'): - del sys.modules[key] - - sys.set_lazy_imports_filter(None) - sys.set_lazy_imports("normal") - def test_concurrent_lazy_import_reification(self): """Multiple threads racing to reify the same lazy import should succeed.""" from test.test_lazy_import.data import basic_unused @@ -2087,11 +1929,7 @@ def test_normal_import_dis(self): @unittest.skipIf(_testcapi is None, 'need the _testcapi module') -class LazyCApiTests(unittest.TestCase): - def tearDown(self): - sys.set_lazy_imports("normal") - sys.set_lazy_imports_filter(None) - +class LazyCApiTests(LazyImportTestCase): def test_set_matches_sys(self): self.assertEqual(_testcapi.PyImport_GetLazyImportsMode(), sys.get_lazy_imports()) for mode in ("normal", "all"): diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py index cee528722b85aa0..cf3796d94808015 100644 --- a/Lib/test/test_listcomps.py +++ b/Lib/test/test_listcomps.py @@ -171,6 +171,17 @@ def test_references___class__(self): """ self._check_in_scopes(code, raises=NameError) + def test_references___class___nested(self): + code = """ + res = [(lambda: __class__)() for _ in [1]] + """ + self._check_in_scopes(code, raises=NameError) + + def test_references___class___nested_used(self): + class _C: + res = [lambda: __class__ for _ in [1]] + self.assertIs(_C.res[0](), _C) + def test_references___class___defined(self): code = """ __class__ = 2 @@ -180,18 +191,38 @@ def test_references___class___defined(self): code, outputs={"res": [2]}, scopes=["module", "function"]) self._check_in_scopes(code, raises=NameError, scopes=["class"]) + def test_references___class___defined_nested(self): + code = """ + __class__ = 2 + res = [(lambda: __class__)() for x in [1]] + """ + self._check_in_scopes( + code, outputs={"res": [2]}, scopes=["module", "function"]) + self._check_in_scopes(code, raises=NameError, scopes=["class"]) + def test_references___classdict__(self): code = """ class i: [__classdict__ for x in y] """ self._check_in_scopes(code, raises=NameError) + def test_references___classdict___nested(self): + class _C: + res = [(lambda: __classdict__)() for _ in [1]] + self.assertIn("res", _C.res[0]) + def test_references___conditional_annotations__(self): code = """ class i: [__conditional_annotations__ for x in y] """ self._check_in_scopes(code, raises=NameError) + def test_references___conditional_annotations___nested(self): + code = """ + class i: [lambda: __conditional_annotations__ for x in y] + """ + self._check_in_scopes(code, raises=NameError) + def test_references___class___enclosing(self): code = """ __class__ = 2 diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 08678119200d427..cc2e9b782a35022 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -4269,6 +4269,43 @@ def test_set_log_record_factory(self): man.setLogRecordFactory(expected) self.assertEqual(man.logRecordFactory, expected) + @threading_helper.requires_working_threading() + def test_getLogger_fast_path_never_returns_unwired_logger(self): + # getLogger()'s lock-free fast path returns a logger straight out of + # loggerDict, so a logger must be published there only after + # _fixupParents() has set its parent; otherwise a concurrent caller + # observes it detached from the hierarchy (gh-150818 follow-up). + manager = logging.Manager(logging.RootLogger(logging.WARNING)) + name = 'a.b.c' + + paused = threading.Event() + seen = [] + real_fixup = manager._fixupParents + + # Pause the creating thread between publishing rv and wiring its + # parent, then read loggerDict the way the fast path does and snapshot + # the parent at that instant (rv is wired in place soon after). + def fixup(alogger): + paused.set() + reader.join() + real_fixup(alogger) + + def read(): + paused.wait() + rv = manager.loggerDict.get(name) + if rv is not None and not isinstance(rv, logging.PlaceHolder): + seen.append(rv.parent) + + reader = threading.Thread(target=read) + manager._fixupParents = fixup + try: + reader.start() + manager.getLogger(name) + finally: + manager._fixupParents = real_fixup + + self.assertNotIn(None, seen) + class ChildLoggerTest(BaseTest): def test_child_loggers(self): r = logging.getLogger() @@ -6615,6 +6652,57 @@ def test_rollover(self): print(tf.read()) self.assertTrue(found, msg=msg) + @unittest.skipUnless(hasattr(os.stat_result, 'st_birthtime') or hasattr(os, 'statx'), + "st_birthtime and statx() not available or supported by Python on this OS") + @support.requires_resource('walltime') + def test_rollover_based_on_st_birthtime_only(self): + def add_record(message: str) -> None: + fh = logging.handlers.TimedRotatingFileHandler( + self.fn, when='S', interval=4, encoding="utf-8", backupCount=1) + fmt = logging.Formatter('%(asctime)s %(message)s') + fh.setFormatter(fmt) + record = logging.makeLogRecord({'msg': message}) + fh.emit(record) + fh.close() + + add_record('testing - initial') + self.assertLogFile(self.fn) + # Sleep a little over the half of rollover time - and this value + # must be over 2 seconds, since this is the mtime resolution on + # FAT32 filesystems. + time.sleep(2.1) + add_record('testing - update before rollover to renew the st_mtime') + time.sleep(2.1) # a little over the half of rollover time + add_record('testing - new record supposedly in the new file after rollover') + + # At this point, the log file should be rotated if the rotation + # is based on creation time but should be not if it's based on + # modification time. + found = False + now = datetime.datetime.now() + GO_BACK = 5 # seconds + for secs in range(GO_BACK + 1): + prev = now - datetime.timedelta(seconds=secs) + fn = self.fn + prev.strftime(".%Y-%m-%d_%H-%M-%S") + found = os.path.exists(fn) + if found: + self.rmfiles.append(fn) + break + msg = 'No rotated files found, went back %d seconds' % GO_BACK + if not found: + # print additional diagnostics + dn, fn = os.path.split(self.fn) + files = [f for f in os.listdir(dn) if f.startswith(fn)] + print('Test time: %s' % now.strftime("%Y-%m-%d %H-%M-%S"), file=sys.stderr) + print('The only matching files are: %s' % files, file=sys.stderr) + for f in files: + print('Contents of %s:' % f) + path = os.path.join(dn, f) + print(os.stat(path)) + with open(path, 'r') as tf: + print(tf.read()) + self.assertTrue(found, msg=msg) + def test_rollover_at_midnight(self, weekly=False): os_helper.unlink(self.fn) now = datetime.datetime.now() diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index 85ddf68b3f36efc..cc37697189af3e5 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -75,7 +75,7 @@ def parse_mtestfile(fname): -- starts a comment blank lines, or lines containing only a comment, are ignored other lines are expected to have the form - id fn arg -> expected [flag]* + id fn arg... -> expected [flag]* """ with open(fname, encoding="utf-8") as fp: @@ -87,12 +87,12 @@ def parse_mtestfile(fname): continue lhs, rhs = line.split('->') - id, fn, arg = lhs.split() + id, fn, *args = lhs.split() rhs_pieces = rhs.split() exp = rhs_pieces[0] flags = rhs_pieces[1:] - yield (id, fn, float(arg), float(exp), flags) + yield (id, fn, [float(arg) for arg in args], float(exp), flags) def parse_testfile(fname): @@ -2141,10 +2141,10 @@ def test_testfile(self): @requires_IEEE_754 def test_mtestfile(self): - fail_fmt = "{}: {}({!r}): {}" + fail_fmt = "{}: {}{!r}: {}" failures = [] - for id, fn, arg, expected, flags in parse_mtestfile(math_testcases): + for id, fn, args, expected, flags in parse_mtestfile(math_testcases): func = getattr(math, fn) if 'invalid' in flags or 'divide-by-zero' in flags: @@ -2153,7 +2153,7 @@ def test_mtestfile(self): expected = 'OverflowError' try: - got = func(arg) + got = func(*args) except ValueError: got = 'ValueError' except OverflowError: @@ -2176,7 +2176,7 @@ def test_mtestfile(self): # general. abs_tol = 1e-15 - elif fn == 'erfc' and arg >= 0.0: + elif fn == 'erfc' and (arg := args[0]) >= 0.0: # erfc has less-than-ideal accuracy for large # arguments (x ~ 25 or so), mainly due to the # error involved in computing exp(-x*x). @@ -2199,7 +2199,7 @@ def test_mtestfile(self): if failure is None: continue - msg = fail_fmt.format(id, fn, arg, failure) + msg = fail_fmt.format(id, fn, args, failure) failures.append(msg) if failures: diff --git a/Lib/test/test_mimetypes.py b/Lib/test/test_mimetypes.py index 1a3b49b87b121f2..19983fa3fa7628d 100644 --- a/Lib/test/test_mimetypes.py +++ b/Lib/test/test_mimetypes.py @@ -287,6 +287,50 @@ def test_case_sensitivity(self): eq(self.db.guess_file_type("foobar.tar.z"), (None, None)) eq(self.db.guess_type("scheme:foobar.tar.z"), (None, None)) + def test_suffix_map_case_sensitive_preferred(self): + self.db.suffix_map[".TEST-SUFFIX"] = ".tar.gz" + self.db.suffix_map[".test-suffix"] = ".tar.xz" + self.assertEqual( + self.db.guess_file_type("example.TEST-SUFFIX"), + ("application/x-tar", "gzip"), + ) + self.assertEqual( + self.db.guess_file_type("example.test-suffix"), + ("application/x-tar", "xz"), + ) + + def test_added_types_case_sensitive_preferred(self): + self.db.add_type("text/x-test-uppercase-r", ".R") + self.db.add_type("text/x-test-lowercase-r", ".r") + self.assertEqual( + self.db.guess_file_type("example.R"), + ("text/x-test-uppercase-r", None), + ) + self.assertEqual( + self.db.guess_file_type("example.r"), + ("text/x-test-lowercase-r", None), + ) + self.db.add_type("text/x-test-uppercase-non-strict", + ".NON-STRICT-EXT", strict=False) + self.db.add_type("text/x-test-lowercase-non-strict", + ".non-strict-ext", strict=False) + self.assertEqual( + self.db.guess_file_type("example.NON-STRICT-EXT"), + (None, None), + ) + self.assertEqual( + self.db.guess_file_type("example.non-strict-ext"), + (None, None), + ) + self.assertEqual( + self.db.guess_file_type("example.NON-STRICT-EXT", strict=False), + ("text/x-test-uppercase-non-strict", None), + ) + self.assertEqual( + self.db.guess_file_type("example.non-strict-ext", strict=False), + ("text/x-test-lowercase-non-strict", None), + ) + def test_default_data(self): eq = self.assertEqual eq(self.db.guess_file_type("foo.html"), ("text/html", None)) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py index 177fe45e8d97490..2e2ac147968dd4a 100644 --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -354,6 +354,8 @@ def test_find_end(self): self.assertEqual(m.find(b'one', 1, -1), 8) self.assertEqual(m.find(b'one', 1, -2), -1) self.assertEqual(m.find(bytearray(b'one')), 0) + self.assertEqual(m.find(b'', n + 1), -1) + self.assertEqual(m.rfind(b'', n + 1), -1) for i in range(-n-1, n+1): for j in range(-n-1, n+1): diff --git a/Lib/test/test_os/test_os.py b/Lib/test/test_os/test_os.py index 68cb32cd40be306..b88388e091312a0 100644 --- a/Lib/test/test_os/test_os.py +++ b/Lib/test/test_os/test_os.py @@ -3793,7 +3793,6 @@ async def test_trailers(self): @requires_headers_trailers @requires_32b async def test_headers_overflow_32bits(self): - self.server.handler_instance.accumulate = False with self.assertRaises(OSError) as cm: await self.async_sendfile(self.sockno, self.fileno, 0, 0, headers=[b"x" * 2**16] * 2**15) @@ -3802,7 +3801,6 @@ async def test_headers_overflow_32bits(self): @requires_headers_trailers @requires_32b async def test_trailers_overflow_32bits(self): - self.server.handler_instance.accumulate = False with self.assertRaises(OSError) as cm: await self.async_sendfile(self.sockno, self.fileno, 0, 0, trailers=[b"x" * 2**16] * 2**15) diff --git a/Lib/test/test_os/test_posix.py b/Lib/test/test_os/test_posix.py index 1395156539a1637..8e83fa21dae6e22 100644 --- a/Lib/test/test_os/test_posix.py +++ b/Lib/test/test_os/test_posix.py @@ -901,7 +901,9 @@ def check_stat(uid, gid): self.assertRaises(OSError, chown_func, first_param, 0, -1) check_stat(uid, gid) if hasattr(os, 'getgroups'): - if 0 not in os.getgroups(): + # Also check the effective gid, which the kernel + # accepts for chown even if not in getgroups(). + if 0 not in os.getgroups() and os.getegid() != 0: self.assertRaises(OSError, chown_func, first_param, -1, 0) check_stat(uid, gid) # test illegal types diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 9ee97b922ad48e1..63c130813ec4972 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -534,7 +534,7 @@ def test_ios_ver(self): def test_libc_ver(self): if support.is_emscripten: - assert platform.libc_ver() == ("emscripten", "4.0.12") + assert platform.libc_ver() == ("emscripten", "4.0.19") return # check that libc_ver(executable) doesn't raise an exception if os.path.isdir(sys.executable) and \ diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py index 390a1479fdd2975..1ab31af67fec522 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_collectors.py @@ -11,6 +11,7 @@ try: import _remote_debugging # noqa: F401 + from profiling.sampling import gecko_collector from profiling.sampling.pstats_collector import PstatsCollector from profiling.sampling.stack_collector import ( CollapsedStackCollector, @@ -59,6 +60,42 @@ def find_child_by_name(children, strings, substr): return None +def export_gecko_profile(testcase, collector): + gecko_out = tempfile.NamedTemporaryFile(suffix=".json", delete=False) + testcase.addCleanup(close_and_unlink, gecko_out) + # We cannot overwrite an open file on Windows. + gecko_out.close() + + with captured_stdout(), captured_stderr(): + collector.export(gecko_out.name) + + testcase.assertGreater(os.path.getsize(gecko_out.name), 0) + with open(gecko_out.name, encoding="utf-8") as file: + return json.load(file) + + +def assert_gecko_column_lengths(testcase, table, columns): + expected = table["length"] + for column in columns: + testcase.assertEqual( + len(table[column]), expected, + f"{column!r} has wrong length", + ) + + +def gecko_marker_names(profile, markers): + string_array = profile["shared"]["stringArray"] + return [string_array[idx] for idx in markers["name"]] + + +def gecko_opcode_marker_data(profile): + markers = profile["threads"][0]["markers"] + return [ + data for data in markers["data"] + if data.get("type") == "Opcode" + ] + + class TestSampleProfilerComponents(unittest.TestCase): """Unit tests for individual profiler components.""" @@ -583,9 +620,10 @@ def test_gecko_collector_basic(self): # Verify samples samples = thread_data["samples"] - self.assertEqual(len(samples["stack"]), 1) - self.assertEqual(len(samples["time"]), 1) self.assertEqual(samples["length"], 1) + assert_gecko_column_lengths( + self, samples, ("stack", "time", "eventDelay") + ) # Verify function table structure and content func_table = thread_data["funcTable"] @@ -622,9 +660,6 @@ def test_gecko_collector_basic(self): @unittest.skipIf(is_emscripten, "threads not available") def test_gecko_collector_export(self): """Test Gecko profile export functionality.""" - gecko_out = tempfile.NamedTemporaryFile(suffix=".json", delete=False) - self.addCleanup(close_and_unlink, gecko_out) - collector = GeckoCollector(1000) test_frames1 = [ @@ -657,17 +692,7 @@ def test_gecko_collector_export(self): collector.collect(test_frames2) collector.collect(test_frames3) - # Export gecko profile - with captured_stdout(), captured_stderr(): - collector.export(gecko_out.name) - - # Verify file was created and contains valid data - self.assertTrue(os.path.exists(gecko_out.name)) - self.assertGreater(os.path.getsize(gecko_out.name), 0) - - # Check file contains valid JSON - with open(gecko_out.name, "r") as f: - profile_data = json.load(f) + profile_data = export_gecko_profile(self, collector) # Should be valid Gecko profile format self.assertIn("meta", profile_data) @@ -688,6 +713,100 @@ def test_gecko_collector_export(self): self.assertIn("func2", string_array) self.assertIn("other_func", string_array) + thread_data = profile_data["threads"][0] + assert_gecko_column_lengths( + self, thread_data["samples"], ("stack", "time", "eventDelay") + ) + + @unittest.skipIf(is_emscripten, "threads not available") + def test_gecko_collector_export_after_spill_flush(self): + """Test Gecko profile export after spill buffers flush to disk.""" + old_buffer_bytes = gecko_collector.DEFAULT_SPILL_BUFFER_BYTES + gecko_collector.DEFAULT_SPILL_BUFFER_BYTES = 1 + self.addCleanup( + setattr, gecko_collector, "DEFAULT_SPILL_BUFFER_BYTES", + old_buffer_bytes + ) + + collector = GeckoCollector(1000) + test_frames = [ + MockInterpreterInfo( + 0, + [ + MockThreadInfo( + 1, + [MockFrameInfo("file.py", 10, "func")], + status=THREAD_STATUS_HAS_GIL, + ) + ], + ) + ] + collector.collect(test_frames, timestamps_us=[1000, 2000, 3000]) + + profile_data = export_gecko_profile(self, collector) + samples = profile_data["threads"][0]["samples"] + self.assertEqual(samples["length"], 3) + assert_gecko_column_lengths( + self, samples, ("stack", "time", "eventDelay") + ) + + @unittest.skipIf(is_emscripten, "threads not available") + def test_gecko_collector_rejects_collect_after_export(self): + collector = GeckoCollector(1000) + test_frames = [ + MockInterpreterInfo( + 0, + [ + MockThreadInfo( + 1, + [MockFrameInfo("file.py", 10, "func")], + status=THREAD_STATUS_HAS_GIL, + ) + ], + ) + ] + collector.collect(test_frames) + export_gecko_profile(self, collector) + + with self.assertRaisesRegex(RuntimeError, "after export"): + collector.collect(test_frames) + + @unittest.skipIf(is_emscripten, "threads not available") + def test_gecko_collector_export_failure_keeps_existing_file(self): + collector = GeckoCollector(1000) + test_frames = [ + MockInterpreterInfo( + 0, + [ + MockThreadInfo( + 1, + [MockFrameInfo("file.py", 10, "func")], + status=THREAD_STATUS_HAS_GIL, + ) + ], + ) + ] + collector.collect(test_frames) + + with tempfile.TemporaryDirectory() as temp_dir: + filename = os.path.join(temp_dir, "profile.json") + with open(filename, "w", encoding="utf-8") as file: + file.write("existing") + + before = set(os.listdir(temp_dir)) + + def fail(file): + raise OSError("boom") + + collector._stream_profile = fail + with captured_stdout(), captured_stderr(): + with self.assertRaisesRegex(OSError, "boom"): + collector.export(filename) + + with open(filename, encoding="utf-8") as file: + self.assertEqual(file.read(), "existing") + self.assertEqual(set(os.listdir(temp_dir)), before) + def test_gecko_collector_markers(self): """Test Gecko profile markers for GIL and CPU state tracking.""" collector = GeckoCollector(1000) @@ -771,21 +890,16 @@ def test_gecko_collector_markers(self): self.assertIn("markers", thread_data) markers = thread_data["markers"] - # Should have marker arrays - self.assertIn("name", markers) - self.assertIn("startTime", markers) - self.assertIn("endTime", markers) - self.assertIn("category", markers) self.assertGreater( markers["length"], 0, "Should have generated markers" ) - - # Get marker names from string table - string_array = profile_data["shared"]["stringArray"] - marker_names = [string_array[idx] for idx in markers["name"]] + assert_gecko_column_lengths( + self, markers, + ("data", "name", "startTime", "endTime", "phase", "category"), + ) # Verify we have different marker types - marker_name_set = set(marker_names) + marker_name_set = set(gecko_marker_names(profile_data, markers)) # Should have "Has GIL" markers (when thread had GIL) self.assertIn( @@ -2659,6 +2773,7 @@ def test_gecko_collector_opcodes_enabled(self): def test_gecko_opcode_state_tracking(self): """Test that GeckoCollector tracks opcode state changes.""" collector = GeckoCollector(sample_interval_usec=1000, opcodes=True) + self.addCleanup(collector._cleanup_spills) # First sample with opcode 90 (RAISE_VARARGS) frame1 = MockFrameInfo("test.py", 10, "func", opcode=90) @@ -2702,10 +2817,28 @@ def test_gecko_opcode_state_change_emits_marker(self): collector.collect(frames2) # Should have emitted a marker for the first opcode - thread_data = collector.threads[1] - markers = thread_data["markers"] - # At least one marker should have been added - self.assertGreater(len(markers["name"]), 0) + profile = collector._build_profile() + markers = profile["threads"][0]["markers"] + assert_gecko_column_lengths( + self, markers, + ("data", "name", "startTime", "endTime", "phase", "category"), + ) + opcode_markers = gecko_opcode_marker_data(profile) + self.assertIn( + { + "opcode": 90, + "line": 10, + "function": "func", + }, + [ + { + "opcode": marker["opcode"], + "line": marker["line"], + "function": marker["function"], + } + for marker in opcode_markers + ], + ) def test_gecko_opcode_markers_not_emitted_when_disabled(self): """Test that no opcode markers when opcodes=False.""" @@ -2729,8 +2862,9 @@ def test_gecko_opcode_markers_not_emitted_when_disabled(self): ] collector.collect(frames2) - # opcode_state should not be tracked - self.assertEqual(len(collector.opcode_state), 0) + profile = collector._build_profile() + self.assertEqual(gecko_opcode_marker_data(profile), []) + self.assertEqual(profile["meta"]["markerSchema"], []) def test_gecko_opcode_with_none_opcode(self): """Test that None opcode doesn't cause issues.""" @@ -2746,9 +2880,8 @@ def test_gecko_opcode_with_none_opcode(self): ] collector.collect(frames) - # Should track the state but opcode is None - self.assertIn(1, collector.opcode_state) - self.assertIsNone(collector.opcode_state[1][0]) + profile = collector._build_profile() + self.assertEqual(gecko_opcode_marker_data(profile), []) class TestCollectorFrameFormat(unittest.TestCase): diff --git a/Lib/test/test_profiling/test_sampling_profiler/test_live_collector_ui.py b/Lib/test/test_profiling/test_sampling_profiler/test_live_collector_ui.py index 59373a8d00c03cf..ae4ee969f34d8b3 100644 --- a/Lib/test/test_profiling/test_sampling_profiler/test_live_collector_ui.py +++ b/Lib/test/test_profiling/test_sampling_profiler/test_live_collector_ui.py @@ -825,17 +825,34 @@ def test_get_all_lines_full_display(self): class TestLiveModeErrors(unittest.TestCase): """Tests running error commands in the live mode fails gracefully.""" + class QuitWhenFinishedDisplay(MockDisplay): + def __init__(self, collector): + super().__init__() + self.collector = collector + + def get_input(self): + ch = super().get_input() + if ch != -1: + return ch + # Sampling only stops once the target process has exited, at + # which point the collector is marked finished. Quit then so the + # run can surface the target's stderr. We must not rely on the + # target's pid still being signalable: once it exits it lingers + # as a zombie (it is reaped after sample_live returns), so a + # liveness check would never observe it gone and would hang. + if self.collector.finished: + return ord('q') + return -1 + def mock_curses_wrapper(self, func): func(mock.MagicMock()) def mock_init_curses_side_effect(self, n_times, mock_self, stdscr): - mock_self.display = MockDisplay() - # Allow the loop to run for a bit (approx 0.5s) before quitting - # This ensures we don't exit too early while the subprocess is - # still failing + mock_self.display = self.QuitWhenFinishedDisplay(mock_self) + # Feed non-input events so live mode keeps polling while the target + # process is still running; once it exits the display quits on its own. for _ in range(n_times): mock_self.display.simulate_input(-1) - mock_self.display.simulate_input(ord('q')) def test_run_failed_module_live(self): """Test that running a existing module that fails exits with clean error.""" diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py index da2d630d7ace7bb..09113e983fcd94d 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -327,6 +327,12 @@ def test_bad_syntax_with_quiet(self): self.assertEqual(stdout, b'') self.assertEqual(stderr, b'') + def test_bad_syntax_stderr_ends_with_newline(self): + with open(self.source_path, 'w') as file: + file.write(' print("hello world")\n') + rc, stdout, stderr = self.pycompilecmd_failure(self.source_path) + self.assertTrue(stderr.endswith(b'\n')) + def test_file_not_exists(self): should_not_exists = os.path.join(os.path.dirname(__file__), 'should_not_exists.py') rc, stdout, stderr = self.pycompilecmd_failure(self.source_path, should_not_exists) diff --git a/Lib/test/test_pydoc/longsummary.py b/Lib/test/test_pydoc/longsummary.py new file mode 100644 index 000000000000000..0e566d33454119b --- /dev/null +++ b/Lib/test/test_pydoc/longsummary.py @@ -0,0 +1,29 @@ +class C: + """This is a class summary that consists of a very long single line, exceeding the recommended PEP 8 limit. + + The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + """ + def meth(self): + """This is a method summary that consists of a very long single line, exceeding the recommended PEP 8 limit. + + The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + """ + + @property + def prop(self): + """This is a property summary that consists of a very long single line, exceeding the recommended PEP 8 limit. + + The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + """ + +def func(self): + """This is a function summary that consists of a very long single line, exceeding the recommended PEP 8 limit. + + The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + """ + +data = C() +data.__doc__ = """This is a data summary that consists of a very long single line, exceeding the recommended PEP 8 limit. + +The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. +""" diff --git a/Lib/test/test_pydoc/test_pydoc.py b/Lib/test/test_pydoc/test_pydoc.py index 5cd26923f75c311..5543c664528e6c8 100644 --- a/Lib/test/test_pydoc/test_pydoc.py +++ b/Lib/test/test_pydoc/test_pydoc.py @@ -1245,6 +1245,71 @@ def function_with_really_long_name_so_annotations_can_be_rather_small( lambda very_long_parameter_name_that_should_not_fit_into_a_single_line, second_very_long_parameter_name ''' % __name__) + @requires_docstrings + def test_long_summaries(self): + from . import longsummary + doc = pydoc.render_doc(longsummary) + doc = clean_text(doc) + self.assertEqual(doc, '''Python Library Documentation: module test.test_pydoc.longsummary in test.test_pydoc + +NAME + test.test_pydoc.longsummary + +CLASSES + builtins.object + C + + class C(builtins.object) + | This is a class summary that consists of a very long single line, + | exceeding the recommended PEP 8 limit. + | + | The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + | + | Methods defined here: + | + | meth(self) + | This is a method summary that consists of a very long single line, + | exceeding the recommended PEP 8 limit. + | + | The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + | + | ---------------------------------------------------------------------- + | Readonly properties defined here: + | + | prop + | This is a property summary that consists of a very long single line, + | exceeding the recommended PEP 8 limit. + | + | The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + | + | ---------------------------------------------------------------------- + | Data descriptors defined here: + | + | __dict__ + | dictionary for instance variables + | + | __weakref__ + | list of weak references to the object + +FUNCTIONS + func(self) + This is a function summary that consists of a very long single line, + exceeding the recommended PEP 8 limit. + + The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + +DATA + data = + This is a data summary that consists of a very long single line, + exceeding the recommended PEP 8 limit. + + The rest of the docstring body, separated from the summary by a blank line, can also contain very long lines. + +FILE + %s + +''' % inspect.getabsfile(longsummary)) + def test__future__imports(self): # __future__ features are excluded from module help, # except when it's the __future__ module itself diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py index 060a509c1bd1c7a..42309dd8f6c1903 100644 --- a/Lib/test/test_pyexpat.py +++ b/Lib/test/test_pyexpat.py @@ -876,7 +876,7 @@ def test_change_size_2(self): @support.requires_resource('cpu') @support.requires_resource('walltime') @support.bigmemtest(size=2**31, memuse=4, dry_run=False) - def test_large_character_data_does_not_crash(self): + def test_large_character_data_does_not_crash(self, size): # See https://github.com/python/cpython/issues/148441 parser = expat.ParserCreate() parser.buffer_text = True diff --git a/Lib/test/test_pyrepl/test_utils.py b/Lib/test/test_pyrepl/test_utils.py index 3c55b6bdaeee9e8..ebbd06213c69aff 100644 --- a/Lib/test/test_pyrepl/test_utils.py +++ b/Lib/test/test_pyrepl/test_utils.py @@ -125,6 +125,30 @@ def test_gen_colors_keyword_highlighting(self): ("import", "keyword"), ], ), + ( + "case +1", + [ + ("case", "soft_keyword"), + ("+", "op"), + ("1", "number"), + ], + ), + ( + "match +1", + [ + ("match", "soft_keyword"), + ("+", "op"), + ("1", "number"), + ], + ), + ( + "match -1", + [ + ("match", "soft_keyword"), + ("-", "op"), + ("1", "number"), + ], + ), ] for code, expected_highlights in cases: with self.subTest(code=code): diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py index e6d727d417b2985..c0b5a4da8cb2569 100644 --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -107,19 +107,35 @@ def test_excessive_getattr(self): # we use __dir__ and __getattr__ in class Foo to create a "magic" # class attribute 'bar'. This forces `getattr` to call __getattr__ # (which is doesn't necessarily do). - class Foo: + # Test 1: Attribute returns None + class FooReturnsNone: calls = 0 - bar = '' + bar = None def __getattribute__(self, name): if name == 'bar': self.calls += 1 return None return super().__getattribute__(name) - f = Foo() - completer = rlcompleter.Completer(dict(f=f)) - self.assertEqual(completer.complete('f.b', 0), 'f.bar') - self.assertEqual(f.calls, 1) + f1 = FooReturnsNone() + completer1 = rlcompleter.Completer(dict(f=f1)) + self.assertEqual(completer1.complete('f.b', 0), 'f.bar') + self.assertEqual(f1.calls, 1) + + # Test 2: Attribute returns non-None value + class FooReturnsValue: + calls = 0 + bar = '' + def __getattribute__(self, name): + if name == 'bar': + self.calls += 1 + return '' + return super().__getattribute__(name) + + f2 = FooReturnsValue() + completer2 = rlcompleter.Completer(dict(f=f2)) + self.assertEqual(completer2.complete('f.b', 0), 'f.bar') + self.assertEqual(f2.calls, 1) def test_property_method_not_called(self): class Foo: @@ -196,6 +212,7 @@ class Foo: completer = rlcompleter.Completer(dict(f=Foo())) self.assertEqual(completer.complete('f.', 0), 'f.bar') + @unittest.mock.patch('rlcompleter._readline_available', False) def test_complete(self): completer = rlcompleter.Completer() diff --git a/Lib/test/test_shlex.py b/Lib/test/test_shlex.py index 2a355abdeeb30fb..2adaee81b063085 100644 --- a/Lib/test/test_shlex.py +++ b/Lib/test/test_shlex.py @@ -342,6 +342,14 @@ def testQuote(self): self.assertRaises(TypeError, shlex.quote, 42) self.assertRaises(TypeError, shlex.quote, b"abc") + def testForceQuote(self): + self.assertEqual(shlex.quote("spam"), "spam") + self.assertEqual(shlex.quote("spam", force=False), "spam") + self.assertEqual(shlex.quote("spam", force=True), "'spam'") + self.assertEqual(shlex.quote("spam eggs", force=False), "'spam eggs'") + self.assertEqual(shlex.quote("spam eggs", force=True), "'spam eggs'") + self.assertEqual(shlex.quote("two's-complement", force=False), "'two'\"'\"'s-complement'") + def testJoin(self): for split_command, command in [ (['a ', 'b'], "'a ' b"), diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 59cb319b0a95b5e..bb901220fb408c1 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -2914,6 +2914,23 @@ def test_destinsrc_false_positive(self): finally: os_helper.rmtree(TESTFN) + @os_helper.skip_unless_symlink + def test_destinsrc_symlink_bypass(self): + tmp = self.mkdtemp() + src = os.path.join(tmp, 'src') + os.makedirs(src) + # tmp/link -> tmp (one level up) + link = os.path.join(tmp, 'link') + os.symlink(tmp, link) + # raw path: tmp/link/src/sub - no src prefix in string space + # real path: tmp/src/sub - physically inside src + dst = os.path.join(link, 'src', 'sub') + self.assertTrue( + shutil._destinsrc(src, dst), + msg='_destinsrc failed to detect dst inside src via symlink ' + '(dst=%s, src=%s)' % (dst, src), + ) + @os_helper.skip_unless_symlink @mock_rename def test_move_file_symlink(self): diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index 5fd65ad999210e4..bcb51ed7d8476a8 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -233,6 +233,20 @@ def test_addsitedir_hidden_file_attribute(self): self.assertNotIn(site.makepath(pth_file.good_dir_path)[0], sys.path) self.assertIn(pth_file.base_dir, sys.path) + def test_sitedir_variable(self): + # gh-149671: setuptools use of `-nspkg.pth` files in Python < 3.15. + code = '; '.join(( + # Code used by "-nspkg.pth" files generated by setuptools. + "import sys", + "sitedir = sys._getframe(1).f_locals['sitedir']", + "print(sitedir)", + )) + pth_dir, pth_fn = self.make_pth(code) + with support.captured_stdout() as stdout: + known_paths = site.addpackage(pth_dir, pth_fn, set()) + sitedir = stdout.getvalue().rstrip() + self.assertEqual(sitedir, pth_dir) + # This tests _getuserbase, hence the double underline # to distinguish from a test for getuserbase def test__getuserbase(self): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 94325f5a8003d97..63c465e3bfea16d 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -7529,6 +7529,62 @@ def detach(): pass +class ReentrantMutationTests(unittest.TestCase): + """Regression tests for re-entrant mutation in sendmsg/recvmsg_into. + + These tests verify that mutating sequences during argument parsing + via __buffer__ protocol does not cause crashes. + + See: https://github.com/python/cpython/issues/143988 + """ + + @unittest.skipUnless(hasattr(socket.socket, "sendmsg"), + "sendmsg not supported") + def test_sendmsg_reentrant_data_mutation(self): + seq = [] + + class MutBuffer: + def __init__(self): + self.tripped = False + + def __buffer__(self, flags): + if not self.tripped: + self.tripped = True + seq.clear() + return memoryview(b'Hello') + + seq = [MutBuffer(), b'World', b'Test'] + + left, right = socket.socketpair() + with left, right: + left.sendmsg(seq) + self.assertEqual(right.recv(1024), b'HelloWorldTest') + + @unittest.skipUnless(hasattr(socket.socket, "recvmsg_into"), + "recvmsg_into not supported") + def test_recvmsg_into_reentrant_buffer_mutation(self): + seq = [] + buf1 = bytearray(100) + + class MutBuffer: + def __init__(self): + self.tripped = False + + def __buffer__(self, flags): + if not self.tripped: + self.tripped = True + seq.clear() + return memoryview(buf1) + + seq = [MutBuffer(), bytearray(100), bytearray(100)] + + left, right = socket.socketpair() + with left, right: + left.send(b'Hello World!') + right.recvmsg_into(seq) + self.assertEqual(buf1, b'Hello World!'.ljust(100, b'\x00')) + + def setUpModule(): thread_info = threading_helper.threading_setup() unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info) diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 8ac64b3105708f7..53fffe7cfb56d09 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -387,8 +387,7 @@ def test_utf8_non_utf8_third_line_error(self): b'#third\xa4\n' b'raise RuntimeError\n') self.check_script_error(src, - br"'utf-8' codec can't decode byte|" - br"encoding problem: utf8") + br"'utf-8' codec can't decode byte") def test_crlf(self): src = (b'print(ascii("""\r\n"""))\n') @@ -540,6 +539,20 @@ def check_script_error(self, src, expected, lineno=...): line = line.removeprefix('\ufeff') self.assertIn(line.encode(), err) + def test_coding_spec_unknown_encoding(self): + src = (b'# coding: c1252\n' + b'print("Hi!")\n') + self.check_script_error(src, br"unknown encoding: c1252") + + def test_coding_spec_decode_error(self): + src = (b'# coding: shift-jis\n' + b'print("\xc4\x85")\n') + self.check_script_error(src, br"'shift_jis' codec can't decode byte") + + def test_coding_spec_non_text_encoding(self): + src = (b'# coding: hex_codec\n' + b'print("eggs")\n') + self.check_script_error(src, br"'hex_codec' is not a text encoding") if __name__ == "__main__": diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 73b40e82a96811f..5f6cb527955ca17 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -1400,6 +1400,18 @@ def test_blob_set_empty_slice(self): self.blob[0:0] = b"" self.assertEqual(self.blob[:], self.data) + def test_blob_set_empty_slice_wrong_type(self): + with self.assertRaises(TypeError): + self.blob[5:5] = None + + def test_blob_set_empty_slice_wrong_size(self): + with self.assertRaisesRegex(IndexError, "wrong size"): + self.blob[5:5] = b"123" + + def test_blob_set_empty_slice_correct(self): + self.blob[5:5] = b"" + self.assertEqual(self.blob[:], self.data) + def test_blob_set_slice_with_skip(self): self.blob[0:10:2] = b"12345" actual = self.cx.execute("select b from test").fetchone()[0] diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 4f998ef2b02a69a..40111d410077950 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -59,10 +59,7 @@ CAN_GET_SELECTED_OPENSSL_SIGALG = ssl.OPENSSL_VERSION_INFO >= (3, 5) PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') -HAS_KEYLOG = hasattr(ssl.SSLContext, 'keylog_filename') -requires_keylog = unittest.skipUnless( - HAS_KEYLOG, 'test requires OpenSSL 1.1.1 with keylog callback') -CAN_SET_KEYLOG = HAS_KEYLOG and os.name != "nt" +CAN_SET_KEYLOG = (os.name != "nt") requires_keylog_setter = unittest.skipUnless( CAN_SET_KEYLOG, "cannot set 'keylog_filename' on Windows" @@ -5453,7 +5450,6 @@ def keylog_lines(self, fname=os_helper.TESTFN): with open(fname) as f: return len(list(f)) - @requires_keylog def test_keylog_defaults(self): self.addCleanup(os_helper.unlink, os_helper.TESTFN) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) @@ -5481,7 +5477,6 @@ def test_keylog_defaults(self): with self.assertRaises(TypeError): ctx.keylog_filename = 1 - @requires_keylog def test_keylog_filename(self): self.addCleanup(os_helper.unlink, os_helper.TESTFN) client_context, server_context, hostname = testing_context() @@ -5522,7 +5517,6 @@ def test_keylog_filename(self): client_context.keylog_filename = None server_context.keylog_filename = None - @requires_keylog @unittest.skipIf(sys.flags.ignore_environment, "test is not compatible with ignore_environment") def test_keylog_env(self): diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index f944084aaa6d6aa..d41cb1294a3dafe 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -3719,8 +3719,9 @@ def test_startupinfo(self): # Since Python is a console process, it won't be affected # by wShowWindow, but the argument should be silently # ignored - subprocess.call(ZERO_RETURN_CMD, - startupinfo=startupinfo) + rc = subprocess.call(ZERO_RETURN_CMD, + startupinfo=startupinfo) + self.assertEqual(rc, 0) def test_startupinfo_keywords(self): # startupinfo argument @@ -3735,8 +3736,9 @@ def test_startupinfo_keywords(self): # Since Python is a console process, it won't be affected # by wShowWindow, but the argument should be silently # ignored - subprocess.call(ZERO_RETURN_CMD, - startupinfo=startupinfo) + rc = subprocess.call(ZERO_RETURN_CMD, + startupinfo=startupinfo) + self.assertEqual(rc, 0) def test_startupinfo_copy(self): # bpo-34044: Popen must not modify input STARTUPINFO structure @@ -3853,14 +3855,16 @@ def test_close_fds_with_stdio(self): def test_empty_attribute_list(self): startupinfo = subprocess.STARTUPINFO() startupinfo.lpAttributeList = {} - subprocess.call(ZERO_RETURN_CMD, - startupinfo=startupinfo) + rc = subprocess.call(ZERO_RETURN_CMD, + startupinfo=startupinfo) + self.assertEqual(rc, 0) def test_empty_handle_list(self): startupinfo = subprocess.STARTUPINFO() startupinfo.lpAttributeList = {"handle_list": []} - subprocess.call(ZERO_RETURN_CMD, - startupinfo=startupinfo) + rc = subprocess.call(ZERO_RETURN_CMD, + startupinfo=startupinfo) + self.assertEqual(rc, 0) def test_shell_sequence(self): # Run command through the shell (sequence) @@ -3871,6 +3875,8 @@ def test_shell_sequence(self): env=newenv) with p: self.assertIn(b"physalis", p.stdout.read()) + p.communicate() + self.assertEqual(p.returncode, 0) def test_shell_string(self): # Run command through the shell (string) @@ -3881,6 +3887,8 @@ def test_shell_string(self): env=newenv) with p: self.assertIn(b"physalis", p.stdout.read()) + p.communicate() + self.assertEqual(p.returncode, 0) def test_shell_encodings(self): # Run command through the shell (string) @@ -3893,6 +3901,8 @@ def test_shell_encodings(self): encoding=enc) with p: self.assertIn("physalis", p.stdout.read(), enc) + p.communicate() + self.assertEqual(p.returncode, 0) def test_call_string(self): # call() function with string argument on Windows diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 02c70403185f60d..f40da0b79aa4790 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1349,6 +1349,26 @@ def test_pystats(self): def test_disable_gil_abi(self): self.assertEqual('t' in sys.abiflags, support.Py_GIL_DISABLED) + def test_int_max_str_digits(self): + old_limit = sys.get_int_max_str_digits() + self.assertIsInstance(old_limit, int) + self.assertGreaterEqual(old_limit, 0) + self.addCleanup(sys.set_int_max_str_digits, old_limit) + + sys.set_int_max_str_digits(0) + self.assertEqual(sys.get_int_max_str_digits(), 0) + + sys.set_int_max_str_digits(2_048) + self.assertEqual(sys.get_int_max_str_digits(), 2_048) + + with self.assertRaises(ValueError): + # the minimum is 640 digits + sys.set_int_max_str_digits(5) + with self.assertRaises(ValueError): + sys.set_int_max_str_digits(-2) + with self.assertRaises(TypeError): + sys.set_int_max_str_digits(2_048.0) + @test.support.cpython_only @test.support.force_not_colorized_test_class diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index d1831d68f0281d9..7583b61480e3709 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -427,6 +427,11 @@ def test_help_text(self): self.assertEqual(res.out, b'') self.assertIn(b'pygettext -- Python equivalent of xgettext(1)', res.err) + def test_version_text(self): + """Test that the version text is displayed.""" + res = assert_python_ok(self.script, '--version') + self.assertIn(b'pygettext.py (xgettext for Python) 1.5', res.out) + def test_error_messages(self): """Test that pygettext outputs error messages to stderr.""" stderr = self.get_stderr(dedent('''\ diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py index 7dc3364561d8a11..e38d0942e463e9c 100644 --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -206,7 +206,7 @@ def test_recursion_error_during_traceback(self): sys.setrecursionlimit(15) def f(): - ref(lambda: 0, []) + ref(lambda: 0, ord) f() try: @@ -1815,6 +1815,18 @@ class TestKeywordTypoSuggestions(unittest.TestCase): ("[x for x\nin range(3)\nof x]", "if"), ("[123 fur x\nin range(3)\nif x]", "for"), ("for x im n:\n pass", "in"), + ("mach x:", "match"), + ("math x:", "match"), + ("match 1:\n cse 1:", "case"), + ("typ x = int", "type"), + ("typed x = int", "type"), + ("lazi import x", "lazy"), + ("lezi import x", "lazy"), + ("switch x:\n case:", "match"), + ("delete x", "del"), + ("function f():", "def"), + ("func f():", "def"), + ("void f():", "def"), ] def test_keyword_suggestions_from_file(self): diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index ad644bb31288098..042604ed7c1a423 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -5848,6 +5848,27 @@ def foo(x: T): foo(42) + def test_genericalias_instance_isclass(self): + # test against user-defined generic classes + T = TypeVar('T') + + class Node(Generic[T]): + def __init__(self, label: T, + left: 'Node[T] | None' = None, + right: 'Node[T] | None' = None): + self.label = label + self.left = left + self.right = right + + self.assertTrue(inspect.isclass(Node)) + self.assertFalse(inspect.isclass(Node[int])) + self.assertFalse(inspect.isclass(Node[str])) + + # test against standard generic classes + self.assertFalse(inspect.isclass(set[int])) + self.assertFalse(inspect.isclass(list[bytes])) + self.assertFalse(inspect.isclass(dict[str, str])) + def test_implicit_any(self): T = TypeVar('T') diff --git a/Lib/test/test_unittest/test_loader.py b/Lib/test/test_unittest/test_loader.py index cdff6d1a20c8dfd..f4e50a3dccb2bc2 100644 --- a/Lib/test/test_unittest/test_loader.py +++ b/Lib/test/test_unittest/test_loader.py @@ -1,3 +1,4 @@ +import abc import functools import sys import types @@ -98,6 +99,22 @@ def test_loadTestsFromTestCase__from_FunctionTestCase(self): self.assertIsInstance(suite, loader.suiteClass) self.assertEqual(list(suite), []) + # "Do not load any tests from a TestCase-derived class that is an abstract + # base class." + def test_loadTestsFromTestCase__from_abc_TestCase(self): + class FooBase(unittest.TestCase, metaclass=abc.ABCMeta): + @abc.abstractmethod + def test(self): ... + class Foo(FooBase): + def test(self): pass + + empty_suite = unittest.TestSuite() + + loader = unittest.TestLoader() + suite = loader.loadTestsFromTestCase(Foo) + self.assertEqual(loader.loadTestsFromTestCase(FooBase), empty_suite) + self.assertEqual(list(suite), [Foo('test')]) + ################################################################ ### /Tests for TestLoader.loadTestsFromTestCase @@ -252,6 +269,24 @@ def load_tests(loader, tests, pattern): self.assertRaisesRegex(TypeError, "some failure", test.m) + # Check that loadTestsFromModule skips abstract base classes derived from + # TestCase, which can't be instantiated. + def test_loadTestsFromModule__skip_abc_TestCase(self): + m = types.ModuleType('m') + class MyTestCaseBase(unittest.TestCase, metaclass=abc.ABCMeta): + @abc.abstractmethod + def test(self): + ... + class MyTestCase(MyTestCaseBase): + def test(self): + pass + m.testcase_1 = MyTestCaseBase + m.testcase_2 = MyTestCase + loader = unittest.TestLoader() + suite = loader.loadTestsFromModule(m) + expected = [loader.suiteClass([MyTestCase('test')])] + self.assertEqual(list(suite), expected) + ################################################################ ### /Tests for TestLoader.loadTestsFromModule() @@ -1052,6 +1087,22 @@ def test_loadTestsFromNames__module_not_loaded(self): if module_name in sys.modules: del sys.modules[module_name] + # "The specifier should not refer to a test method in a TestCase-derived + # subclass that is an abstract base class" + def test_loadTestsFromNames__testmethod_in_abc_TestCase(self): + m = types.ModuleType('m') + class Foo(unittest.TestCase, metaclass=abc.ABCMeta): + @abc.abstractmethod + def test_1(self): ... + def test_2(self): pass + m.Foo = Foo + + loader = unittest.TestLoader() + for name in 'Foo.test_1', 'Foo.test_2': + with self.subTest(name=name), self.assertRaisesRegex(TypeError, + "Cannot instantiate abstract test case Foo"): + loader.loadTestsFromNames([name], m) + ################################################################ ### /Tests for TestLoader.loadTestsFromNames() diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 1ff5d7cf0c51dd8..0c6cd1b196ac812 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -593,6 +593,51 @@ def test_unicode_in_batch_file(self): ) self.assertEqual(out.strip(), '0') + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') + def test_activate_bat_respects_disable_prompt(self): + rmtree(self.env_dir) + env_dir = os.path.join(os.path.realpath(self.env_dir), 'venv') + builder = venv.EnvBuilder(clear=True) + builder.create(env_dir) + activate = os.path.join(env_dir, self.bindir, 'activate.bat') + test_batch = os.path.join(self.env_dir, 'test_disable_prompt.bat') + with open(test_batch, "w") as f: + f.write('@echo off\n' + 'set "PROMPT=base$G"\n' + 'set "VIRTUAL_ENV_DISABLE_PROMPT=1"\n' + f'call "{activate}"\n' + 'echo ACTIVE_PROMPT:%PROMPT%\n' + 'echo VIRTUAL_ENV:%VIRTUAL_ENV%\n' + 'set "PROMPT=changed$G"\n' + 'call deactivate\n' + 'echo FINAL_PROMPT:%PROMPT%\n') + out, err = check_output([test_batch]) + lines = out.splitlines() + self.assertEqual(lines[0], b'ACTIVE_PROMPT:base$G') + self.assertEndsWith(lines[1], os.fsencode(env_dir)) + self.assertEqual(lines[2], b'FINAL_PROMPT:changed$G') + + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') + def test_activate_bat_prefixes_prompt_by_default(self): + rmtree(self.env_dir) + env_dir = os.path.join(os.path.realpath(self.env_dir), 'venv') + builder = venv.EnvBuilder(clear=True) + builder.create(env_dir) + activate = os.path.join(env_dir, self.bindir, 'activate.bat') + test_batch = os.path.join(self.env_dir, 'test_enable_prompt.bat') + with open(test_batch, "w") as f: + f.write('@echo off\n' + 'set "PROMPT=base) $G"\n' + 'set "VIRTUAL_ENV_DISABLE_PROMPT="\n' + f'call "{activate}"\n' + 'echo ACTIVE_PROMPT:%PROMPT%\n' + 'call deactivate\n' + 'echo FINAL_PROMPT:%PROMPT%\n') + out, err = check_output([test_batch]) + lines = out.splitlines() + self.assertEqual(lines[0], b'ACTIVE_PROMPT:(venv) base) $G') + self.assertEqual(lines[1], b'FINAL_PROMPT:base) $G') + @unittest.skipUnless(os.name == 'nt' and can_symlink(), 'symlinks on Windows') def test_failed_symlink(self): diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index b187643e84521cc..0c4717521f16f67 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -167,6 +167,11 @@ def test_basic_callback(self): self.check_basic_callback(create_function) self.check_basic_callback(create_bound_method) + def test_non_callable_callback(self): + c = C() + self.assertRaises(TypeError, weakref.ref, c, 42) + self.assertRaises(TypeError, weakref.proxy, c, 42) + @support.cpython_only def test_cfunction(self): _testcapi = import_helper.import_module("_testcapi") diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 2803c6d45c27bfa..ee0e24f6e86ae33 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -208,6 +208,17 @@ def test_dump_encoding(self): self.assertEqual(xmlrpclib.loads(strg)[0][0], value) self.assertEqual(xmlrpclib.loads(strg)[1], methodname) + def test_dump_escape_methodname(self): + payload = 'foobar' + s = xmlrpclib.dumps((), methodname=payload) + self.assertIn( + 'foo</methodName><injected attr="evil"/>' + '<methodName>bar', s + ) + self.assertNotIn('', s) + load, m = xmlrpclib.loads(s) + self.assertEqual(m, payload) + def test_dump_bytes(self): sample = b"my dog has fleas" self.assertEqual(sample, xmlrpclib.Binary(sample)) diff --git a/Lib/traceback.py b/Lib/traceback.py index 614a12f69b32e40..dcdab1f12e9a168 100644 --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -1485,11 +1485,22 @@ def _find_keyword_typos(self): # Limit the number of possible matches to try max_matches = 3 matches = [] + + hint = _get_cross_language_keyword_hint(wrong_name) + if hint: + matches.append(hint) if _suggestions is not None: - suggestion = _suggestions._generate_suggestions(keyword.kwlist, wrong_name) + suggestion = _suggestions._generate_suggestions(keyword.kwlist + keyword.softkwlist, wrong_name) if suggestion: matches.append(suggestion) - matches.extend(difflib.get_close_matches(wrong_name, keyword.kwlist, n=max_matches, cutoff=0.5)) + matches.extend( + difflib.get_close_matches( + wrong_name, + keyword.kwlist + keyword.softkwlist, + n=max_matches, + cutoff=0.5 + ) + ) matches = matches[:max_matches] for suggestion in matches: if not suggestion or suggestion == wrong_name: @@ -1787,6 +1798,17 @@ def print(self, *, file=None, chain=True, **kwargs): }) +# Cross-language keyword suggestions. +_CROSS_LANGUAGE_KEYWORD_HINTS = frozendict({ + # C/C++ equivalents + 'switch': 'match', + 'delete': 'del', + # function define equivalents + 'function': 'def', + 'func': 'def', + 'void': 'def', +}) + def _substitution_cost(ch_a, ch_b): if ch_a == ch_b: return 0 @@ -1866,6 +1888,12 @@ def _get_cross_language_hint(obj, wrong_name): return None +def _get_cross_language_keyword_hint(wrong_name): + """Check if wrong_name is a common keyword from another language + """ + return _CROSS_LANGUAGE_KEYWORD_HINTS.get(wrong_name) + + def _get_safe___dir__(obj): # Use obj.__dir__() to avoid a TypeError when calling dir(obj). # See gh-131001 and gh-139933. diff --git a/Lib/typing.py b/Lib/typing.py index 715d08e0e1603e6..1579f492003f748 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1343,32 +1343,35 @@ def __dir__(self): class _GenericAlias(_BaseGenericAlias, _root=True): - # The type of parameterized generics. - # - # That is, for example, `type(List[int])` is `_GenericAlias`. - # - # Objects which are instances of this class include: - # * Parameterized container types, e.g. `Tuple[int]`, `List[int]`. - # * Note that native container types, e.g. `tuple`, `list`, use - # `types.GenericAlias` instead. - # * Parameterized classes: - # class C[T]: pass - # # C[int] is a _GenericAlias - # * `Callable` aliases, generic `Callable` aliases, and - # parameterized `Callable` aliases: - # T = TypeVar('T') - # # _CallableGenericAlias inherits from _GenericAlias. - # A = Callable[[], None] # _CallableGenericAlias - # B = Callable[[T], None] # _CallableGenericAlias - # C = B[int] # _CallableGenericAlias - # * Parameterized `Final`, `ClassVar`, `TypeForm`, `TypeGuard`, and `TypeIs`: - # # All _GenericAlias - # Final[int] - # ClassVar[float] - # TypeForm[bytes] - # TypeGuard[bool] - # TypeIs[range] - + """The type of parameterized generics. + + That is, for example, `type(List[int])` is `_GenericAlias`. + + Objects which are instances of this class include: + * Parameterized container types, e.g. `Tuple[int]`, `List[int]`. + * Note that native container types, e.g. `tuple`, `list`, use + `types.GenericAlias` instead. + * Parameterized classes: + class C[T]: pass + # C[int] is a _GenericAlias + * `Callable` aliases, generic `Callable` aliases, and + parameterized `Callable` aliases: + T = TypeVar('T') + # _CallableGenericAlias inherits from _GenericAlias. + A = Callable[[], None] # _CallableGenericAlias + B = Callable[[T], None] # _CallableGenericAlias + C = B[int] # _CallableGenericAlias + * Parameterized `Final`, `ClassVar`, `TypeForm`, `TypeGuard`, and `TypeIs`: + # All _GenericAlias + Final[int] + ClassVar[float] + TypeForm[bytearray] + TypeGuard[bool] + TypeIs[range] + + Note that instances of this class are not classes (e.g by `inspect.isclass`), + even though they behave like them. + """ def __init__(self, origin, args, *, inst=True, name=None): super().__init__(origin, inst=inst, name=name) if not isinstance(args, tuple): @@ -1400,20 +1403,21 @@ def __ror__(self, left): @_tp_cache def __getitem__(self, args): - # Parameterizes an already-parameterized object. - # - # For example, we arrive here doing something like: - # T1 = TypeVar('T1') - # T2 = TypeVar('T2') - # T3 = TypeVar('T3') - # class A(Generic[T1]): pass - # B = A[T2] # B is a _GenericAlias - # C = B[T3] # Invokes _GenericAlias.__getitem__ - # - # We also arrive here when parameterizing a generic `Callable` alias: - # T = TypeVar('T') - # C = Callable[[T], None] - # C[int] # Invokes _GenericAlias.__getitem__ + """Parameterizes an already-parameterized object. + + For example, we arrive here doing something like: + T1 = TypeVar('T1') + T2 = TypeVar('T2') + T3 = TypeVar('T3') + class A(Generic[T1]): pass + B = A[T2] # B is a _GenericAlias + C = B[T3] # Invokes _GenericAlias.__getitem__ + + We also arrive here when parameterizing a generic `Callable` alias: + T = TypeVar('T') + C = Callable[[T], None] + C[int] # Invokes _GenericAlias.__getitem__ + """ if self.__origin__ in (Generic, Protocol): # Can't subscript Generic[...] or Protocol[...]. @@ -1430,20 +1434,20 @@ def __getitem__(self, args): return r def _determine_new_args(self, args): - # Determines new __args__ for __getitem__. - # - # For example, suppose we had: - # T1 = TypeVar('T1') - # T2 = TypeVar('T2') - # class A(Generic[T1, T2]): pass - # T3 = TypeVar('T3') - # B = A[int, T3] - # C = B[str] - # `B.__args__` is `(int, T3)`, so `C.__args__` should be `(int, str)`. - # Unfortunately, this is harder than it looks, because if `T3` is - # anything more exotic than a plain `TypeVar`, we need to consider - # edge cases. - + """Determines new __args__ for __getitem__. + + For example, suppose we had: + T1 = TypeVar('T1') + T2 = TypeVar('T2') + class A(Generic[T1, T2]): pass + T3 = TypeVar('T3') + B = A[int, T3] + C = B[str] + `B.__args__` is `(int, T3)`, so `C.__args__` should be `(int, str)`. + Unfortunately, this is harder than it looks, because if `T3` is + anything more exotic than a plain `TypeVar`, we need to consider + edge cases. + """ params = self.__parameters__ # In the example above, this would be {T3: str} for param in params: diff --git a/Lib/unittest/loader.py b/Lib/unittest/loader.py index a52950dad224ee7..697520246f0e3c6 100644 --- a/Lib/unittest/loader.py +++ b/Lib/unittest/loader.py @@ -1,5 +1,6 @@ """Loading unittests.""" +import inspect import os import re import sys @@ -84,8 +85,10 @@ def loadTestsFromTestCase(self, testCaseClass): raise TypeError("Test cases should not be derived from " "TestSuite. Maybe you meant to derive from " "TestCase?") - if testCaseClass in (case.TestCase, case.FunctionTestCase): - # We don't load any tests from base types that should not be loaded. + if (testCaseClass in (case.TestCase, case.FunctionTestCase) or + inspect.isabstract(testCaseClass)): + # We don't load any tests from base types that should not be loaded, + # and abstract base classes that can't be instantiated testCaseNames = [] else: testCaseNames = self.getTestCaseNames(testCaseClass) @@ -103,6 +106,7 @@ def loadTestsFromModule(self, module, *, pattern=None): isinstance(obj, type) and issubclass(obj, case.TestCase) and obj not in (case.TestCase, case.FunctionTestCase) + and not inspect.isabstract(obj) ): tests.append(self.loadTestsFromTestCase(obj)) @@ -181,6 +185,9 @@ def loadTestsFromName(self, name, module=None): elif (isinstance(obj, types.FunctionType) and isinstance(parent, type) and issubclass(parent, case.TestCase)): + if inspect.isabstract(parent): + raise TypeError( + "Cannot instantiate abstract test case %s" % parent.__name__) name = parts[-1] inst = parent(name) # static methods follow a different path diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 56cdc37942d65d8..14a490c16575857 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -24,7 +24,6 @@ ) -import asyncio import contextlib import io import inspect diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py index d64f678d235b6f9..82b95adbdc283ef 100644 --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -277,7 +277,7 @@ def _hostinfo(self): return hostname, port -_UNSPECIFIED = ['not specified'] +_UNSPECIFIED = sentinel("_UNSPECIFIED", repr="") _MISSING_AS_NONE_DEFAULT = False class _ResultBase: diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat index 06f4753d73b7aed..4a3e791abb86bd2 100644 --- a/Lib/venv/scripts/nt/activate.bat +++ b/Lib/venv/scripts/nt/activate.bat @@ -13,8 +13,8 @@ @if defined _OLD_VIRTUAL_PROMPT @set PROMPT=%_OLD_VIRTUAL_PROMPT% @if defined _OLD_VIRTUAL_PYTHONHOME @set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% -@set "_OLD_VIRTUAL_PROMPT=%PROMPT%" -@set "PROMPT=(__VENV_PROMPT__) %PROMPT%" +@if not defined VIRTUAL_ENV_DISABLE_PROMPT @set "_OLD_VIRTUAL_PROMPT=%PROMPT%" +@if not defined VIRTUAL_ENV_DISABLE_PROMPT @set "PROMPT=(__VENV_PROMPT__) %PROMPT%" @if defined PYTHONHOME @set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% @set PYTHONHOME= diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index f441376d09c4aa2..84e4e4d11a7319e 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -965,7 +965,7 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None, data = ( xmlheader, "\n" - "", methodname, "\n", + "", escape(methodname), "\n", data, "\n" ) diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 71e4dd4f6f625ce..005b6f4eb840448 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -4,7 +4,6 @@ XXX references to utf-8 need further investigation. """ import binascii -import importlib.util import io import os import shutil diff --git a/Lib/zoneinfo/_common.py b/Lib/zoneinfo/_common.py index 98668c15d8bf94b..caa3a5b583bab32 100644 --- a/Lib/zoneinfo/_common.py +++ b/Lib/zoneinfo/_common.py @@ -26,7 +26,7 @@ def load_tzdata(key): # UnicodeEncodeError: If package_name or resource_name are not UTF-8, # such as keys containing a surrogate character. # IsADirectoryError: If package_name without a resource_name specified. - raise ZoneInfoNotFoundError(f"No time zone found with key {key}") + raise ZoneInfoNotFoundError(f"No time zone found with key {key!r}") def load_data(fobj): diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index d4df8fbc42ddcba..394e42439f7710e 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -246,9 +246,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 3.5.6", - url="https://github.com/openssl/openssl/releases/download/openssl-3.5.6/openssl-3.5.6.tar.gz", - checksum="deae7c80cba99c4b4f940ecadb3c3338b13cb77418409238e57d7f31f2a3b736", + name="OpenSSL 3.5.7", + url="https://github.com/openssl/openssl/releases/download/openssl-3.5.7/openssl-3.5.7.tar.gz", + checksum="a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8", buildrecipe=build_universal_openssl, configure=None, install=None, @@ -359,9 +359,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.53.1", - url="https://www.sqlite.org/2026/sqlite-autoconf-3530100.tar.gz", - checksum="83e6b2020a034e9a7ad4a72feea59e1ad52f162e09cbd26735a3ffb98359fc4f", + name="SQLite 3.53.2", + url="https://www.sqlite.org/2026/sqlite-autoconf-3530200.tar.gz", + checksum="588ad51949419a56ebe81fe56193d510c559eb94c9a57748387860b5d3069316", extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Makefile.pre.in b/Makefile.pre.in index 2b34b009fd745a0..cf700e9f2340901 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1616,6 +1616,8 @@ Programs/_bootstrap_python.o: Programs/_bootstrap_python.c $(BOOTSTRAP_HEADERS) _bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath.o Modules/Setup.local $(LINKCC) $(PY_LDFLAGS_NOLTO) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \ Programs/_bootstrap_python.o Modules/getpath.o $(LIBS) $(MODLIBS) $(SYSLIBS) + # Dummy pybuilddir.txt is needed for _bootstrap_python to be runnable + @echo "none" > ./pybuilddir.txt ############################################################################ diff --git a/Misc/ACKS b/Misc/ACKS index 14f0db7549534be..ee68d91f13c431f 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1226,6 +1226,7 @@ Owen Martin Sidney San Martín Westley Martínez Sébastien Martini +Iván Márton Roger Masse Nick Mathewson Simon Mathieu @@ -1762,6 +1763,7 @@ Charlie Shepherd Bruce Sherwood Gregory Shevchenko Hai Shi +Daniel Shields Alexander Shigin Pete Shinners Michael Shiplett diff --git a/Misc/NEWS.d/next/Build/2026-04-21-17-27-52.gh-issue-148832.Kx9aQ1.rst b/Misc/NEWS.d/next/Build/2026-04-21-17-27-52.gh-issue-148832.Kx9aQ1.rst new file mode 100644 index 000000000000000..867cfcc5ab62ca2 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-21-17-27-52.gh-issue-148832.Kx9aQ1.rst @@ -0,0 +1,4 @@ +Fix :option:`--enable-bolt` build by switching the default BOLT flag from +``-icf=1`` to ``-icf=0``. ``-icf=1`` folds address-taken functions and +breaks type-slot dispatch, crashing on :mod:`list` and :mod:`tuple` +concatenation. Patched by Shamil Abdulaev. diff --git a/Misc/NEWS.d/next/Build/2026-06-09-11-54-13.gh-issue-151163.vFAtjv.rst b/Misc/NEWS.d/next/Build/2026-06-09-11-54-13.gh-issue-151163.vFAtjv.rst new file mode 100644 index 000000000000000..e4f3a044c81c6f5 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-06-09-11-54-13.gh-issue-151163.vFAtjv.rst @@ -0,0 +1 @@ +Updated Android build to include SQLite version 3.53.2. diff --git a/Misc/NEWS.d/next/C_API/2026-05-31-15-39-58.gh-issue-150671.bTkDVC.rst b/Misc/NEWS.d/next/C_API/2026-05-31-15-39-58.gh-issue-150671.bTkDVC.rst new file mode 100644 index 000000000000000..a67a0f85db1a506 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-05-31-15-39-58.gh-issue-150671.bTkDVC.rst @@ -0,0 +1,4 @@ +Deprecate these C-API functions: :c:func:`PyGen_New`, +:c:func:`PyGen_NewWithQualName`, :c:func:`PyCoro_New`, and +:c:func:`PyAsyncGen_New`. +Schedule them for removal in 3.18 diff --git a/Misc/NEWS.d/next/C_API/2026-06-04-14-26-17.gh-issue-150907.CA91_B.rst b/Misc/NEWS.d/next/C_API/2026-06-04-14-26-17.gh-issue-150907.CA91_B.rst new file mode 100644 index 000000000000000..f58b248f3a0b986 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-06-04-14-26-17.gh-issue-150907.CA91_B.rst @@ -0,0 +1,2 @@ +Fix ``dynamic_annotations.h`` header file when built with C++ and Valgrind: +add ``extern "C++" scope`` for the C++ template. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2026-06-09-14-50-35.gh-issue-80384.UEGyvB.rst b/Misc/NEWS.d/next/C_API/2026-06-09-14-50-35.gh-issue-80384.UEGyvB.rst new file mode 100644 index 000000000000000..c4f5e8f3f9bbc2d --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-06-09-14-50-35.gh-issue-80384.UEGyvB.rst @@ -0,0 +1,3 @@ +:c:func:`PyWeakref_NewRef` and :c:func:`PyWeakref_NewProxy` now raise +:exc:`TypeError` if the *callback* argument is not callable, ``None``, or +``NULL``. diff --git a/Misc/NEWS.d/next/C_API/2026-06-10-15-22-44.gh-issue-149044.O7KEcs.rst b/Misc/NEWS.d/next/C_API/2026-06-10-15-22-44.gh-issue-149044.O7KEcs.rst new file mode 100644 index 000000000000000..fe0730b1bf87c4d --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-06-10-15-22-44.gh-issue-149044.O7KEcs.rst @@ -0,0 +1,3 @@ +Improved error message when specifying non-type base classes in +:c:macro:`Py_tp_bases`, :c:macro:`Py_tp_base`, and *bases* argument to +:c:func:`PyType_FromMetaclass` and other ``PyType_From*`` functions. diff --git a/Misc/NEWS.d/next/C_API/2026-06-10-16-43-37.gh-issue-123619.dV82r6.rst b/Misc/NEWS.d/next/C_API/2026-06-10-16-43-37.gh-issue-123619.dV82r6.rst new file mode 100644 index 000000000000000..4d4c94563330c06 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-06-10-16-43-37.gh-issue-123619.dV82r6.rst @@ -0,0 +1,3 @@ +:c:func:`PyUnstable_Object_EnableDeferredRefcount` now returns ``0`` if the +object is not tracked by the garbage collector: if :func:`gc.is_tracked` is +false. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2019-12-27-19-20-33.bpo-38131.J5fv54.rst b/Misc/NEWS.d/next/Core_and_Builtins/2019-12-27-19-20-33.bpo-38131.J5fv54.rst new file mode 100644 index 000000000000000..8b606c4335e033a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2019-12-27-19-20-33.bpo-38131.J5fv54.rst @@ -0,0 +1,2 @@ +Produce more meaningful messages when compiling AST objects with wrong field +values. Patch by Batuhan Taskaya. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-22-21-52-38.gh-issue-150207.l2BUtI.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-22-21-52-38.gh-issue-150207.l2BUtI.rst new file mode 100644 index 000000000000000..12fbffcd170684c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-22-21-52-38.gh-issue-150207.l2BUtI.rst @@ -0,0 +1 @@ +Fix a crash when a memory allocation fails during tokenizer initialization. A proper :exc:`MemoryError` is now raised instead. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-24-22-46-49.gh-issue-148613.PLpmyd.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-24-22-46-49.gh-issue-148613.PLpmyd.rst new file mode 100644 index 000000000000000..71a701bf3eb3551 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-24-22-46-49.gh-issue-148613.PLpmyd.rst @@ -0,0 +1,2 @@ +Fix a data race in the free-threaded build between :func:`gc.set_threshold` +and garbage collection scheduling during object allocation. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-26-00-06-30.gh-issue-150411.u-d-_5.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-26-00-06-30.gh-issue-150411.u-d-_5.rst new file mode 100644 index 000000000000000..5b19a4fff5ddc73 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-26-00-06-30.gh-issue-150411.u-d-_5.rst @@ -0,0 +1,2 @@ +Fix a data race in the free-threaded build when :func:`gc.get_count` reads +the young generation allocation count while another thread updates it. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-30-20-19-35.gh-issue-150633.XkNul0.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-30-20-19-35.gh-issue-150633.XkNul0.rst new file mode 100644 index 000000000000000..c397ad61f086c1b --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-30-20-19-35.gh-issue-150633.XkNul0.rst @@ -0,0 +1,3 @@ +Fix the frozen importer accepting module names with embedded null bytes, which +caused it to bypass the :data:`sys.modules` cache and create duplicate module +objects. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-01-19-00-00.gh-issue-150700.W8CzVR.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-01-19-00-00.gh-issue-150700.W8CzVR.rst new file mode 100644 index 000000000000000..e7734034ff5c814 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-01-19-00-00.gh-issue-150700.W8CzVR.rst @@ -0,0 +1,3 @@ +Fix a :exc:`SystemError` when compiling a class-scope comprehension containing +a ``lambda`` that references ``__class__``, ``__classdict__``, or +``__conditional_annotations__``. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-03-16-27-00.gh-issue-150858.j2dSkD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-03-16-27-00.gh-issue-150858.j2dSkD.rst new file mode 100644 index 000000000000000..dcb932bf320629a --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-03-16-27-00.gh-issue-150858.j2dSkD.rst @@ -0,0 +1 @@ +Fix a data race while changing ``__qualname__`` of a type concurrently on free-threaded builds. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-05-22-52-41.gh-issue-150988.fDKfMJ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-05-22-52-41.gh-issue-150988.fDKfMJ.rst new file mode 100644 index 000000000000000..6fb70a1ce2685c8 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-05-22-52-41.gh-issue-150988.fDKfMJ.rst @@ -0,0 +1,2 @@ +Fix a reference leak in :exc:`OSError` when attributes are set before +``super().__init__()``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-06-08-20-00.gh-issue-150942.Jk9pQr.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-06-08-20-00.gh-issue-150942.Jk9pQr.rst new file mode 100644 index 000000000000000..9777b8932271404 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-06-08-20-00.gh-issue-150942.Jk9pQr.rst @@ -0,0 +1,3 @@ +Speed up frame local variable item collection by appending result pairs to the +output list without an extra reference-count round-trip (using the internal +reference-stealing list append helper). Patch by Omkar Kabde. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-05-31-22.gh-issue-151065._o_31F.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-05-31-22.gh-issue-151065._o_31F.rst new file mode 100644 index 000000000000000..e46c96ef784cc9e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-05-31-22.gh-issue-151065._o_31F.rst @@ -0,0 +1 @@ +Fix memory leak when using the :ref:`mimalloc memory allocator `. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-13-14-42.gh-issue-150902.-CWZ66.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-13-14-42.gh-issue-150902.-CWZ66.rst new file mode 100644 index 000000000000000..e3b7cd387b439fe --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-08-13-14-42.gh-issue-150902.-CWZ66.rst @@ -0,0 +1 @@ +Apply an existing optimization of PyCriticalSection (single mutex) to PyCriticalSection2: avoid acquiring the same locks that the current CS has already acquired. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-09-10-28-30.gh-issue-151126.DKa6Sl.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-09-10-28-30.gh-issue-151126.DKa6Sl.rst new file mode 100644 index 000000000000000..67e2ce4044431f9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-09-10-28-30.gh-issue-151126.DKa6Sl.rst @@ -0,0 +1,5 @@ +Fix a crash, when there's no memory left on a device, +which happened in: code compilation, :mod:`!_interpchannels` module, +:func:`!_winapi.CreateProcess` function. + +Now these places raise proper :exc:`MemoryError` errors. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-09-12-24-35.gh-issue-151112.4RKCkD.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-09-12-24-35.gh-issue-151112.4RKCkD.rst new file mode 100644 index 000000000000000..93ee5c8cf1914b4 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-09-12-24-35.gh-issue-151112.4RKCkD.rst @@ -0,0 +1 @@ +Fix a crash in the compiler that could occur when running out of memory. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-10-15-19-58.gh-issue-151238.C9Wu4x.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-10-15-19-58.gh-issue-151238.C9Wu4x.rst new file mode 100644 index 000000000000000..fe7519fb4878952 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-10-15-19-58.gh-issue-151238.C9Wu4x.rst @@ -0,0 +1,2 @@ +Fix a crash when compiling a concatenated f-string or t-string if an error +occurs when processing one of it's parts. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-10-15-42-46.gh-issue-151253.7MMQ8P.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-10-15-42-46.gh-issue-151253.7MMQ8P.rst new file mode 100644 index 000000000000000..56d2f3b2633bb01 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-10-15-42-46.gh-issue-151253.7MMQ8P.rst @@ -0,0 +1,3 @@ +If ``import encodings`` (first import) fails at Python startup, dump the +Python path configuration to help users debugging their configuration. Patch +by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-11-16-03-23.gh-issue-151297.NGPkUM.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-11-16-03-23.gh-issue-151297.NGPkUM.rst new file mode 100644 index 000000000000000..288d726e0f1004d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-11-16-03-23.gh-issue-151297.NGPkUM.rst @@ -0,0 +1 @@ +Fix an invalid pointer dereference that could occur when calling :c:func:`PyObject_Realloc` with a NULL pointer in :term:`free-threaded builds ` or with :envvar:`PYTHONMALLOC` set to ``mimalloc``. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-12-15-30-25.gh-issue-151218.5M_nv8.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-12-15-30-25.gh-issue-151218.5M_nv8.rst new file mode 100644 index 000000000000000..46539efc373eb0d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-12-15-30-25.gh-issue-151218.5M_nv8.rst @@ -0,0 +1,3 @@ +:c:func:`PyConfig_Set` and :func:`sys.set_int_max_str_digits` now replace +:data:`sys.flags` (create a new object), instead of modifying :data:`sys.flags` +in-place. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst new file mode 100644 index 000000000000000..d76a9bc95278bcb --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst @@ -0,0 +1,3 @@ +Fix direct execution of files with invalid source encodings to report the +underlying codec lookup or decoding error instead of the generic +``SyntaxError: encoding problem`` message. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-16-17-23-37.gh-issue-151546.LhiaZz.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-16-17-23-37.gh-issue-151546.LhiaZz.rst new file mode 100644 index 000000000000000..af1c23bd50355f2 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-16-17-23-37.gh-issue-151546.LhiaZz.rst @@ -0,0 +1,3 @@ +Fix the stack limit check if Python is linked to musl (ex: Alpine Linux). +Use the stack size set by the linker to compute the stack limits. Patch by +Victor Stinner. diff --git a/Misc/NEWS.d/next/IDLE/2019-12-12-03-18-02.bpo-6699.1CqJFG.rst b/Misc/NEWS.d/next/IDLE/2019-12-12-03-18-02.bpo-6699.1CqJFG.rst new file mode 100644 index 000000000000000..e7fb9bf1b3bdf6a --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2019-12-12-03-18-02.bpo-6699.1CqJFG.rst @@ -0,0 +1 @@ +Warn the user if a file will be overwritten when saving. diff --git a/Misc/NEWS.d/next/Library/2021-02-26-13-17-57.bpo-40469.yJHeQg.rst b/Misc/NEWS.d/next/Library/2021-02-26-13-17-57.bpo-40469.yJHeQg.rst new file mode 100644 index 000000000000000..239f856bb04c0ae --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-02-26-13-17-57.bpo-40469.yJHeQg.rst @@ -0,0 +1,5 @@ +:class:`~logging.handlers.TimedRotatingFileHandler` now uses the creation time +instead of the last modification time of an existing log file as the basis +for the first rotation after handler creation, if supported by the OS and file system. +This allows it to be used in short-running programs that start and end before +the rotation interval expires. diff --git a/Misc/NEWS.d/next/Library/2023-01-23-21-23-50.gh-issue-101267._f-cFH.rst b/Misc/NEWS.d/next/Library/2023-01-23-21-23-50.gh-issue-101267._f-cFH.rst new file mode 100644 index 000000000000000..901a3fb60ab5b9f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-01-23-21-23-50.gh-issue-101267._f-cFH.rst @@ -0,0 +1,7 @@ +When a worker process terminates unexpectedly, +:class:`concurrent.futures.ProcessPoolExecutor` now sets a separate +:exc:`~concurrent.futures.process.BrokenProcessPool` exception on each pending +future instead of sharing a single instance among them all. Sharing one +exception produced malformed tracebacks: each +:meth:`Future.result() ` call re-raised the +same object, appending another copy of the traceback to it. diff --git a/Misc/NEWS.d/next/Library/2024-06-18-04-08-37.gh-issue-120665.x7T1hV.rst b/Misc/NEWS.d/next/Library/2024-06-18-04-08-37.gh-issue-120665.x7T1hV.rst new file mode 100644 index 000000000000000..27e93988ed11efb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-06-18-04-08-37.gh-issue-120665.x7T1hV.rst @@ -0,0 +1 @@ +Fixed an issue where ``unittest`` loaders would load and instantiate :class:`unittest.TestCase`-derived subclasses that are also abstract base classes, which can't be instantiated. diff --git a/Misc/NEWS.d/next/Library/2025-10-09-12-13-29.gh-issue-139819.YxUDyH.rst b/Misc/NEWS.d/next/Library/2025-10-09-12-13-29.gh-issue-139819.YxUDyH.rst new file mode 100644 index 000000000000000..ab3a8c6ed16ce4a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-10-09-12-13-29.gh-issue-139819.YxUDyH.rst @@ -0,0 +1,3 @@ +:mod:`rlcompleter`: Avoid suggesting attributes that are not accessible on +instances (e.g., Enum members showing ``__name__``). Patch by Peter +(ttw225). diff --git a/Misc/NEWS.d/next/Library/2025-12-21-17-56-37.gh-issue-143008.aakErJ.rst b/Misc/NEWS.d/next/Library/2025-12-21-17-56-37.gh-issue-143008.aakErJ.rst new file mode 100644 index 000000000000000..907cdb770ab65f9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-21-17-56-37.gh-issue-143008.aakErJ.rst @@ -0,0 +1,2 @@ +Fix crash in :class:`io.TextIOWrapper` when reentrant +:meth:`io.TextIOBase.detach` is called reentrantly from the underlying buffer. diff --git a/Misc/NEWS.d/next/Library/2026-01-18-06-42-47.gh-issue-143988.MtLtCP.rst b/Misc/NEWS.d/next/Library/2026-01-18-06-42-47.gh-issue-143988.MtLtCP.rst new file mode 100644 index 000000000000000..fcc0cb54934b90e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-18-06-42-47.gh-issue-143988.MtLtCP.rst @@ -0,0 +1,2 @@ +Fixed crashes in :meth:`socket.socket.sendmsg` and :meth:`socket.socket.recvmsg_into` +that could occur if buffer sequences are concurrently mutated. diff --git a/Misc/NEWS.d/next/Library/2026-04-20-01-24-22.gh-issue-92455.vXhmad.rst b/Misc/NEWS.d/next/Library/2026-04-20-01-24-22.gh-issue-92455.vXhmad.rst new file mode 100644 index 000000000000000..8d2a11cb7761377 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-20-01-24-22.gh-issue-92455.vXhmad.rst @@ -0,0 +1,3 @@ +Fix :mod:`mimetypes` to prefer case-sensitive matches for suffix mappings and +MIME type suffixes before falling back to case-insensitive matches. +Contributed by Xiao Yuan. diff --git a/Misc/NEWS.d/next/Library/2026-04-21-06-30-59.gh-issue-119670.pMWZfY.rst b/Misc/NEWS.d/next/Library/2026-04-21-06-30-59.gh-issue-119670.pMWZfY.rst new file mode 100644 index 000000000000000..fc1941be4dc7925 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-21-06-30-59.gh-issue-119670.pMWZfY.rst @@ -0,0 +1,2 @@ +Add keyword-only parameter *force* to :func:`shlex.quote` to force quoting +a string, even if it is already safe for a shell without being quoted. diff --git a/Misc/NEWS.d/next/Library/2026-04-24-19-54-00.gh-issue-148954.v1.rst b/Misc/NEWS.d/next/Library/2026-04-24-19-54-00.gh-issue-148954.v1.rst new file mode 100644 index 000000000000000..6245af7e362e920 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-24-19-54-00.gh-issue-148954.v1.rst @@ -0,0 +1 @@ +Fix XML injection vulnerability in :func:`xmlrpc.client.dumps` where the ``methodname`` was not being escaped before interpolation into the XML body. diff --git a/Misc/NEWS.d/next/Library/2026-04-26-11-25-38.gh-issue-118158.xIy05H.rst b/Misc/NEWS.d/next/Library/2026-04-26-11-25-38.gh-issue-118158.xIy05H.rst new file mode 100644 index 000000000000000..bd22871c1c0c172 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-26-11-25-38.gh-issue-118158.xIy05H.rst @@ -0,0 +1 @@ +Ensure py_compile CLI error messages end with a newline. Contributed by Xiao Yuan. diff --git a/Misc/NEWS.d/next/Library/2026-05-15-19-52-41.gh-issue-149891.BJUIGB.rst b/Misc/NEWS.d/next/Library/2026-05-15-19-52-41.gh-issue-149891.BJUIGB.rst new file mode 100644 index 000000000000000..f8bc28659533af8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-15-19-52-41.gh-issue-149891.BJUIGB.rst @@ -0,0 +1 @@ +Add support for more encoding aliases `officially registered in IANA `__. diff --git a/Misc/NEWS.d/next/Library/2026-05-17-12-37-59.gh-issue-53144.c5tr1p.rst b/Misc/NEWS.d/next/Library/2026-05-17-12-37-59.gh-issue-53144.c5tr1p.rst new file mode 100644 index 000000000000000..283a5ba44d1f19f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-17-12-37-59.gh-issue-53144.c5tr1p.rst @@ -0,0 +1,2 @@ +The :mod:`email` package now supports all aliases of Python codecs and uses +MIME/IANA names for all IANA registered charsets. diff --git a/Misc/NEWS.d/next/Library/2026-05-27-15-51-29.gh-issue-150534.3Nan6S.rst b/Misc/NEWS.d/next/Library/2026-05-27-15-51-29.gh-issue-150534.3Nan6S.rst new file mode 100644 index 000000000000000..2ead9990513015f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-27-15-51-29.gh-issue-150534.3Nan6S.rst @@ -0,0 +1,6 @@ +Added trigonometric functions that work in units of half turns, rather than +radians. The new functions :func:`math.acospi`, :func:`math.asinpi`, +:func:`math.atanpi`, and :func:`math.atan2pi` return half-turn angles. The +new functions :func:`math.cospi`, :func:`math.sinpi`, and :func:`math.tanpi` +take half-turn angle arguments. These functions are recommended by IEEE +754-2019 and standardized in C23. diff --git a/Misc/NEWS.d/next/Library/2026-05-27-23-47-31.gh-issue-148932.Y1xmvA.rst b/Misc/NEWS.d/next/Library/2026-05-27-23-47-31.gh-issue-148932.Y1xmvA.rst new file mode 100644 index 000000000000000..a0b7a9740cd518d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-27-23-47-31.gh-issue-148932.Y1xmvA.rst @@ -0,0 +1 @@ +Fix ``profiling.sampling`` on Windows virtual environments to resolve the actual Python PID from a virtual environment shim. diff --git a/Misc/NEWS.d/next/Library/2026-05-31-10-00-00.gh-issue-150942.Tk9aRef.rst b/Misc/NEWS.d/next/Library/2026-05-31-10-00-00.gh-issue-150942.Tk9aRef.rst new file mode 100644 index 000000000000000..ba0de8fd434d303 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-31-10-00-00.gh-issue-150942.Tk9aRef.rst @@ -0,0 +1,3 @@ +Speed up :func:`json.loads` decoding of arrays and objects by storing +parsed values into the result list/dict without an extra reference-count +round-trip (using the internal reference-stealing append/insert helpers). diff --git a/Misc/NEWS.d/next/Library/2026-05-31-12-00-00.gh-issue-150942.Re7Ref.rst b/Misc/NEWS.d/next/Library/2026-05-31-12-00-00.gh-issue-150942.Re7Ref.rst new file mode 100644 index 000000000000000..63967108b1e0b3b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-31-12-00-00.gh-issue-150942.Re7Ref.rst @@ -0,0 +1,3 @@ +Speed up :func:`re.findall`, :func:`re.sub` and :func:`re.subn` by appending +result items to the output list without an extra reference-count round-trip +(using the internal reference-stealing list append helper). diff --git a/Misc/NEWS.d/next/Library/2026-06-02-14-21-46.gh-issue-150750.SVS2o0.rst b/Misc/NEWS.d/next/Library/2026-06-02-14-21-46.gh-issue-150750.SVS2o0.rst new file mode 100644 index 000000000000000..bda500383e7cda3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-02-14-21-46.gh-issue-150750.SVS2o0.rst @@ -0,0 +1 @@ +Fix a race condition in :meth:`collections.deque.index` with free-threading. diff --git a/Misc/NEWS.d/next/Library/2026-06-02-15-44-57.gh-issue-150817.lpFCh0.rst b/Misc/NEWS.d/next/Library/2026-06-02-15-44-57.gh-issue-150817.lpFCh0.rst new file mode 100644 index 000000000000000..42532bb0222cf4e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-02-15-44-57.gh-issue-150817.lpFCh0.rst @@ -0,0 +1,2 @@ +Speed up the ``|``, ``&`` and ``^`` operations on :class:`enum.Flag` members. +Patch by Bernát Gábor. diff --git a/Misc/NEWS.d/next/Library/2026-06-02-15-44-58.gh-issue-150818.Orcefu.rst b/Misc/NEWS.d/next/Library/2026-06-02-15-44-58.gh-issue-150818.Orcefu.rst new file mode 100644 index 000000000000000..3bb16001cc0bb41 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-02-15-44-58.gh-issue-150818.Orcefu.rst @@ -0,0 +1,3 @@ +Speed up :func:`logging.getLogger` with a lock-free fast path that returns an +already-registered logger without acquiring the logging lock. Patch by Bernát +Gábor. diff --git a/Misc/NEWS.d/next/Library/2026-06-03-13-51-29.gh-issue-150662.ELT8Vg.rst b/Misc/NEWS.d/next/Library/2026-06-03-13-51-29.gh-issue-150662.ELT8Vg.rst new file mode 100644 index 000000000000000..42ed6ad7cd3c65f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-03-13-51-29.gh-issue-150662.ELT8Vg.rst @@ -0,0 +1,4 @@ +Fix the ``--gecko`` collector in :mod:`profiling.sampling` that kept every +sample in memory. It now writes sample and marker data to temporary files +and reads them back, ultimately building the output file at the end. Patch +by Pablo Galindo and Maurycy Pawłowski-Wieroński. diff --git a/Misc/NEWS.d/next/Library/2026-06-03-21-59-11.gh-issue-150886.r2c25g.rst b/Misc/NEWS.d/next/Library/2026-06-03-21-59-11.gh-issue-150886.r2c25g.rst new file mode 100644 index 000000000000000..b220b63cfdb4ab5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-03-21-59-11.gh-issue-150886.r2c25g.rst @@ -0,0 +1,4 @@ +Remove the private, undocumented function +``importlib._bootstrap._object_name()``. It had no caller after +``load_module()`` and its deprecation warnings were removed from +:mod:`importlib`. diff --git a/Misc/NEWS.d/next/Library/2026-06-04-06-50-06.gh-issue-150898.1LkLA3.rst b/Misc/NEWS.d/next/Library/2026-06-04-06-50-06.gh-issue-150898.1LkLA3.rst new file mode 100644 index 000000000000000..85328c43368e198 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-04-06-50-06.gh-issue-150898.1LkLA3.rst @@ -0,0 +1 @@ +Unconditionally assume :attr:`ssl.SSLContext.keylog_filename` exists. diff --git a/Misc/NEWS.d/next/Library/2026-06-04-10-44-36.gh-issue-150889.UYNLR_.rst b/Misc/NEWS.d/next/Library/2026-06-04-10-44-36.gh-issue-150889.UYNLR_.rst new file mode 100644 index 000000000000000..a5cc1da758637c5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-04-10-44-36.gh-issue-150889.UYNLR_.rst @@ -0,0 +1 @@ +Speed up :func:`unicodedata.normalize` for the NFC and NFKC forms of non-ASCII text up to a factor 2. diff --git a/Misc/NEWS.d/next/Library/2026-06-04-18-22-56.gh-issue-143008.z5tw-J.rst b/Misc/NEWS.d/next/Library/2026-06-04-18-22-56.gh-issue-143008.z5tw-J.rst new file mode 100644 index 000000000000000..e99bc39c45f9b8f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-04-18-22-56.gh-issue-143008.z5tw-J.rst @@ -0,0 +1 @@ +Fix race conditions when re-initializing a :class:`io.TextIOWrapper` object. diff --git a/Misc/NEWS.d/next/Library/2026-06-04-21-49-18.gh-issue-150913.EmptyBl.rst b/Misc/NEWS.d/next/Library/2026-06-04-21-49-18.gh-issue-150913.EmptyBl.rst new file mode 100644 index 000000000000000..f95a6ee6ee15bf7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-04-21-49-18.gh-issue-150913.EmptyBl.rst @@ -0,0 +1,3 @@ +Fix :class:`sqlite3.Blob` slice assignment to raise +:exc:`TypeError` and :exc:`IndexError` for type and size mismatches +respectively, even when the target slice is empty. diff --git a/Misc/NEWS.d/next/Library/2026-06-04-23-10-31.gh-issue-62825.BtG_yQ.rst b/Misc/NEWS.d/next/Library/2026-06-04-23-10-31.gh-issue-62825.BtG_yQ.rst new file mode 100644 index 000000000000000..95a4fb1c61d4c30 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-04-23-10-31.gh-issue-62825.BtG_yQ.rst @@ -0,0 +1,2 @@ +Encodings "KS_C_5601-1987", "KS X 1001", etc are now aliases of "CP949" +instead of "EUC-KR". diff --git a/Misc/NEWS.d/next/Library/2026-06-06-15-20-54.gh-issue-151021.J4qk2A.rst b/Misc/NEWS.d/next/Library/2026-06-06-15-20-54.gh-issue-151021.J4qk2A.rst new file mode 100644 index 000000000000000..0617fa068c844d6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-06-15-20-54.gh-issue-151021.J4qk2A.rst @@ -0,0 +1,3 @@ +Fix :meth:`mmap.mmap.find` and :meth:`~mmap.mmap.rfind` to return ``-1`` +when searching for an empty subsequence with a start position past the end +of the mapping. diff --git a/Misc/NEWS.d/next/Library/2026-06-07-17-29-33.gh-issue-151039.AZ0qBn.rst b/Misc/NEWS.d/next/Library/2026-06-07-17-29-33.gh-issue-151039.AZ0qBn.rst new file mode 100644 index 000000000000000..1e99567f5550579 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-07-17-29-33.gh-issue-151039.AZ0qBn.rst @@ -0,0 +1 @@ +Fix a crash when static :mod:`datetime` types outlive the ``_datetime`` module. diff --git a/Misc/NEWS.d/next/Library/2026-06-08-15-04-35.gh-issue-150285.-Tj94n.rst b/Misc/NEWS.d/next/Library/2026-06-08-15-04-35.gh-issue-150285.-Tj94n.rst new file mode 100644 index 000000000000000..60b1f3e0a71f5bb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-08-15-04-35.gh-issue-150285.-Tj94n.rst @@ -0,0 +1 @@ +:mod:`pydoc` now wraps long single-line summary in text output. diff --git a/Misc/NEWS.d/next/Library/2026-06-09-12-00-00.gh-issue-150771.K7mNx2.rst b/Misc/NEWS.d/next/Library/2026-06-09-12-00-00.gh-issue-150771.K7mNx2.rst new file mode 100644 index 000000000000000..6535e5c48bf0360 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-09-12-00-00.gh-issue-150771.K7mNx2.rst @@ -0,0 +1,4 @@ +Fix :mod:`email` messages created with ``shift_jis`` or ``euc-jp`` charsets. +``set_content()`` now stores the payload using the output charset +(``iso-2022-jp``) so printing the message no longer raises +:exc:`UnicodeEncodeError`. diff --git a/Misc/NEWS.d/next/Library/2026-06-09-14-49-17.gh-issue-80384.ttRAja.rst b/Misc/NEWS.d/next/Library/2026-06-09-14-49-17.gh-issue-80384.ttRAja.rst new file mode 100644 index 000000000000000..53d4d513ba757de --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-09-14-49-17.gh-issue-80384.ttRAja.rst @@ -0,0 +1,2 @@ +:func:`weakref.ref` and :func:`weakref.proxy` now raise :exc:`TypeError` if +the *callback* argument is not callable or ``None``. diff --git a/Misc/NEWS.d/next/Library/2026-06-09-19-43-24.gh-issue-151179.hl_6Z0.rst b/Misc/NEWS.d/next/Library/2026-06-09-19-43-24.gh-issue-151179.hl_6Z0.rst new file mode 100644 index 000000000000000..904edf3a8c70908 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-09-19-43-24.gh-issue-151179.hl_6Z0.rst @@ -0,0 +1,3 @@ +Fix a pidfd leak in ``_PidfdChildWatcher`` on Linux: the watcher no +longer leaks the process file descriptor when ``waitpid()`` fails with an +error other than :exc:`ChildProcessError`. diff --git a/Misc/NEWS.d/next/Library/2026-06-10-00-00-02.gh-issue-109940.Cx1099.rst b/Misc/NEWS.d/next/Library/2026-06-10-00-00-02.gh-issue-109940.Cx1099.rst new file mode 100644 index 000000000000000..130dc780b612864 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-10-00-00-02.gh-issue-109940.Cx1099.rst @@ -0,0 +1,2 @@ +Fix Windows :mod:`venv` activation in ``cmd.exe`` to respect +``VIRTUAL_ENV_DISABLE_PROMPT``. diff --git a/Misc/NEWS.d/next/Library/2026-06-11-00-00-00.gh-issue-151295.NQYUzW.rst b/Misc/NEWS.d/next/Library/2026-06-11-00-00-00.gh-issue-151295.NQYUzW.rst new file mode 100644 index 000000000000000..e9012f023ff7f77 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-11-00-00-00.gh-issue-151295.NQYUzW.rst @@ -0,0 +1,4 @@ +Fixed a crash (use-after-free) in :meth:`bytes.join` and +:meth:`bytearray.join` that could occur if an item's +:meth:`~object.__buffer__` concurrently mutates the sequence being joined. +The mutation is now reported as a :exc:`RuntimeError` instead. diff --git a/Misc/NEWS.d/next/Library/2026-06-11-11-52-23.gh-issue-149671.6Rpr5r.rst b/Misc/NEWS.d/next/Library/2026-06-11-11-52-23.gh-issue-149671.6Rpr5r.rst new file mode 100644 index 000000000000000..5c08828e5fd77ec --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-11-11-52-23.gh-issue-149671.6Rpr5r.rst @@ -0,0 +1,3 @@ +Restore compatibility with setuptools ``-nspkg.pth`` files in the :mod:`site` +module. Inject ``sitedir`` variable in the frame which executes pth code. +Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/Library/2026-06-11-16-25-38.gh-issue-151126.bh_Usy.rst b/Misc/NEWS.d/next/Library/2026-06-11-16-25-38.gh-issue-151126.bh_Usy.rst new file mode 100644 index 000000000000000..25149057aa7d092 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-11-16-25-38.gh-issue-151126.bh_Usy.rst @@ -0,0 +1,2 @@ +Fix a crash when :exc:`MemoryError` in :func:`!os._path_splitroot` +was not set properly. diff --git a/Misc/NEWS.d/next/Library/2026-06-11-19-46-16.gh-issue-150285.wuhAsL.rst b/Misc/NEWS.d/next/Library/2026-06-11-19-46-16.gh-issue-150285.wuhAsL.rst new file mode 100644 index 000000000000000..3f19150488f3131 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-11-19-46-16.gh-issue-150285.wuhAsL.rst @@ -0,0 +1,2 @@ +:mod:`pydoc` now uses all available space (80 columns) for formatting reprs +of module and class data, but ensure that they do not overflow. diff --git a/Misc/NEWS.d/next/Library/2026-06-11-21-43-24.gh-issue-151337.JSVV18.rst b/Misc/NEWS.d/next/Library/2026-06-11-21-43-24.gh-issue-151337.JSVV18.rst new file mode 100644 index 000000000000000..0344eee9471d292 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-11-21-43-24.gh-issue-151337.JSVV18.rst @@ -0,0 +1 @@ +Avoid possible memory leak in ``tkinter.c`` on Windows. diff --git a/Misc/NEWS.d/next/Library/2026-06-12-00-04-34.gh-issue-151126.aHaBYq.rst b/Misc/NEWS.d/next/Library/2026-06-12-00-04-34.gh-issue-151126.aHaBYq.rst new file mode 100644 index 000000000000000..20ef69d5de5ac55 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-12-00-04-34.gh-issue-151126.aHaBYq.rst @@ -0,0 +1,2 @@ +Fix crash on unset :exc:`MemoryError` on allocation failure in +:func:`ctypes.get_errno`. diff --git a/Misc/NEWS.d/next/Library/2026-06-12-00-17-29.gh-issue-151128.-LYO3a.rst b/Misc/NEWS.d/next/Library/2026-06-12-00-17-29.gh-issue-151128.-LYO3a.rst new file mode 100644 index 000000000000000..6e760686af2b01f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-12-00-17-29.gh-issue-151128.-LYO3a.rst @@ -0,0 +1,3 @@ +Cross-language keyword suggestions are now shown for :exc:`SyntaxError` messages. +For example, ``switch x:`` suggests ``match``, ``delete x`` suggests ``del``, +``function f():`` suggests ``def``. Contributed by Zang Langyan. diff --git a/Misc/NEWS.d/next/Library/2026-06-12-07-20-08.gh-issue-151390.CmYN9EeJ.rst b/Misc/NEWS.d/next/Library/2026-06-12-07-20-08.gh-issue-151390.CmYN9EeJ.rst new file mode 100644 index 000000000000000..ff8de30599c6ad5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-12-07-20-08.gh-issue-151390.CmYN9EeJ.rst @@ -0,0 +1 @@ +Colorize ``match`` in the :term:`REPL` when followed by a unary ``+`` or ``-`` operator. Patch by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2026-06-12-22-46-31.gh-issue-151403.DalZWh.rst b/Misc/NEWS.d/next/Library/2026-06-12-22-46-31.gh-issue-151403.DalZWh.rst new file mode 100644 index 000000000000000..ca779ed684e7616 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-12-22-46-31.gh-issue-151403.DalZWh.rst @@ -0,0 +1,3 @@ +Fixed a crash in :class:`subprocess.Popen` (and ``_posixsubprocess.fork_exec``) +when an ``argv`` item's :meth:`~os.PathLike.__fspath__` concurrently mutates the +``args`` sequence being converted. diff --git a/Misc/NEWS.d/next/Library/2026-06-13-04-11-00.gh-issue-151426.f2V67e.rst b/Misc/NEWS.d/next/Library/2026-06-13-04-11-00.gh-issue-151426.f2V67e.rst new file mode 100644 index 000000000000000..428302e5f847f36 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-13-04-11-00.gh-issue-151426.f2V67e.rst @@ -0,0 +1,4 @@ +Fix impossible stack traces (callers and callees cross called, orphans and +incorrect lines) in the Tachyon profiler when caching frames, by snapshotting +the stack chunks before walking the frame chain on a cache miss. Patch by +Maurycy Pawłowski-Wieroński. diff --git a/Misc/NEWS.d/next/Security/2026-05-18-17-46-00.gh-issue-149835.EebFlk.rst b/Misc/NEWS.d/next/Security/2026-05-18-17-46-00.gh-issue-149835.EebFlk.rst new file mode 100644 index 000000000000000..20cab736552486d --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-05-18-17-46-00.gh-issue-149835.EebFlk.rst @@ -0,0 +1,3 @@ +:func:`shutil.move` now resolves symlinks via :func:`os.path.realpath` +when checking whether the destination is inside the source directory, +preventing a symlink-based bypass of that guard. diff --git a/Misc/NEWS.d/next/Security/2026-05-30-09-36-20.gh-issue-150599.nlHqU-.rst b/Misc/NEWS.d/next/Security/2026-05-30-09-36-20.gh-issue-150599.nlHqU-.rst new file mode 100644 index 000000000000000..a37d86cf423f820 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-05-30-09-36-20.gh-issue-150599.nlHqU-.rst @@ -0,0 +1,3 @@ +Fix a possible stack buffer overflow in :mod:`bz2` when a +:class:`bz2.BZ2Decompressor` is reused after a decompression error. +The decompressor now becomes unusable after libbz2 reports an error. diff --git a/Misc/NEWS.d/next/Security/2026-06-09-10-23-57.gh-issue-151159.91GpWQ.rst b/Misc/NEWS.d/next/Security/2026-06-09-10-23-57.gh-issue-151159.91GpWQ.rst new file mode 100644 index 000000000000000..735164c1a65ec33 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-06-09-10-23-57.gh-issue-151159.91GpWQ.rst @@ -0,0 +1 @@ +Update Android and iOS installers to use OpenSSL 3.5.7. diff --git a/Misc/NEWS.d/next/Security/2026-06-09-23-38-08.gh-issue-151159.ds-9f8.rst b/Misc/NEWS.d/next/Security/2026-06-09-23-38-08.gh-issue-151159.ds-9f8.rst new file mode 100644 index 000000000000000..d9251a93b40b2cc --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-06-09-23-38-08.gh-issue-151159.ds-9f8.rst @@ -0,0 +1 @@ +Update macOS installer to use OpenSSL 3.5.7. diff --git a/Misc/NEWS.d/next/Security/2026-06-16-14-58-02.gh-issue-151544._bexVy.rst b/Misc/NEWS.d/next/Security/2026-06-16-14-58-02.gh-issue-151544._bexVy.rst new file mode 100644 index 000000000000000..418e3b4b9677943 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-06-16-14-58-02.gh-issue-151544._bexVy.rst @@ -0,0 +1,4 @@ +:file:`Modules/Setup.local` is no longer used as a landmark to discover +whether Python is running in a source tree, as it could potentially affect +actual installs. The :file:`pybuilddir.txt` file is now the sole indicator +of running in a source tree. diff --git a/Misc/NEWS.d/next/Tests/2026-04-24-01-38-56.gh-issue-148853._uM4_Q.rst b/Misc/NEWS.d/next/Tests/2026-04-24-01-38-56.gh-issue-148853._uM4_Q.rst new file mode 100644 index 000000000000000..9d3fbc2590dc7a2 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2026-04-24-01-38-56.gh-issue-148853._uM4_Q.rst @@ -0,0 +1,2 @@ +Fix tests failing on FreeBSD in test.support's +in_systemd_nspawn_sync_suppressed() due to unreadable /run directory. diff --git a/Misc/NEWS.d/next/Tests/2026-06-06-16-22-00.gh-issue-150966.7N9x5Q.rst b/Misc/NEWS.d/next/Tests/2026-06-06-16-22-00.gh-issue-150966.7N9x5Q.rst new file mode 100644 index 000000000000000..3bbb471163d64e1 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2026-06-06-16-22-00.gh-issue-150966.7N9x5Q.rst @@ -0,0 +1,2 @@ +Avoid prematurely terminating failing live sampling profiler test targets, +which made stderr assertions flaky on ASAN buildbots. diff --git a/Misc/NEWS.d/next/Tests/2026-06-09-11-52-52.gh-issue-151130.1vslPH.rst b/Misc/NEWS.d/next/Tests/2026-06-09-11-52-52.gh-issue-151130.1vslPH.rst new file mode 100644 index 000000000000000..0333e66446ce161 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2026-06-09-11-52-52.gh-issue-151130.1vslPH.rst @@ -0,0 +1 @@ +Add more tests for ``PyWeakref_*`` C API. diff --git a/Misc/NEWS.d/next/Windows/2026-04-26-23-14-45.gh-issue-149029.oPTXP4.rst b/Misc/NEWS.d/next/Windows/2026-04-26-23-14-45.gh-issue-149029.oPTXP4.rst deleted file mode 100644 index 6c4c6403b989847..000000000000000 --- a/Misc/NEWS.d/next/Windows/2026-04-26-23-14-45.gh-issue-149029.oPTXP4.rst +++ /dev/null @@ -1 +0,0 @@ -Update Windows installer to ship with SQLite 3.53.1. diff --git a/Misc/NEWS.d/next/Windows/2026-06-09-11-40-48.gh-issue-151159.JKVfme.rst b/Misc/NEWS.d/next/Windows/2026-06-09-11-40-48.gh-issue-151159.JKVfme.rst new file mode 100644 index 000000000000000..ad1be115db5ce8f --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-06-09-11-40-48.gh-issue-151159.JKVfme.rst @@ -0,0 +1 @@ +Updated bundled version of OpenSSL to 3.5.7. diff --git a/Misc/NEWS.d/next/Windows/2026-06-09-11-55-41.gh-issue-151163.oizZYV.rst b/Misc/NEWS.d/next/Windows/2026-06-09-11-55-41.gh-issue-151163.oizZYV.rst new file mode 100644 index 000000000000000..580a87400862c52 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-06-09-11-55-41.gh-issue-151163.oizZYV.rst @@ -0,0 +1 @@ +Updated Windows builds to include SQLite version 3.53.2. diff --git a/Misc/NEWS.d/next/macOS/2026-04-26-23-15-09.gh-issue-149029.Lsx--T.rst b/Misc/NEWS.d/next/macOS/2026-04-26-23-15-09.gh-issue-149029.Lsx--T.rst deleted file mode 100644 index 157a70f5e3cefc9..000000000000000 --- a/Misc/NEWS.d/next/macOS/2026-04-26-23-15-09.gh-issue-149029.Lsx--T.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS installer to ship with SQLite version 3.53.1. diff --git a/Misc/NEWS.d/next/macOS/2026-06-09-11-52-35.gh-issue-151163.RlPXHq.rst b/Misc/NEWS.d/next/macOS/2026-06-09-11-52-35.gh-issue-151163.RlPXHq.rst new file mode 100644 index 000000000000000..7e9bf6f4587974e --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2026-06-09-11-52-35.gh-issue-151163.RlPXHq.rst @@ -0,0 +1 @@ +Updated macOS installer to include SQLite version 3.53.2. diff --git a/Misc/externals.spdx.json b/Misc/externals.spdx.json index 080330c1cb75a53..523d20259adaaa9 100644 --- a/Misc/externals.spdx.json +++ b/Misc/externals.spdx.json @@ -70,42 +70,42 @@ "checksums": [ { "algorithm": "SHA256", - "checksumValue": "cf01946f3a61ba45a08c1e35b223d41d23963e3df5ac98cbad6c8fa5a81070ca" + "checksumValue": "ca94e7c6c223d9caf77bb51aac5949186379608ea2a0cad3aa8bdf31856912e9" } ], - "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/openssl-3.5.6.tar.gz", + "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/openssl-3.5.7.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:openssl:openssl:3.5.6:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:openssl:openssl:3.5.7:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], "licenseConcluded": "NOASSERTION", "name": "openssl", "primaryPackagePurpose": "SOURCE", - "versionInfo": "3.5.6" + "versionInfo": "3.5.7" }, { "SPDXID": "SPDXRef-PACKAGE-sqlite", "checksums": [ { "algorithm": "SHA256", - "checksumValue": "15e8fc7dc059f7b156e53629540951c2691acd71e027f6f8f66dacab5c66c884" + "checksumValue": "53f8711811090cc4d9ffc624c360f81e7b409763b145ab2e948998f1a0d6a612" } ], - "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/sqlite-3.53.1.0.tar.gz", + "downloadLocation": "https://github.com/python/cpython-source-deps/archive/refs/tags/sqlite-3.53.2.0.tar.gz", "externalRefs": [ { "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:sqlite:sqlite:3.53.1.0:*:*:*:*:*:*:*", + "referenceLocator": "cpe:2.3:a:sqlite:sqlite:3.53.2.0:*:*:*:*:*:*:*", "referenceType": "cpe23Type" } ], "licenseConcluded": "NOASSERTION", "name": "sqlite", "primaryPackagePurpose": "SOURCE", - "versionInfo": "3.53.1.0" + "versionInfo": "3.53.2.0" }, { "SPDXID": "SPDXRef-PACKAGE-tcl", diff --git a/Misc/python.man b/Misc/python.man index a65fb98a697b503..5e4f3c3debe9358 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -1,4 +1,4 @@ -.TH PYTHON "1" +.TH PYTHON 1 .\" To view this file while editing, run it through groff: .\" groff -Tascii -man python.man | less @@ -162,7 +162,7 @@ compilation options). Ignore environment variables like PYTHONPATH and PYTHONHOME that modify the behavior of the interpreter. .TP -.B \-h ", " \-? ", "\-\-help +.BR \-h ", " \-? ", " \-\-help Prints the usage for the interpreter executable and exits. .TP .B "\-\-help\-env" @@ -171,7 +171,6 @@ Prints help about Python-specific environment variables and exits. .B "\-\-help\-xoptions" Prints help about implementation-specific \fB\-X\fP options and exits. .TP -.TP .B "\-\-help\-all" Prints complete usage information and exits. .TP @@ -243,7 +242,7 @@ twice, print a message for each file that is checked for when searching for a module. Also provides information on module cleanup at exit. .TP -.B \-V ", " \-\-version +.BR \-V ", " \-\-version Prints the Python version number of the executable and exits. When given twice, print more information about the build. @@ -255,23 +254,38 @@ to The simplest settings apply a particular action unconditionally to all warnings emitted by a process (even those that are otherwise ignored by default): - - -Wdefault # Warn once per call location - -Werror # Convert to exceptions - -Walways # Warn every time - -Wall # Same as -Walways - -Wmodule # Warn once per calling module - -Wonce # Warn once per Python process - -Wignore # Never warn - +.RS +.TP +.B \-Wdefault +Warn once per call location +.TP +.B \-Werror +Convert to exceptions +.TP +.B \-Walways +Warn every time +.TP +.B \-Wall +Same as \-Walways +.TP +.B \-Wmodule +Warn once per calling module +.TP +.B \-Wonce +Warn once per Python process +.TP +.B \-Wignore +Never warn +.RE +.IP The action names can be abbreviated as desired and the interpreter will resolve them to the appropriate action name. For example, .B \-Wi is the same as -.B \-Wignore . +.BR \-Wignore . The full form of argument is: -.IB action:message:category:module:lineno +.IB action : message : category : module : lineno Empty fields match all values; trailing empty fields may be omitted. For example @@ -457,7 +471,7 @@ is an empty string; if is used, .I sys.argv[0] contains the string -.I '\-c'. +.RI ' \-c '. Note that options interpreted by the Python interpreter itself are not placed in .IR sys.argv . @@ -531,12 +545,12 @@ the \fB\-d\fP option. If set to an integer, it is equivalent to specifying \fB\-d\fP multiple times. .IP PYTHONEXECUTABLE If this environment variable is set, -.IB sys.argv[0] +.I sys.argv[0] will be set to its value instead of the value got through the C runtime. Only works on Mac OS X. .IP PYTHONFAULTHANDLER If this environment variable is set to a non-empty string, -.IR faulthandler.enable() +.I faulthandler.enable() is called at startup: install a handler for SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL signals to dump the Python traceback. .IP @@ -584,8 +598,8 @@ purpose is to allow repeatable hashing, such as for selftests for the interpreter itself, or to allow a cluster of python processes to share hash values. -The integer must be a decimal number in the range [0,4294967295]. Specifying -the value 0 will disable hash randomization. +The integer must be a decimal number in the range [0,4\|294\|967\|295]. +Specifying the value 0 will disable hash randomization. .IP PYTHONHOME Change the location of the standard Python libraries. By default, the libraries are searched in ${prefix}/lib/python and @@ -607,16 +621,16 @@ This is equivalent to the \fB\-X int_max_str_digits=\fINUMBER\fR option. .IP PYTHONIOENCODING If this is set before running the interpreter, it overrides the encoding used for stdin/stdout/stderr, in the syntax -.IB encodingname ":" errorhandler +.IB encodingname : errorhandler The -.IB errorhandler +.I errorhandler part is optional and has the same meaning as in str.encode. For stderr, the -.IB errorhandler +.I errorhandler part is ignored; the handler will always be \'backslashreplace\'. .IP PYTHONMALLOC Set the Python memory allocators and/or install debug hooks. The available memory allocators are -.IR malloc +.I malloc and .IR pymalloc . The available debug hooks are @@ -626,7 +640,7 @@ and .IR pymalloc_debug . .IP When Python is compiled in debug mode, the default is -.IR pymalloc_debug +.I pymalloc_debug and the debug hooks are automatically used. Otherwise, the default is .IR pymalloc . .IP PYTHONMALLOCSTATS @@ -707,14 +721,14 @@ Python memory allocations using the tracemalloc module. .IP The value of the variable is the maximum number of frames stored in a traceback of a trace. For example, -.IB PYTHONTRACEMALLOC=1 +.I PYTHONTRACEMALLOC=1 stores only the most recent frame. .IP PYTHONUNBUFFERED If this is set to a non-empty string it is equivalent to specifying the \fB\-u\fP option. .IP PYTHONUSERBASE Defines the user base directory, which is used to compute the path of the user -.IR site\-packages +.I site\-packages directory and installation paths for .IR "python \-m pip install \-\-user" . .IP PYTHONUTF8 @@ -750,17 +764,17 @@ This is equivalent to the \fB\-X presite=\fImodule\fR option. .SH AUTHOR The Python Software Foundation: https://www.python.org/psf/ .SH INTERNET RESOURCES -Main website: https://www.python.org/ +Main website: https://www.python.org/ .br -Documentation: https://docs.python.org/ +Documentation: https://docs.python.org/ .br -Developer resources: https://devguide.python.org/ +Developer resources: https://devguide.python.org/ .br -Downloads: https://www.python.org/downloads/ +Downloads: https://www.python.org/downloads/ .br -Module repository: https://pypi.org/ +Module repository: https://pypi.org/ .br -Newsgroups: comp.lang.python, comp.lang.python.announce +Newsgroups: comp.lang.python, comp.lang.python.announce .SH LICENSING Python is distributed under an Open Source license. See the file "LICENSE" in the Python source distribution for information on terms & diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 8fd7aba09241e63..d59a7c788fa9e02 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -1813,7 +1813,6 @@ [const.METH_COEXIST] added = '3.2' # METH_STACKLESS is undocumented -# METH_FASTCALL is not part of limited API. # The following are defined in private headers, but historically # they were exported as part of the stable ABI. @@ -2149,8 +2148,6 @@ # New method flags in 3.7 (PEP 590): -[const.METH_FASTCALL] - added = '3.7' [const.METH_METHOD] added = '3.7' @@ -2300,6 +2297,10 @@ [data.PyStructSequence_UnnamedField] added = '3.11' +# Added in 3.7 but in the Stable ABI from 3.10 +[const.METH_FASTCALL] + added = '3.10' + # Add stable Py_buffer API in Python 3.11 (https://bugs.python.org/issue45459) [struct.Py_buffer] added = '3.11' diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index c3dd47a5e40a675..8efea27824f0e88 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -173,8 +173,8 @@ @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c @MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c _testinternalcapi/tuple.c -@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/modsupport.c _testcapi/monitoring.c _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c _testcapi/module.c -@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/slots.c _testlimitedcapi/sys.c _testlimitedcapi/threadstate.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c +@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/modsupport.c _testcapi/monitoring.c _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c _testcapi/module.c _testcapi/weakref.c +@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/slots.c _testlimitedcapi/sys.c _testlimitedcapi/threadstate.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c _testlimitedcapi/weakref.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index 4cf8beed9ee3eba..9db3ac39da52099 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -108,6 +108,7 @@ typedef struct { typedef struct { PyObject_HEAD bz_stream bzs; + int bzerror; char eof; /* Py_T_BOOL expects a char */ PyObject *unused_data; char needs_input; @@ -435,8 +436,11 @@ decompress_buf(BZ2Decompressor *d, Py_ssize_t max_length) d->bzs_avail_in_real += bzs->avail_in; - if (catch_bz2_error(bzret)) + if (catch_bz2_error(bzret)) { + d->bzerror = bzret; + FT_ATOMIC_STORE_CHAR_RELAXED(d->needs_input, 0); goto error; + } if (bzret == BZ_STREAM_END) { FT_ATOMIC_STORE_CHAR_RELAXED(d->eof, 1); break; @@ -607,10 +611,17 @@ _bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, PyObject *result = NULL; PyMutex_Lock(&self->mutex); - if (self->eof) + if (self->eof) { PyErr_SetString(PyExc_EOFError, "End of stream already reached"); - else + } + else if (self->bzerror) { + // Re-entering BZ2_bzDecompress() after an error can write out of bounds. + PyErr_SetString(PyExc_ValueError, + "Decompressor is unusable after a previous error"); + } + else { result = decompress(self, data->buf, data->len, max_length); + } PyMutex_Unlock(&self->mutex); return result; } @@ -638,6 +649,7 @@ _bz2_BZ2Decompressor_impl(PyTypeObject *type) } self->mutex = (PyMutex){0}; + self->bzerror = 0; self->needs_input = 1; self->bzs_avail_in_real = 0; self->input_buffer = NULL; diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index c5d4879312bc8a8..e96a546a818d3d7 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1251,7 +1251,7 @@ _collections.deque.index as deque_index deque: dequeobject value as v: object start: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='0') = NULL - stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='Py_SIZE(deque)') = NULL + stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='PY_SSIZE_T_MAX') = NULL / Return first index of value. @@ -1262,7 +1262,7 @@ Raises ValueError if the value is not present. static PyObject * deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start, Py_ssize_t stop) -/*[clinic end generated code: output=df45132753175ef9 input=90f48833a91e1743]*/ +/*[clinic end generated code: output=df45132753175ef9 input=1c3b19632cf3484f]*/ { Py_ssize_t i, n; PyObject *item; @@ -1270,22 +1270,23 @@ deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start, Py_ssize_t index = deque->leftindex; size_t start_state = deque->state; int cmp; + Py_ssize_t size = Py_SIZE(deque); if (start < 0) { - start += Py_SIZE(deque); + start += size; if (start < 0) start = 0; } if (stop < 0) { - stop += Py_SIZE(deque); + stop += size; if (stop < 0) stop = 0; } - if (stop > Py_SIZE(deque)) - stop = Py_SIZE(deque); + if (stop > size) + stop = size; if (start > stop) start = stop; - assert(0 <= start && start <= stop && stop <= Py_SIZE(deque)); + assert(0 <= start && start <= stop && stop <= size); for (i=0 ; i < start - BLOCKLEN ; i += BLOCKLEN) { b = b->rightlink; @@ -2589,7 +2590,7 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping, if (key == NULL) break; - hash = _PyObject_HashFast(key); + hash = _PyObject_HashDictKey(key); if (hash == -1) { goto done; } diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index e453cfeec9cc8ca..ccc57e347b07acf 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -168,8 +168,9 @@ _ctypes_get_errobj(ctypes_state *st, int **pspace) } else { void *space = PyMem_Calloc(2, sizeof(int)); - if (space == NULL) - return NULL; + if (space == NULL) { + return PyErr_NoMemory(); + } errobj = PyCapsule_New(space, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor); if (errobj == NULL) { PyMem_Free(space); diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 59af7afcfcc644e..82b1f898a3c6741 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -126,8 +126,8 @@ get_module_state(PyObject *module) #define INTERP_KEY ((PyObject *)&_Py_ID(cached_datetime_module)) -static PyObject * -get_current_module(PyInterpreterState *interp) +static int +get_current_module(PyInterpreterState *interp, PyObject **p_mod) { PyObject *mod = NULL; @@ -139,20 +139,24 @@ get_current_module(PyInterpreterState *interp) if (PyDict_GetItemRef(dict, INTERP_KEY, &ref) < 0) { goto error; } - if (ref != NULL) { - if (ref != Py_None) { - (void)PyWeakref_GetRef(ref, &mod); - if (mod == Py_None) { - Py_CLEAR(mod); - } + if (ref != NULL && ref != Py_None) { + if (PyWeakref_GetRef(ref, &mod) < 0) { Py_DECREF(ref); + goto error; + } + if (mod == Py_None) { + Py_CLEAR(mod); } + Py_DECREF(ref); } - return mod; + assert(!PyErr_Occurred()); + *p_mod = mod; + return mod != NULL; error: assert(PyErr_Occurred()); - return NULL; + *p_mod = NULL; + return -1; } static PyModuleDef datetimemodule; @@ -161,22 +165,26 @@ static datetime_state * _get_current_state(PyObject **p_mod) { PyInterpreterState *interp = PyInterpreterState_Get(); - PyObject *mod = get_current_module(interp); + PyObject *mod; + if (get_current_module(interp, &mod) < 0) { + goto error; + } if (mod == NULL) { - assert(!PyErr_Occurred()); - if (PyErr_Occurred()) { - return NULL; - } /* The static types can outlive the module, * so we must re-import the module. */ mod = PyImport_ImportModule("_datetime"); if (mod == NULL) { - return NULL; + goto error; } } datetime_state *st = get_module_state(mod); *p_mod = mod; return st; + +error: + assert(PyErr_Occurred()); + *p_mod = NULL; + return NULL; } #define GET_CURRENT_STATE(MOD_VAR) \ @@ -1509,7 +1517,7 @@ get_tzinfo_member(PyObject *self) * this returns NULL. Else result is returned. */ static PyObject * -call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) +call_tzinfo_method(PyObject *tzinfo, PyObject *name, PyObject *tzinfoarg) { PyObject *offset; @@ -1519,7 +1527,7 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) if (tzinfo == Py_None) Py_RETURN_NONE; - offset = PyObject_CallMethod(tzinfo, name, "O", tzinfoarg); + offset = PyObject_CallMethodOneArg(tzinfo, name, tzinfoarg); if (offset == Py_None || offset == NULL) return offset; if (PyDelta_Check(offset)) { @@ -1536,7 +1544,7 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) } else { PyErr_Format(PyExc_TypeError, - "tzinfo.%s() must return None or " + "tzinfo.%U() must return None or " "timedelta, not '%.200s'", name, Py_TYPE(offset)->tp_name); Py_DECREF(offset); @@ -1557,7 +1565,7 @@ call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) static PyObject * call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg) { - return call_tzinfo_method(tzinfo, "utcoffset", tzinfoarg); + return call_tzinfo_method(tzinfo, &_Py_ID(utcoffset), tzinfoarg); } /* Call tzinfo.dst(tzinfoarg), and extract an integer from the @@ -1571,7 +1579,7 @@ call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg) static PyObject * call_dst(PyObject *tzinfo, PyObject *tzinfoarg) { - return call_tzinfo_method(tzinfo, "dst", tzinfoarg); + return call_tzinfo_method(tzinfo, &_Py_ID(dst), tzinfoarg); } /* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be @@ -2128,8 +2136,11 @@ delta_to_microseconds(PyDateTime_Delta *self) PyObject *x3 = NULL; PyObject *result = NULL; - PyObject *current_mod = NULL; + PyObject *current_mod; datetime_state *st = GET_CURRENT_STATE(current_mod); + if (st == NULL) { + return NULL; + } x1 = PyLong_FromLong(GET_TD_DAYS(self)); if (x1 == NULL) @@ -2207,8 +2218,11 @@ microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type) PyObject *num = NULL; PyObject *result = NULL; - PyObject *current_mod = NULL; + PyObject *current_mod; datetime_state *st = GET_CURRENT_STATE(current_mod); + if (st == NULL) { + return NULL; + } tuple = checked_divmod(pyus, CONST_US_PER_SECOND(st)); if (tuple == NULL) { @@ -2815,8 +2829,11 @@ delta_new_impl(PyTypeObject *type, PyObject *days, PyObject *seconds, { PyObject *self = NULL; - PyObject *current_mod = NULL; + PyObject *current_mod; datetime_state *st = GET_CURRENT_STATE(current_mod); + if (st == NULL) { + return NULL; + } PyObject *x = NULL; /* running sum of microseconds */ PyObject *y = NULL; /* temp sum of microseconds */ @@ -3014,8 +3031,12 @@ delta_total_seconds(PyObject *op, PyObject *Py_UNUSED(dummy)) if (total_microseconds == NULL) return NULL; - PyObject *current_mod = NULL; + PyObject *current_mod; datetime_state *st = GET_CURRENT_STATE(current_mod); + if (st == NULL) { + Py_DECREF(total_microseconds); + return NULL; + } total_seconds = PyNumber_TrueDivide(total_microseconds, CONST_US_PER_SECOND(st)); @@ -3867,8 +3888,11 @@ date_isocalendar(PyObject *self, PyObject *Py_UNUSED(dummy)) week = 0; } - PyObject *current_mod = NULL; + PyObject *current_mod; datetime_state *st = GET_CURRENT_STATE(current_mod); + if (st == NULL) { + return NULL; + } PyObject *v = iso_calendar_date_new_impl(ISOCALENDAR_DATE_TYPE(st), year, week + 1, day + 1); @@ -6800,8 +6824,11 @@ local_timezone(PyDateTime_DateTime *utc_time) PyObject *one_second; PyObject *seconds; - PyObject *current_mod = NULL; + PyObject *current_mod; datetime_state *st = GET_CURRENT_STATE(current_mod); + if (st == NULL) { + return NULL; + } delta = datetime_subtract((PyObject *)utc_time, CONST_EPOCH(st)); RELEASE_CURRENT_STATE(st, current_mod); @@ -7047,8 +7074,11 @@ datetime_timestamp(PyObject *op, PyObject *Py_UNUSED(dummy)) PyObject *result; if (HASTZINFO(self) && self->tzinfo != Py_None) { - PyObject *current_mod = NULL; + PyObject *current_mod; datetime_state *st = GET_CURRENT_STATE(current_mod); + if (st == NULL) { + return NULL; + } PyObject *delta; delta = datetime_subtract(op, CONST_EPOCH(st)); @@ -7581,9 +7611,8 @@ _datetime_exec(PyObject *module) datetime_state *st = get_module_state(module); PyInterpreterState *interp = PyInterpreterState_Get(); - PyObject *old_module = get_current_module(interp); - if (PyErr_Occurred()) { - assert(old_module == NULL); + PyObject *old_module; + if (get_current_module(interp, &old_module) < 0) { goto error; } /* We actually set the "current" module right before a successful return. */ diff --git a/Modules/_interpchannelsmodule.c b/Modules/_interpchannelsmodule.c index c6d107d243dda0e..3614890757d69da 100644 --- a/Modules/_interpchannelsmodule.c +++ b/Modules/_interpchannelsmodule.c @@ -921,7 +921,8 @@ static _channelends * _channelends_new(void) { _channelends *ends = GLOBAL_MALLOC(_channelends); - if (ends== NULL) { + if (ends == NULL) { + PyErr_NoMemory(); return NULL; } ends->numsendopen = 0; @@ -1115,6 +1116,7 @@ _channel_new(PyThread_type_lock mutex, struct _channeldefaults defaults) assert(check_unbound(defaults.unboundop)); _channel_state *chan = GLOBAL_MALLOC(_channel_state); if (chan == NULL) { + PyErr_NoMemory(); return NULL; } chan->mutex = mutex; @@ -1313,6 +1315,7 @@ _channelref_new(int64_t cid, _channel_state *chan) { _channelref *ref = GLOBAL_MALLOC(_channelref); if (ref == NULL) { + PyErr_NoMemory(); return NULL; } ref->cid = cid; @@ -1698,6 +1701,7 @@ _channel_set_closing(_channelref *ref, PyThread_type_lock mutex) { } chan->closing = GLOBAL_MALLOC(struct _channel_closing); if (chan->closing == NULL) { + PyErr_NoMemory(); goto done; } chan->closing->ref = ref; diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h index 9407076b850cee9..8d59bda5f74b386 100644 --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -666,7 +666,9 @@ _io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) goto exit; } skip_optional_pos: + Py_BEGIN_CRITICAL_SECTION(self); return_value = _io_TextIOWrapper___init___impl((textio *)self, buffer, encoding, errors, newline, line_buffering, write_through); + Py_END_CRITICAL_SECTION(); exit: return return_value; @@ -1329,4 +1331,4 @@ _io_TextIOWrapper__CHUNK_SIZE_set(PyObject *self, PyObject *value, void *Py_UNUS return return_value; } -/*[clinic end generated code: output=f900b42090c9781c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8c571c9dba87d2b1 input=a9049054013a1b77]*/ diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index e80b75066c59a61..24e08cec88f2a3a 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -672,6 +672,8 @@ struct textio int ok; /* initialized? */ int detached; Py_ssize_t chunk_size; + /* Use helpers buffer_*() functions to access buffer; many operations can set it to + NULL (see gh-143008, gh-142594). */ PyObject *buffer; PyObject *encoding; PyObject *encoder; @@ -729,6 +731,67 @@ struct textio #define textio_CAST(op) ((textio *)(op)) +/* Helpers to safely operate on self->buffer. + + self->buffer can be detached (set to NULL) by any user code that is called + leading to NULL pointer dereferences (see gh-143008, gh-142594). Protect + against that by using helpers to check self->buffer validity at callsites. */ +static PyObject * +buffer_access_safe(textio *self) +{ + /* Check self->buffer directly but match errors of CHECK_ATTACHED since this + is called during construction and finalization where self->ok == 0. */ + if (self->buffer == NULL) { + if (self->ok <= 0) { + PyErr_SetString(PyExc_ValueError, + "I/O operation on uninitialized object"); + } + else { + PyErr_SetString(PyExc_ValueError, + "underlying buffer has been detached"); + } + return NULL; + } + + /* Returning a borrowed reference is safe since TextIOWrapper methods are + protected by critical sections. */ + _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self); + return self->buffer; +} + +static PyObject * +buffer_getattr(textio *self, PyObject *attr_name) +{ + PyObject *buffer = buffer_access_safe(self); + if (buffer == NULL) { + return NULL; + } + + return PyObject_GetAttr(buffer, attr_name); +} + +static PyObject * +buffer_callmethod_noargs(textio *self, PyObject *name) +{ + PyObject *buffer = buffer_access_safe(self); + if (buffer == NULL) { + return NULL; + } + + return PyObject_CallMethodNoArgs(buffer, name); +} + +static PyObject * +buffer_callmethod_onearg(textio *self, PyObject *name, PyObject *arg) +{ + PyObject *buffer = buffer_access_safe(self); + if (buffer == NULL) { + return NULL; + } + + return PyObject_CallMethodOneArg(buffer, name, arg); +} + static void textiowrapper_set_decoded_chars(textio *self, PyObject *chars); @@ -898,7 +961,7 @@ _textiowrapper_set_decoder(textio *self, PyObject *codec_info, PyObject *res; int r; - res = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(readable)); + res = buffer_callmethod_noargs(self, &_Py_ID(readable)); if (res == NULL) return -1; @@ -954,7 +1017,7 @@ _textiowrapper_set_encoder(textio *self, PyObject *codec_info, PyObject *res; int r; - res = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(writable)); + res = buffer_callmethod_noargs(self, &_Py_ID(writable)); if (res == NULL) return -1; @@ -1000,8 +1063,7 @@ _textiowrapper_fix_encoder_state(textio *self) self->encoding_start_of_stream = 1; - PyObject *cookieObj = PyObject_CallMethodNoArgs( - self->buffer, &_Py_ID(tell)); + PyObject *cookieObj = buffer_callmethod_noargs(self, &_Py_ID(tell)); if (cookieObj == NULL) { return -1; } @@ -1061,6 +1123,7 @@ io_check_errors(PyObject *errors) /*[clinic input] +@critical_section _io.TextIOWrapper.__init__ buffer: object encoding: str(accept={str, NoneType}) = None @@ -1104,7 +1167,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, const char *encoding, PyObject *errors, const char *newline, int line_buffering, int write_through) -/*[clinic end generated code: output=72267c0c01032ed2 input=e6cfaaaf6059d4f5]*/ +/*[clinic end generated code: output=72267c0c01032ed2 input=0f077220214c40a4]*/ { PyObject *raw, *codec_info = NULL; PyObject *res; @@ -1568,11 +1631,14 @@ _io_TextIOWrapper_detach_impl(textio *self) /*[clinic end generated code: output=7ba3715cd032d5f2 input=c908a3b4ef203b0f]*/ { PyObject *buffer; - CHECK_ATTACHED(self); if (_PyFile_Flush((PyObject *)self) < 0) { return NULL; } - buffer = self->buffer; + /* _PyFile_Flush could detach before returning; raise an exception. */ + buffer = buffer_access_safe(self); + if (buffer == NULL) { + return NULL; + } self->buffer = NULL; self->detached = 1; return buffer; @@ -1641,7 +1707,7 @@ _textiowrapper_writeflush(textio *self) PyObject *ret; do { - ret = PyObject_CallMethodOneArg(self->buffer, &_Py_ID(write), b); + ret = buffer_callmethod_onearg(self, &_Py_ID(write), b); } while (ret == NULL && _PyIO_trap_eintr()); Py_DECREF(b); // NOTE: We cleared buffer but we don't know how many bytes are actually written @@ -1787,7 +1853,8 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) } if (needflush) { - if (_PyFile_Flush(self->buffer) < 0) { + PyObject *buffer = buffer_access_safe(self); + if (buffer == NULL || _PyFile_Flush(buffer) < 0) { return NULL; } } @@ -1917,9 +1984,10 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) if (chunk_size == NULL) goto fail; - input_chunk = PyObject_CallMethodOneArg(self->buffer, - (self->has_read1 ? &_Py_ID(read1): &_Py_ID(read)), - chunk_size); + input_chunk = buffer_callmethod_onearg(self, + (self->has_read1 ? &_Py_ID(read1) : + &_Py_ID(read)), + chunk_size); Py_DECREF(chunk_size); if (input_chunk == NULL) goto fail; @@ -2003,7 +2071,7 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) if (n < 0) { /* Read everything */ - PyObject *bytes = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(read)); + PyObject *bytes = buffer_callmethod_noargs(self, &_Py_ID(read)); PyObject *decoded; if (bytes == NULL) goto fail; @@ -2600,7 +2668,11 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) Py_DECREF(res); } - res = _PyObject_CallMethod(self->buffer, &_Py_ID(seek), "ii", 0, 2); + PyObject *buf = buffer_access_safe(self); + if (buf == NULL) { + goto fail; + } + res = _PyObject_CallMethod(buf, &_Py_ID(seek), "ii", 0, 2); Py_CLEAR(cookieObj); if (res == NULL) goto fail; @@ -2648,7 +2720,7 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) posobj = PyLong_FromOff_t(cookie.start_pos); if (posobj == NULL) goto fail; - res = PyObject_CallMethodOneArg(self->buffer, &_Py_ID(seek), posobj); + res = buffer_callmethod_onearg(self, &_Py_ID(seek), posobj); Py_DECREF(posobj); if (res == NULL) goto fail; @@ -2665,8 +2737,15 @@ _io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) if (cookie.chars_to_skip) { /* Just like _read_chunk, feed the decoder and save a snapshot. */ - PyObject *input_chunk = _PyObject_CallMethod(self->buffer, &_Py_ID(read), - "i", cookie.bytes_to_feed); + PyObject *bytes_to_feed = PyLong_FromLong(cookie.bytes_to_feed); + if (bytes_to_feed == NULL) { + goto fail; + } + PyObject *input_chunk = buffer_callmethod_onearg(self, + &_Py_ID(read), + bytes_to_feed); + Py_DECREF(bytes_to_feed); + PyObject *decoded; if (input_chunk == NULL) @@ -2765,7 +2844,7 @@ _io_TextIOWrapper_tell_impl(textio *self) goto fail; } - posobj = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(tell)); + posobj = buffer_callmethod_noargs(self, &_Py_ID(tell)); if (posobj == NULL) goto fail; @@ -2975,7 +3054,7 @@ _io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos) return NULL; } - return PyObject_CallMethodOneArg(self->buffer, &_Py_ID(truncate), pos); + return buffer_callmethod_onearg(self, &_Py_ID(truncate), pos); } static PyObject * @@ -3057,8 +3136,7 @@ static PyObject * _io_TextIOWrapper_fileno_impl(textio *self) /*[clinic end generated code: output=21490a4c3da13e6c input=515e1196aceb97ab]*/ { - CHECK_ATTACHED(self); - return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(fileno)); + return buffer_callmethod_noargs(self, &_Py_ID(fileno)); } /*[clinic input] @@ -3070,8 +3148,7 @@ static PyObject * _io_TextIOWrapper_seekable_impl(textio *self) /*[clinic end generated code: output=ab223dbbcffc0f00 input=71c4c092736c549b]*/ { - CHECK_ATTACHED(self); - return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(seekable)); + return buffer_callmethod_noargs(self, &_Py_ID(seekable)); } /*[clinic input] @@ -3083,8 +3160,7 @@ static PyObject * _io_TextIOWrapper_readable_impl(textio *self) /*[clinic end generated code: output=72ff7ba289a8a91b input=80438d1f01b0a89b]*/ { - CHECK_ATTACHED(self); - return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(readable)); + return buffer_callmethod_noargs(self, &_Py_ID(readable)); } /*[clinic input] @@ -3096,8 +3172,7 @@ static PyObject * _io_TextIOWrapper_writable_impl(textio *self) /*[clinic end generated code: output=a728c71790d03200 input=9d6c22befb0c340a]*/ { - CHECK_ATTACHED(self); - return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(writable)); + return buffer_callmethod_noargs(self, &_Py_ID(writable)); } /*[clinic input] @@ -3109,8 +3184,7 @@ static PyObject * _io_TextIOWrapper_isatty_impl(textio *self) /*[clinic end generated code: output=12be1a35bace882e input=7f83ff04d4d1733d]*/ { - CHECK_ATTACHED(self); - return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(isatty)); + return buffer_callmethod_noargs(self, &_Py_ID(isatty)); } /*[clinic input] @@ -3127,7 +3201,7 @@ _io_TextIOWrapper_flush_impl(textio *self) self->telling = self->seekable; if (_textiowrapper_writeflush(self) < 0) return NULL; - return PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(flush)); + return buffer_callmethod_noargs(self, &_Py_ID(flush)); } /*[clinic input] @@ -3160,8 +3234,9 @@ _io_TextIOWrapper_close_impl(textio *self) else { PyObject *exc = NULL; if (self->finalizing) { - res = PyObject_CallMethodOneArg(self->buffer, &_Py_ID(_dealloc_warn), - (PyObject *)self); + res = buffer_callmethod_onearg(self, + &_Py_ID(_dealloc_warn), + (PyObject *)self); if (res) { Py_DECREF(res); } @@ -3173,7 +3248,7 @@ _io_TextIOWrapper_close_impl(textio *self) exc = PyErr_GetRaisedException(); } - res = PyObject_CallMethodNoArgs(self->buffer, &_Py_ID(close)); + res = buffer_callmethod_noargs(self, &_Py_ID(close)); if (exc != NULL) { _PyErr_ChainExceptions1(exc); Py_CLEAR(res); @@ -3241,8 +3316,7 @@ static PyObject * _io_TextIOWrapper_name_get_impl(textio *self) /*[clinic end generated code: output=8c2f1d6d8756af40 input=26ecec9b39e30e07]*/ { - CHECK_ATTACHED(self); - return PyObject_GetAttr(self->buffer, &_Py_ID(name)); + return buffer_getattr(self, &_Py_ID(name)); } /*[clinic input] @@ -3255,8 +3329,17 @@ static PyObject * _io_TextIOWrapper_closed_get_impl(textio *self) /*[clinic end generated code: output=b49b68f443a85e3c input=7dfcf43f63c7003d]*/ { - CHECK_ATTACHED(self); - return PyObject_GetAttr(self->buffer, &_Py_ID(closed)); + /* If partially constructed or deconstructed, return that the underlying + buffer is closed. + + The code managing the transition is responsible for closing. The closed + attribute is often called in re-initalization, as part of repr in error + cases, and when the I/O stack is garbage collected. */ + if (self->ok <= 0) { + Py_RETURN_TRUE; + } + + return buffer_getattr(self, &_Py_ID(closed)); } /*[clinic input] diff --git a/Modules/_json.c b/Modules/_json.c index 6c4f38834631d30..b057b56b2f9f8d9 100644 --- a/Modules/_json.c +++ b/Modules/_json.c @@ -11,6 +11,8 @@ #include "Python.h" #include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST() +#include "pycore_dict.h" // _PyDict_SetItem_Take2() +#include "pycore_list.h" // _PyList_AppendTakeRef() #include "pycore_global_strings.h" // _Py_ID() #include "pycore_pyerrors.h" // _PyErr_FormatNote #include "pycore_runtime.h" // _PyRuntime @@ -752,7 +754,6 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss const void *str; int kind; Py_ssize_t end_idx; - PyObject *val = NULL; PyObject *rval = NULL; PyObject *key = NULL; int has_pairs_hook = (s->object_pairs_hook != Py_None); @@ -802,13 +803,16 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss while (idx <= end_idx && IS_WHITESPACE(PyUnicode_READ(kind, str, idx))) idx++; /* read any JSON term */ - val = scan_once_unicode(s, memo, pystr, idx, &next_idx); + PyObject *val = scan_once_unicode(s, memo, pystr, idx, &next_idx); if (val == NULL) goto bail; + /* The steal below takes our references to both key and val + (releasing them on failure). Only key is reset for the bail + path; val is never live there, so it needs no cleanup. */ if (has_pairs_hook) { PyObject *item = _PyTuple_FromPairSteal(key, val); - key = val = NULL; + key = NULL; if (item == NULL) goto bail; if (PyList_Append(rval, item) == -1) { @@ -818,10 +822,10 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss Py_DECREF(item); } else { - if (PyDict_SetItem(rval, key, val) < 0) + int err = _PyDict_SetItem_Take2((PyDictObject *)rval, key, val); + key = NULL; + if (err < 0) goto bail; - Py_CLEAR(key); - Py_CLEAR(val); } idx = next_idx; @@ -851,21 +855,20 @@ _parse_object_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ss *next_idx_ptr = idx + 1; if (has_pairs_hook) { - val = PyObject_CallOneArg(s->object_pairs_hook, rval); + PyObject *res = PyObject_CallOneArg(s->object_pairs_hook, rval); Py_DECREF(rval); - return val; + return res; } /* if object_hook is not None: rval = object_hook(rval) */ if (s->object_hook != Py_None) { - val = PyObject_CallOneArg(s->object_hook, rval); + PyObject *res = PyObject_CallOneArg(s->object_hook, rval); Py_DECREF(rval); - return val; + return res; } return rval; bail: Py_XDECREF(key); - Py_XDECREF(val); Py_XDECREF(rval); return NULL; } @@ -882,7 +885,6 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi const void *str; int kind; Py_ssize_t end_idx; - PyObject *val = NULL; PyObject *rval; Py_ssize_t next_idx; Py_ssize_t comma_idx; @@ -903,14 +905,12 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi while (1) { /* read any JSON term */ - val = scan_once_unicode(s, memo, pystr, idx, &next_idx); + PyObject *val = scan_once_unicode(s, memo, pystr, idx, &next_idx); if (val == NULL) goto bail; - if (PyList_Append(rval, val) == -1) + if (_PyList_AppendTakeRef((PyListObject *)rval, val) < 0) goto bail; - - Py_CLEAR(val); idx = next_idx; /* skip whitespace between term and , */ @@ -944,13 +944,12 @@ _parse_array_unicode(PyScannerObject *s, PyObject *memo, PyObject *pystr, Py_ssi *next_idx_ptr = idx + 1; /* if array_hook is not None: return array_hook(rval) */ if (!Py_IsNone(s->array_hook)) { - val = PyObject_CallOneArg(s->array_hook, rval); + PyObject *res = PyObject_CallOneArg(s->array_hook, rval); Py_DECREF(rval); - return val; + return res; } return rval; bail: - Py_XDECREF(val); Py_DECREF(rval); return NULL; } diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index ddc27c4a5b7356a..2aa3923f68e66ad 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -1090,8 +1090,14 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, goto cleanup; } borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num); - if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0) + /* borrowed_arg is only borrowed; its __fspath__() may run Python + that drops fast_args' last reference to it. */ + Py_INCREF(borrowed_arg); + if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0) { + Py_DECREF(borrowed_arg); goto cleanup; + } + Py_DECREF(borrowed_arg); PyTuple_SET_ITEM(converted_args, arg_num, converted_arg); } diff --git a/Modules/_remote_debugging/frames.c b/Modules/_remote_debugging/frames.c index d73cd080dc477f3..e7d2a2764390261 100644 --- a/Modules/_remote_debugging/frames.c +++ b/Modules/_remote_debugging/frames.c @@ -580,6 +580,14 @@ collect_frames_with_cache( return full_hit < 0 ? -1 : 0; } + assert(ctx->chunks != NULL); + + if (ctx->chunks->count == 0) { + if (copy_stack_chunks(unwinder, ctx->thread_state_addr, ctx->chunks) < 0) { + PyErr_Clear(); + } + } + Py_ssize_t frames_before = PyList_GET_SIZE(ctx->frame_info); if (process_frame_chain(unwinder, ctx) < 0) { diff --git a/Modules/_remote_debugging/module.c b/Modules/_remote_debugging/module.c index 984213d18817523..36115f20d9d4ccc 100644 --- a/Modules/_remote_debugging/module.c +++ b/Modules/_remote_debugging/module.c @@ -1624,9 +1624,6 @@ _remote_debugging_exec(PyObject *m) return -1; } -#ifdef Py_GIL_DISABLED - PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); -#endif int rc = PyModule_AddIntConstant(m, "PROCESS_VM_READV_SUPPORTED", HAVE_PROCESS_VM_READV); if (rc < 0) { return -1; diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c index 2cc62751054278f..d81784409e5d91a 100644 --- a/Modules/_sqlite/blob.c +++ b/Modules/_sqlite/blob.c @@ -531,21 +531,25 @@ ass_subscript_slice(pysqlite_Blob *self, PyObject *item, PyObject *value) return -1; } - if (len == 0) { - return 0; - } - Py_buffer vbuf; if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0) { return -1; } - int rc = -1; if (vbuf.len != len) { PyErr_SetString(PyExc_IndexError, "Blob slice assignment is wrong size"); + PyBuffer_Release(&vbuf); + return -1; } - else if (step == 1) { + + if (len == 0) { + PyBuffer_Release(&vbuf); + return 0; + } + + int rc = -1; + if (step == 1) { rc = inner_write(self, vbuf.buf, len, start); } else { diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index ee6cb4a371ea505..32aa06bed4a409c 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -42,6 +42,7 @@ static const char copyright[] = #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION #include "pycore_dict.h" // _PyDict_Next() #include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_list.h" // _PyList_AppendTakeRef() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_tuple.h" // _PyTuple_FromPairSteal #include "pycore_unicodeobject.h" // _PyUnicode_Copy @@ -986,8 +987,7 @@ _sre_SRE_Pattern_findall_impl(PatternObject *self, PyObject *string, break; } - status = PyList_Append(list, item); - Py_DECREF(item); + status = _PyList_AppendTakeRef((PyListObject *)list, item); if (status < 0) goto error; @@ -1333,8 +1333,7 @@ pattern_subx(_sremodulestate* module_state, string, i, b); if (!item) goto error; - status = PyList_Append(list, item); - Py_DECREF(item); + status = _PyList_AppendTakeRef((PyListObject *)list, item); if (status < 0) goto error; @@ -1363,8 +1362,7 @@ pattern_subx(_sremodulestate* module_state, /* add to list */ if (item != Py_None) { - status = PyList_Append(list, item); - Py_DECREF(item); + status = _PyList_AppendTakeRef((PyListObject *)list, item); if (status < 0) goto error; } @@ -1381,8 +1379,7 @@ pattern_subx(_sremodulestate* module_state, string, i, state.endpos); if (!item) goto error; - status = PyList_Append(list, item); - Py_DECREF(item); + status = _PyList_AppendTakeRef((PyListObject *)list, item); if (status < 0) goto error; } diff --git a/Modules/_testcapi/mem.c b/Modules/_testcapi/mem.c index 7909476ac11aa6b..28e89275d61705e 100644 --- a/Modules/_testcapi/mem.c +++ b/Modules/_testcapi/mem.c @@ -345,6 +345,53 @@ test_setallocators(PyMemAllocatorDomain domain) goto fail; } + /* realloc(NULL, size) should behave like malloc(size) */ + size_t size3 = 100; + void *ptr3; + switch(domain) { + case PYMEM_DOMAIN_RAW: + ptr3 = PyMem_RawRealloc(NULL, size3); + break; + case PYMEM_DOMAIN_MEM: + ptr3 = PyMem_Realloc(NULL, size3); + break; + case PYMEM_DOMAIN_OBJ: + ptr3 = PyObject_Realloc(NULL, size3); + break; + default: + ptr3 = NULL; + break; + } + + CHECK_CTX("realloc(NULL, size)"); + if (ptr3 == NULL) { + error_msg = "realloc(NULL, size) failed"; + goto fail; + } + if (hook.realloc_ptr != NULL || hook.realloc_new_size != size3) { + error_msg = "realloc(NULL, size) invalid parameters"; + goto fail; + } + + hook.free_ptr = NULL; + switch(domain) { + case PYMEM_DOMAIN_RAW: + PyMem_RawFree(ptr3); + break; + case PYMEM_DOMAIN_MEM: + PyMem_Free(ptr3); + break; + case PYMEM_DOMAIN_OBJ: + PyObject_Free(ptr3); + break; + } + + CHECK_CTX("realloc(NULL, size) free"); + if (hook.free_ptr != ptr3) { + error_msg = "unexpected pointer passed to free"; + goto fail; + } + res = Py_NewRef(Py_None); goto finally; diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index a7feca5bd960705..98b5dd47accde35 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -67,5 +67,6 @@ int _PyTestCapi_Init_Frame(PyObject *mod); int _PyTestCapi_Init_Type(PyObject *mod); int _PyTestCapi_Init_Function(PyObject *mod); int _PyTestCapi_Init_Module(PyObject *mod); +int _PyTestCapi_Init_Weakref(PyObject *mod); #endif // Py_TESTCAPI_PARTS_H diff --git a/Modules/_testcapi/weakref.c b/Modules/_testcapi/weakref.c new file mode 100644 index 000000000000000..7c3ad8565991b7e --- /dev/null +++ b/Modules/_testcapi/weakref.c @@ -0,0 +1,46 @@ +#include "parts.h" +#include "util.h" + + +static PyObject * +pyweakref_getref(PyObject *module, PyObject *ref) +{ + NULLABLE(ref); + PyObject *obj = UNINITIALIZED_PTR; + int rc = PyWeakref_GetRef(ref, &obj); + if (rc == -1 && PyErr_Occurred()) { + assert(obj == NULL); + return NULL; + } + if (obj == NULL) { + return Py_BuildValue("i", rc); + } + else { + assert(obj != UNINITIALIZED_PTR); + return Py_BuildValue("iN", rc, obj); + } +} + +static PyObject * +pyweakref_isdead(PyObject *module, PyObject *obj) +{ + NULLABLE(obj); + int rc = PyWeakref_IsDead(obj); + if (rc == -1 && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromLong(rc); +} + + +static PyMethodDef test_methods[] = { + {"pyweakref_getref", pyweakref_getref, METH_O}, + {"pyweakref_isdead", pyweakref_isdead, METH_O}, + {NULL}, +}; + +int +_PyTestCapi_Init_Weakref(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index be5ad3e9efa1040..9c90d1fc36f398e 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3909,6 +3909,9 @@ _testcapi_exec(PyObject *m) if (_PyTestCapi_Init_Module(m) < 0) { return -1; } + if (_PyTestCapi_Init_Weakref(m) < 0) { + return -1; + } return 0; } diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 11dfcc68eb2dacd..62d08826a2faea4 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -8773,18 +8773,7 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - // _GUARD_KEYS_VERSION - { - uint32_t keys_version = read_u32(&this_instr[4].cache); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - } + /* Skip 2 cache entries */ // _LOAD_ATTR_METHOD_WITH_VALUES { PyObject *descr = read_obj(&this_instr[6].cache); @@ -8841,7 +8830,7 @@ assert(keys->dk_kind == DICT_KEYS_UNICODE); assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(keys->dk_nentries)); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(keys) + index; - PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value); + PyObject *attr_o = FT_ATOMIC_LOAD_PTR_CONSUME(ep->me_value); if (attr_o == NULL) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -8967,18 +8956,7 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - // _GUARD_KEYS_VERSION - { - uint32_t keys_version = read_u32(&this_instr[4].cache); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - } + /* Skip 2 cache entries */ // _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES { PyObject *descr = read_obj(&this_instr[6].cache); @@ -9729,7 +9707,7 @@ } assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); if (res_o == NULL) { UPDATE_MISS_STATS(LOAD_GLOBAL); assert(_PyOpcode_Deopt[opcode] == (LOAD_GLOBAL)); @@ -9796,7 +9774,7 @@ assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); assert(index < DK_SIZE(keys)); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); if (res_o == NULL) { UPDATE_MISS_STATS(LOAD_GLOBAL); assert(_PyOpcode_Deopt[opcode] == (LOAD_GLOBAL)); diff --git a/Modules/_testlimitedcapi.c b/Modules/_testlimitedcapi.c index 5f2be0dd43954e3..9314fccc6c915a4 100644 --- a/Modules/_testlimitedcapi.c +++ b/Modules/_testlimitedcapi.c @@ -98,5 +98,8 @@ PyInit__testlimitedcapi(void) if (_PyTestLimitedCAPI_Init_File(mod) < 0) { return NULL; } + if (_PyTestLimitedCAPI_Init_Weakref(mod) < 0) { + return NULL; + } return mod; } diff --git a/Modules/_testlimitedcapi/parts.h b/Modules/_testlimitedcapi/parts.h index 1eea4f74d14416c..c51d285e19ab0d6 100644 --- a/Modules/_testlimitedcapi/parts.h +++ b/Modules/_testlimitedcapi/parts.h @@ -45,5 +45,6 @@ int _PyTestLimitedCAPI_Init_Unicode(PyObject *module); int _PyTestLimitedCAPI_Init_VectorcallLimited(PyObject *module); int _PyTestLimitedCAPI_Init_Version(PyObject *module); int _PyTestLimitedCAPI_Init_File(PyObject *module); +int _PyTestLimitedCAPI_Init_Weakref(PyObject *module); #endif // Py_TESTLIMITEDCAPI_PARTS_H diff --git a/Modules/_testlimitedcapi/slots.c b/Modules/_testlimitedcapi/slots.c index 7a8d6466e53a096..9abe53d21154645 100644 --- a/Modules/_testlimitedcapi/slots.c +++ b/Modules/_testlimitedcapi/slots.c @@ -607,6 +607,47 @@ module_from_null_slot(PyObject* Py_UNUSED(module), PyObject *args) }, spec); } + + +static PyObject * +type_from_base_slots( + PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *base = NULL; + PyObject *bases = NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "|OO", + (char*[]){"base", "bases", NULL}, + &base, &bases)) + { + return NULL; + } + + PySlot empty_slots[] = { + PySlot_END + }; + + PySlot base_slots[] = { + PySlot_DATA(Py_tp_base, base), + PySlot_END + }; + + PySlot bases_slots[] = { + PySlot_DATA(Py_tp_bases, bases), + PySlot_END + }; + + PySlot slots[] = { + PySlot_STATIC_DATA(Py_tp_name, "_testcapi.HeapCTypeWithBases"), + PySlot_UINT64(Py_tp_flags, Py_TPFLAGS_BASETYPE), + PySlot_DATA(Py_slot_subslots, base ? base_slots: empty_slots), + PySlot_DATA(Py_slot_subslots, bases ? bases_slots: empty_slots), + PySlot_END + }; + + return PyType_FromSlots(slots); +} + static PyMethodDef _TestMethods[] = { {"type_from_slots", type_from_slots, METH_VARARGS}, {"module_from_gil_slot", module_from_gil_slot, METH_VARARGS}, @@ -614,6 +655,8 @@ static PyMethodDef _TestMethods[] = { {"type_from_null_spec_slot", type_from_null_spec_slot, METH_VARARGS}, {"module_from_slots", module_from_slots, METH_VARARGS}, {"module_from_null_slot", module_from_null_slot, METH_VARARGS}, + {"type_from_base_slots", _PyCFunction_CAST(type_from_base_slots), + METH_VARARGS | METH_KEYWORDS}, {NULL}, }; static PyMethodDef *TestMethods = _TestMethods; diff --git a/Modules/_testlimitedcapi/weakref.c b/Modules/_testlimitedcapi/weakref.c new file mode 100644 index 000000000000000..e7f9d54d1a0d59e --- /dev/null +++ b/Modules/_testlimitedcapi/weakref.c @@ -0,0 +1,78 @@ +#include "pyconfig.h" // Py_GIL_DISABLED +#ifndef Py_GIL_DISABLED + // Need limited C API 3.5 for PyModule_AddFunctions() +# define Py_LIMITED_API 0x03050000 +#endif + +#include "parts.h" +#include "util.h" + + +static PyObject * +pyweakref_check(PyObject *module, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyWeakref_Check(obj)); +} + +static PyObject * +pyweakref_checkref(PyObject *module, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyWeakref_CheckRef(obj)); +} + +static PyObject * +pyweakref_checkrefexact(PyObject *module, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyWeakref_CheckRefExact(obj)); +} + +static PyObject * +pyweakref_checkproxy(PyObject *module, PyObject *obj) +{ + NULLABLE(obj); + return PyLong_FromLong(PyWeakref_CheckProxy(obj)); +} + +static PyObject * +pyweakref_newref(PyObject *module, PyObject *args) +{ + PyObject *obj; + PyObject *callback = NULL; + if (!PyArg_ParseTuple(args, "O|O", &obj, &callback)) { + return NULL; + } + NULLABLE(obj); + return PyWeakref_NewRef(obj, callback); +} + +static PyObject * +pyweakref_newproxy(PyObject *module, PyObject *args) +{ + PyObject *obj; + PyObject *callback = NULL; + if (!PyArg_ParseTuple(args, "O|O", &obj, &callback)) { + return NULL; + } + NULLABLE(obj); + return PyWeakref_NewProxy(obj, callback); +} + + +static PyMethodDef test_methods[] = { + {"pyweakref_check", pyweakref_check, METH_O}, + {"pyweakref_checkref", pyweakref_checkref, METH_O}, + {"pyweakref_checkrefexact", pyweakref_checkrefexact, METH_O}, + {"pyweakref_checkproxy", pyweakref_checkproxy, METH_O}, + {"pyweakref_newref", pyweakref_newref, METH_VARARGS}, + {"pyweakref_newproxy", pyweakref_newproxy, METH_VARARGS}, + {NULL}, +}; + +int +_PyTestLimitedCAPI_Init_Weakref(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 58fdabecf16ada7..6eca98a3c8033fa 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -128,18 +128,20 @@ _get_tcl_lib_path(void) } /* Check expected location for an installed Python first */ - tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION); - if (tcl_library_path == NULL) { + PyObject* tmp_tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION); + if (tmp_tcl_library_path == NULL) { Py_DECREF(prefix); return NULL; } - tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path); + tcl_library_path = PyUnicode_Concat(prefix, tmp_tcl_library_path); + Py_DECREF(tmp_tcl_library_path); Py_DECREF(prefix); if (tcl_library_path == NULL) { return NULL; } stat_return_value = _Py_stat(tcl_library_path, &stat_buf); if (stat_return_value == -2) { + Py_DECREF(tcl_library_path); return NULL; } if (stat_return_value == -1) { @@ -154,16 +156,17 @@ _get_tcl_lib_path(void) } stat_return_value = _Py_stat(tcl_library_path, &stat_buf); if (stat_return_value == -2) { + Py_DECREF(tcl_library_path); return NULL; } if (stat_return_value == -1) { /* tcltkDir for a repository build doesn't exist either, reset errno and leave Tcl to its own devices */ errno = 0; - tcl_library_path = NULL; + Py_CLEAR(tcl_library_path); } #else - tcl_library_path = NULL; + Py_CLEAR(tcl_library_path); #endif } already_checked = 1; @@ -707,11 +710,13 @@ Tkapp_New(const char *screenName, const char *className, if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { str_path = _get_tcl_lib_path(); if (str_path == NULL && PyErr_Occurred()) { + Py_DECREF(v); return NULL; } if (str_path != NULL) { utf8_path = PyUnicode_AsUTF8String(str_path); if (utf8_path == NULL) { + Py_DECREF(v); return NULL; } Tcl_SetVar(v->interp, diff --git a/Modules/_winapi.c b/Modules/_winapi.c index fc2c0890468a6b9..369a7400eb63b90 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -1194,8 +1194,10 @@ gethandlelist(PyObject *mapping, const char *name, Py_ssize_t *size) } ret = PyMem_Malloc(*size); - if (ret == NULL) + if (ret == NULL) { + PyErr_NoMemory(); goto cleanup; + } for (i = 0; i < PySequence_Fast_GET_SIZE(value_fast); i++) { ret[i] = PYNUM_TO_HANDLE(PySequence_Fast_GET_ITEM(value_fast, i)); @@ -1278,6 +1280,7 @@ getattributelist(PyObject *obj, const char *name, AttributeList *attribute_list) attribute_list->attribute_list = PyMem_Malloc(attribute_list_size); if (attribute_list->attribute_list == NULL) { ret = -1; + PyErr_NoMemory(); goto cleanup; } diff --git a/Modules/clinic/_collectionsmodule.c.h b/Modules/clinic/_collectionsmodule.c.h index b5c315c680e7821..6c60678a6fbd51a 100644 --- a/Modules/clinic/_collectionsmodule.c.h +++ b/Modules/clinic/_collectionsmodule.c.h @@ -340,7 +340,7 @@ deque_index(PyObject *deque, PyObject *const *args, Py_ssize_t nargs) PyObject *return_value = NULL; PyObject *v; Py_ssize_t start = 0; - Py_ssize_t stop = Py_SIZE(deque); + Py_ssize_t stop = PY_SSIZE_T_MAX; if (!_PyArg_CheckPositional("index", nargs, 1, 3)) { goto exit; @@ -632,4 +632,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=b9d4d647c221cb9f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f5a388add99d3d15 input=a9049054013a1b77]*/ diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 7c727d8c2d4ff0e..3b0647152ceffed 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -101,8 +101,6 @@ static int faulthandler_get_fileno(PyObject **file_ptr) { PyObject *result; - long fd_long; - int fd; PyObject *file = *file_ptr; if (file == NULL || file == Py_None) { @@ -124,7 +122,7 @@ faulthandler_get_fileno(PyObject **file_ptr) return -1; } } - fd = PyLong_AsInt(file); + int fd = PyLong_AsInt(file); if (fd == -1 && PyErr_Occurred()) return -1; if (fd < 0) { @@ -145,15 +143,16 @@ faulthandler_get_fileno(PyObject **file_ptr) return -1; } - fd = -1; + int fd; if (PyLong_Check(result)) { - fd_long = PyLong_AsLong(result); - if (0 <= fd_long && fd_long < INT_MAX) - fd = (int)fd_long; + fd = PyLong_AsInt(result); + } + else { + fd = -1; } Py_DECREF(result); - if (fd == -1) { + if (fd < 0) { PyErr_SetString(PyExc_RuntimeError, "file.fileno() is not a valid file descriptor"); Py_DECREF(file); @@ -407,10 +406,8 @@ faulthandler_fatal_error(int signum) PUTS(fd, "\n\n"); } else { - char unknown_signum[23] = {0,}; - snprintf(unknown_signum, 23, "%d", signum); PUTS(fd, "Fatal Python error from unexpected signum: "); - PUTS(fd, unknown_signum); + _Py_DumpDecimal(fd, signum); PUTS(fd, "\n\n"); } @@ -713,7 +710,7 @@ faulthandler_thread(void *unused) /* Timeout => dump traceback */ assert(st == PY_LOCK_FAILURE); - (void)_Py_write_noraise(thread.fd, thread.header, (int)thread.header_len); + (void)_Py_write_noraise(thread.fd, thread.header, thread.header_len); errmsg = PyUnstable_DumpTracebackThreads(thread.fd, thread.interp, NULL, thread.max_threads); @@ -1224,7 +1221,7 @@ static PyObject * faulthandler__fatal_error_c_thread_impl(PyObject *module) /*[clinic end generated code: output=101bc8aaf4a5eec1 input=fbdca6fffd639a39]*/ { - long tid; + unsigned long tid; PyThread_type_lock lock; faulthandler_suppress_crash_report(); @@ -1236,7 +1233,7 @@ faulthandler__fatal_error_c_thread_impl(PyObject *module) PyThread_acquire_lock(lock, WAIT_LOCK); tid = PyThread_start_new_thread(faulthandler_fatal_error_thread, lock); - if (tid == -1) { + if (tid == PYTHREAD_INVALID_THREAD_ID) { PyThread_free_lock(lock); PyErr_SetString(PyExc_RuntimeError, "unable to start the thread"); return NULL; diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 12f93ac0fdea14b..0093995441e390d 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -167,6 +167,8 @@ gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, gcstate->generations[2].threshold = threshold2; } #else + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyEval_StopTheWorld(interp); gcstate->young.threshold = threshold0; if (group_right_1) { gcstate->old[0].threshold = threshold1; @@ -174,6 +176,7 @@ gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, if (group_right_2) { gcstate->old[1].threshold = threshold2; } + _PyEval_StartTheWorld(interp); #endif Py_RETURN_NONE; } @@ -230,7 +233,7 @@ gc_get_count_impl(PyObject *module) gcstate->generations[2].count); #else return Py_BuildValue("(iii)", - gcstate->young.count, + _Py_atomic_load_int_relaxed(&gcstate->young.count), gcstate->old[0].count, gcstate->old[1].count); #endif diff --git a/Modules/getpath.py b/Modules/getpath.py index 4dceb5cdc8dfcf0..6199567bd777aa0 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -129,8 +129,7 @@ # checked by looking for the BUILDDIR_TXT file, which contains the # relative path to the platlib dir. The executable_dir value is # derived from joining the VPATH preprocessor variable to the -# directory containing pybuilddir.txt. If it is not found, the -# BUILD_LANDMARK file is found, which is part of the source tree. +# directory containing pybuilddir.txt. # prefix is then found by searching up for a file that should only # exist in the source tree, and the stdlib dir is set to prefix/Lib. @@ -177,7 +176,6 @@ if os_name == 'posix' or os_name == 'darwin': BUILDDIR_TXT = 'pybuilddir.txt' - BUILD_LANDMARK = 'Modules/Setup.local' DEFAULT_PROGRAM_NAME = f'python{VERSION_MAJOR}' STDLIB_SUBDIR = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}{ABI_THREAD}' STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}/os.py', f'{STDLIB_SUBDIR}/os.pyc'] @@ -190,7 +188,6 @@ elif os_name == 'nt': BUILDDIR_TXT = 'pybuilddir.txt' - BUILD_LANDMARK = f'{VPATH}\\Modules\\Setup.local' DEFAULT_PROGRAM_NAME = f'python' STDLIB_SUBDIR = 'Lib' STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}\\os.py', f'{STDLIB_SUBDIR}\\os.pyc'] @@ -513,13 +510,9 @@ def search_up(prefix, *landmarks, test=isfile): platstdlib_dir = real_executable_dir build_prefix = joinpath(real_executable_dir, VPATH) except (FileNotFoundError, PermissionError): - if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)): - build_prefix = joinpath(real_executable_dir, VPATH) - if os_name == 'nt': - # QUIRK: Windows builds need platstdlib_dir to be the executable - # dir. Normally the builddir marker handles this, but in this - # case we need to correct manually. - platstdlib_dir = real_executable_dir + # We used to check for an alternate landmark here, but now we require + # BUILDDIR_TXT to exist. (gh-151544; CVE-2026-12003) + pass if build_prefix: if os_name == 'nt': diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 5636a00afe10c4b..64e5372d73d2f29 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -187,13 +187,6 @@ tl_to_d(TripleLength total) } -/* - sin(pi*x), giving accurate results for all finite x (especially x - integral or close to an integer). This is here for use in the - reflection formula for the gamma function. It conforms to IEEE - 754-2008 for finite arguments, but not for infinities or nans. -*/ - static const double pi = 3.141592653589793238462643383279502884197; static const double logpi = 1.144729885849400174143427351353058711647; @@ -219,13 +212,120 @@ static const double logpi = 1.144729885849400174143427351353058711647; } \ } +#ifndef HAVE_ACOSPI +/* + acos(x)/pi. It conforms to C23 Annex 'F'. +*/ + +static double +m_acospi(double x) +{ + double r = acos(x)/pi; + if (isgreater(r, 1.0)) { + return 1.0; + } + return r; +} +#else +#define m_acospi acospi +#endif + +#ifndef HAVE_ASINPI +/* + asin(x)/pi. It conforms to C23 Annex 'F'. +*/ + +static double +m_asinpi(double x) +{ + double r = asin(x)/pi; + if (isgreater(fabs(r), 0.5)) { + return copysign(0.5, r); + } + return r; +} +#else +#define m_asinpi asinpi +#endif + +#ifndef HAVE_ATANPI +/* + asin(x)/pi. It conforms to C23 Annex 'F'. +*/ + +static double +m_atanpi(double x) +{ + double r = atan(x)/pi; + if (isgreater(fabs(r), 0.5)) { + return copysign(0.5, r); + } + return r; +} +#else +#define m_atanpi atanpi +#endif + +#ifndef HAVE_ATAN2PI +/* + asin(x)/pi. It conforms to C23 Annex 'F'. +*/ + +static double +m_atan2pi(double y, double x) +{ + double r = atan2(y, x)/pi; + if (isgreater(fabs(r), 1.0)) { + return copysign(1.0, r); + } + return r; +} +#else +#define m_atan2pi atan2pi +#endif + +#ifndef HAVE_COSPI +/* + cos(pi*x), giving accurate results for all finite x (especially x + integral or close to an integer). It conforms to C23 Annex 'F'. +*/ + +static double +m_cospi(double x) +{ + if (!isfinite(x)) { + return cos(x); + } + x = fabs(x - 2.0 * round(0.5 * x)); + if (x <= 0.25) { + return cos(pi * x); + } + if (x == 0.5) { + return 0.0; + } + if (x <= 0.75) { + return sin(pi * (0.5 - x)); + } + return -cos(pi * (1.0 - x)); +} +#else +#define m_cospi cospi +#endif + +#ifndef HAVE_SINPI +/* + sin(pi*x), giving accurate results for all finite x (especially x + integral or close to an integer). It conforms to C23 Annex 'F'. +*/ + static double m_sinpi(double x) { double y, r; int n; - /* this function should only ever be called for finite arguments */ - assert(isfinite(x)); + if (!isfinite(x)) { + return sin(x); + } y = fmod(fabs(x), 2.0); n = (int)round(2.0*y); assert(0 <= n && n <= 4); @@ -252,6 +352,47 @@ m_sinpi(double x) } return copysign(1.0, x)*r; } +#else +#define m_sinpi sinpi +#endif + +#ifndef HAVE_TANPI +/* + tan(pi*x), giving accurate results for all finite x (especially x + integral or close to an integer). It conforms to C23 Annex 'F'. +*/ + +static double +m_tanpi(double x) +{ + double y, absy; + if (!isfinite(x)) { + return tan(x); + } + y = x - 2.0 * round(0.5 * x); + absy = fabs(y); + if (absy == 0.0) { + return copysign(0.0, x); + } + if (absy == 1.0) { + return copysign(0.0, -x); + } + if (absy == 0.5) { + errno = ERANGE; + return 1.0 / copysign(0.0, y); + } + if (absy > 0.5) { + y -= copysign(1.0, y); + absy = fabs(y); + } + if (absy <= 0.25) { + return tan(pi * y); + } + return copysign(1.0 / tan(pi * (0.5 - absy)), y); +} +#else +#define m_tanpi tanpi +#endif /* Implementation of the real gamma function. Kept here to work around issues (see e.g. gh-70309) with quality of libm's tgamma/lgamma implementations @@ -952,6 +1093,11 @@ FUNC1D(acosh, acosh, 0, "acosh($module, x, /)\n--\n\n" "Return the inverse hyperbolic cosine of x.", "expected argument value not less than 1, got %s") +FUNC1D(acospi, m_acospi, 0, + "acospi($module, x, /)\n--\n\n" + "Return the arc cosine (measured in half-turns) of x.\n\n" + "The result is between 0 and 1.", + "expected a number in range from -1 up to 1, got %s") FUNC1D(asin, asin, 0, "asin($module, x, /)\n--\n\n" "Return the arc sine (measured in radians) of x.\n\n" @@ -960,6 +1106,11 @@ FUNC1D(asin, asin, 0, FUNC1(asinh, asinh, 0, "asinh($module, x, /)\n--\n\n" "Return the inverse hyperbolic sine of x.") +FUNC1D(asinpi, m_asinpi, 0, + "asinpi($module, x, /)\n--\n\n" + "Return the arc sine (measured in half-turns) of x.\n\n" + "The result is between -1/2 and 1/2.", + "expected a number in range from -1 up to 1, got %s") FUNC1(atan, atan, 0, "atan($module, x, /)\n--\n\n" "Return the arc tangent (measured in radians) of x.\n\n" @@ -968,10 +1119,19 @@ FUNC2(atan2, atan2, "atan2($module, y, x, /)\n--\n\n" "Return the arc tangent (measured in radians) of y/x.\n\n" "Unlike atan(y/x), the signs of both x and y are considered.") +FUNC2(atan2pi, m_atan2pi, + "atan2pi($module, y, x, /)\n--\n\n" + "Return the arc tangent (measured in half-turns) of y/x.\n\n" + "Unlike atanpi(y/x), the signs of both x and y are considered.") FUNC1D(atanh, atanh, 0, "atanh($module, x, /)\n--\n\n" "Return the inverse hyperbolic tangent of x.", "expected a number between -1 and 1, got %s") +FUNC1D(atanpi, m_atanpi, 0, + "atanpi($module, x, /)\n--\n\n" + "Return the arc tangent (measured in half-turns) of x.\n\n" + "The result is between 0 and 1.", + "expected a number in range from -1 up to 1, got %s") FUNC1(cbrt, cbrt, 0, "cbrt($module, x, /)\n--\n\n" "Return the cube root of x.") @@ -1024,6 +1184,10 @@ FUNC1D(cos, cos, 0, FUNC1(cosh, cosh, 1, "cosh($module, x, /)\n--\n\n" "Return the hyperbolic cosine of x.") +FUNC1D(cospi, m_cospi, 0, + "cospi($module, x, /)\n--\n\n" + "Return the cosine of x (measured in half-turns).", + "expected a finite input, got %s") FUNC1A(erf, erf, "erf($module, x, /)\n--\n\n" "Error function at x.") @@ -1158,6 +1322,10 @@ FUNC1D(sin, sin, 0, FUNC1(sinh, sinh, 1, "sinh($module, x, /)\n--\n\n" "Return the hyperbolic sine of x.") +FUNC1D(sinpi, m_sinpi, 0, + "sinpi($module, x, /)\n--\n\n" + "Return the sine of x (measured in half-turns).", + "expected a finite input, got %s") FUNC1D(sqrt, sqrt, 0, "sqrt($module, x, /)\n--\n\n" "Return the square root of x.", @@ -1169,6 +1337,10 @@ FUNC1D(tan, tan, 0, FUNC1(tanh, tanh, 0, "tanh($module, x, /)\n--\n\n" "Return the hyperbolic tangent of x.") +FUNC1D(tanpi, m_tanpi, 1, + "tanpi($module, x, /)\n--\n\n" + "Return the tangent of x (measured in half-turns).", + "expected a finite input, got %s") /* Precision summation function as msum() by Raymond Hettinger in , @@ -3047,16 +3219,21 @@ math_exec(PyObject *module) static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, {"acosh", math_acosh, METH_O, math_acosh_doc}, + {"acospi", math_acospi, METH_O, math_acospi_doc}, {"asin", math_asin, METH_O, math_asin_doc}, {"asinh", math_asinh, METH_O, math_asinh_doc}, + {"asinpi", math_asinpi, METH_O, math_asinpi_doc}, {"atan", math_atan, METH_O, math_atan_doc}, {"atan2", _PyCFunction_CAST(math_atan2), METH_FASTCALL, math_atan2_doc}, {"atanh", math_atanh, METH_O, math_atanh_doc}, + {"atan2pi", _PyCFunction_CAST(math_atan2pi), METH_FASTCALL, math_atan2pi_doc}, + {"atanpi", math_atanpi, METH_O, math_atanpi_doc}, {"cbrt", math_cbrt, METH_O, math_cbrt_doc}, MATH_CEIL_METHODDEF {"copysign", _PyCFunction_CAST(math_copysign), METH_FASTCALL, math_copysign_doc}, {"cos", math_cos, METH_O, math_cos_doc}, {"cosh", math_cosh, METH_O, math_cosh_doc}, + {"cospi", math_cospi, METH_O, math_cospi_doc}, MATH_DEGREES_METHODDEF MATH_DIST_METHODDEF {"erf", math_erf, METH_O, math_erf_doc}, @@ -3093,9 +3270,11 @@ static PyMethodDef math_methods[] = { MATH_SIGNBIT_METHODDEF {"sin", math_sin, METH_O, math_sin_doc}, {"sinh", math_sinh, METH_O, math_sinh_doc}, + {"sinpi", math_sinpi, METH_O, math_sinpi_doc}, {"sqrt", math_sqrt, METH_O, math_sqrt_doc}, {"tan", math_tan, METH_O, math_tan_doc}, {"tanh", math_tanh, METH_O, math_tanh_doc}, + {"tanpi", math_tanpi, METH_O, math_tanpi_doc}, MATH_SUMPROD_METHODDEF MATH_TRUNC_METHODDEF MATH_PROD_METHODDEF diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c index a30afe91f8fa171..6fb04ba7bd47c67 100644 --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -620,8 +620,6 @@ mmap_gfind_lock_held(mmap_object *self, Py_buffer *view, PyObject *start_obj, start += self->size; if (start < 0) start = 0; - else if (start > self->size) - start = self->size; if (end < 0) end += self->size; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a06479fa60cdba1..1f1b7fa729c01c8 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3123,7 +3123,7 @@ class path_t_converter(CConverter): impl_by_reference = True parse_by_reference = True default_type = () - c_init_default = "" # overridden in pre_render(() + c_init_default = "" # overridden in pre_render() converter = 'path_converter' @@ -3266,7 +3266,7 @@ class confname_converter(CConverter): """, argname=argname, converter=self.converter, table=self.table) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=d58f18bdf3bd3565]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=ddbf3ac90a981122]*/ /*[clinic input] @@ -5699,7 +5699,7 @@ os__path_splitroot_impl(PyObject *module, path_t *path) buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1)); if (!buffer) { - return NULL; + return PyErr_NoMemory(); } wcscpy(buffer, path->wide); for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) { diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 3eaa8cf75482397..3e82af3194d053a 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4526,17 +4526,19 @@ sock_recvmsg_into(PyObject *self, PyObject *args) struct iovec *iovs = NULL; Py_ssize_t i, nitems, nbufs = 0; Py_buffer *bufs = NULL; - PyObject *buffers_arg, *fast, *retval = NULL; + PyObject *buffers_arg, *buffers_tuple, *retval = NULL; if (!PyArg_ParseTuple(args, "O|ni:recvmsg_into", &buffers_arg, &ancbufsize, &flags)) return NULL; - if ((fast = PySequence_Fast(buffers_arg, - "recvmsg_into() argument 1 must be an " - "iterable")) == NULL) + buffers_tuple = PySequence_Tuple(buffers_arg); + if (buffers_tuple == NULL) { + PyErr_SetString(PyExc_TypeError, + "recvmsg_into() argument 1 must be an iterable"); return NULL; - nitems = PySequence_Fast_GET_SIZE(fast); + } + nitems = PyTuple_GET_SIZE(buffers_tuple); if (nitems > INT_MAX) { PyErr_SetString(PyExc_OSError, "recvmsg_into() argument 1 is too long"); goto finally; @@ -4550,7 +4552,7 @@ sock_recvmsg_into(PyObject *self, PyObject *args) goto finally; } for (; nbufs < nitems; nbufs++) { - if (!PyArg_Parse(PySequence_Fast_GET_ITEM(fast, nbufs), + if (!PyArg_Parse(PyTuple_GET_ITEM(buffers_tuple, nbufs), "w*;recvmsg_into() argument 1 must be an iterable " "of single-segment read-write buffers", &bufs[nbufs])) @@ -4566,7 +4568,7 @@ sock_recvmsg_into(PyObject *self, PyObject *args) PyBuffer_Release(&bufs[i]); PyMem_Free(bufs); PyMem_Free(iovs); - Py_DECREF(fast); + Py_DECREF(buffers_tuple); return retval; } @@ -4861,14 +4863,14 @@ sock_sendmsg_iovec(PySocketSockObject *s, PyObject *data_arg, /* Fill in an iovec for each message part, and save the Py_buffer structs to release afterwards. */ - data_fast = PySequence_Fast(data_arg, - "sendmsg() argument 1 must be an " - "iterable"); + data_fast = PySequence_Tuple(data_arg); if (data_fast == NULL) { + PyErr_SetString(PyExc_TypeError, + "sendmsg() argument 1 must be an iterable"); goto finally; } - ndataparts = PySequence_Fast_GET_SIZE(data_fast); + ndataparts = PyTuple_GET_SIZE(data_fast); if (ndataparts > INT_MAX) { PyErr_SetString(PyExc_OSError, "sendmsg() argument 1 is too long"); goto finally; @@ -4890,7 +4892,7 @@ sock_sendmsg_iovec(PySocketSockObject *s, PyObject *data_arg, } } for (; ndatabufs < ndataparts; ndatabufs++) { - if (PyObject_GetBuffer(PySequence_Fast_GET_ITEM(data_fast, ndatabufs), + if (PyObject_GetBuffer(PyTuple_GET_ITEM(data_fast, ndatabufs), &databufs[ndatabufs], PyBUF_SIMPLE) < 0) goto finally; iovs[ndatabufs].iov_base = databufs[ndatabufs].buf; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index 60df68216938134..5f0e7ab6ec220d6 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -560,39 +560,36 @@ get_decomp_record(PyObject *self, Py_UCS4 code, #define CANONICAL_ORDERING_COUNTING_SORT_THRESHOLD 20 static void -canonical_ordering_sort_insertion(int kind, void *data, - Py_ssize_t start, Py_ssize_t end) +canonical_ordering_sort_insertion(Py_UCS4 *data, Py_ssize_t length) { - for (Py_ssize_t i = start + 1; i < end; i++) { - Py_UCS4 code = PyUnicode_READ(kind, data, i); + for (Py_ssize_t i = 1; i < length; i++) { + Py_UCS4 code = data[i]; unsigned char combining = _getrecord_ex(code)->combining; Py_ssize_t j = i; - while (j > start) { - Py_UCS4 previous = PyUnicode_READ(kind, data, j - 1); + while (j > 0) { + Py_UCS4 previous = data[j - 1]; if (_getrecord_ex(previous)->combining <= combining) { break; } - PyUnicode_WRITE(kind, data, j, previous); + data[j] = previous; j--; } if (j != i) { - PyUnicode_WRITE(kind, data, j, code); + data[j] = code; } } } static void -canonical_ordering_sort_counting(int kind, void *data, - Py_ssize_t start, Py_ssize_t end, +canonical_ordering_sort_counting(Py_UCS4 *data, Py_ssize_t length, Py_UCS4 *sortbuf) { Py_ssize_t counts[256] = {0}; - Py_ssize_t run_length = end - start; Py_ssize_t total = 0; - for (Py_ssize_t i = start; i < end; i++) { - Py_UCS4 code = PyUnicode_READ(kind, data, i); + for (Py_ssize_t i = 0; i < length; i++) { + Py_UCS4 code = data[i]; unsigned char combining = _getrecord_ex(code)->combining; counts[combining]++; } @@ -604,14 +601,12 @@ canonical_ordering_sort_counting(int kind, void *data, } /* Reuse counts[] as the next output slot for each CCC. */ - for (Py_ssize_t i = start; i < end; i++) { - Py_UCS4 code = PyUnicode_READ(kind, data, i); + for (Py_ssize_t i = 0; i < length; i++) { + Py_UCS4 code = data[i]; unsigned char combining = _getrecord_ex(code)->combining; sortbuf[counts[combining]++] = code; } - for (Py_ssize_t i = 0; i < run_length; i++) { - PyUnicode_WRITE(kind, data, start + i, sortbuf[i]); - } + memcpy(data, sortbuf, length * sizeof(Py_UCS4)); } static PyObject* @@ -620,9 +615,8 @@ nfd_nfkd(PyObject *self, PyObject *input, int k) PyObject *result; Py_UCS4 *output; Py_ssize_t i, o, osize; - int input_kind, result_kind; + int input_kind; const void *input_data; - void *result_data; /* Longest decomposition in Unicode 3.2: U+FDFA */ Py_UCS4 stack[20]; Py_ssize_t space, isize; @@ -715,22 +709,13 @@ nfd_nfkd(PyObject *self, PyObject *input, int k) } } - result = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - output, o); - PyMem_Free(output); - if (!result) - return NULL; - - result_kind = PyUnicode_KIND(result); - result_data = PyUnicode_DATA(result); - /* Sort each consecutive combining-character run canonically. */ i = 0; while (i < o) { Py_ssize_t run_length, run_start; int needs_sort = 0; - Py_UCS4 ch = PyUnicode_READ(result_kind, result_data, i); + Py_UCS4 ch = output[i]; prev = _getrecord_ex(ch)->combining; if (prev == 0) { i++; @@ -739,7 +724,7 @@ nfd_nfkd(PyObject *self, PyObject *input, int k) run_start = i++; while (i < o) { - Py_UCS4 ch = PyUnicode_READ(result_kind, result_data, i); + Py_UCS4 ch = output[i]; cur = _getrecord_ex(ch)->combining; if (cur == 0) { break; @@ -756,44 +741,47 @@ nfd_nfkd(PyObject *self, PyObject *input, int k) run_length = i - run_start; if (run_length < CANONICAL_ORDERING_COUNTING_SORT_THRESHOLD) { - canonical_ordering_sort_insertion(result_kind, result_data, - run_start, i); + canonical_ordering_sort_insertion(output + run_start, run_length); continue; } if (run_length > sortbuflen) { - Py_UCS4 *new_sortbuf = PyMem_Resize(sortbuf, - Py_UCS4, - run_length); + Py_UCS4 *new_sortbuf = PyMem_Resize(sortbuf, Py_UCS4, run_length); if (new_sortbuf == NULL) { PyErr_NoMemory(); PyMem_Free(sortbuf); - Py_DECREF(result); + PyMem_Free(output); return NULL; } sortbuf = new_sortbuf; sortbuflen = run_length; } - canonical_ordering_sort_counting(result_kind, result_data, - run_start, i, sortbuf); + canonical_ordering_sort_counting(output + run_start, run_length, + sortbuf); } PyMem_Free(sortbuf); + result = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, output, o); + PyMem_Free(output); return result; } static int find_nfc_index(const struct reindex* nfc, Py_UCS4 code) { - unsigned int index; - for (index = 0; nfc[index].start; index++) { - unsigned int start = nfc[index].start; - if (code < start) - return -1; - if (code <= start + nfc[index].count) { - unsigned int delta = code - start; - return nfc[index].index + delta; - } + /* The table is sorted by .start ascending with disjoint [start, start+count] + ranges and ends with a sentinel whose .start exceeds every codepoint, so + a single .start <= code test per entry also stops at the sentinel. Find + the first entry past code, then range-check the candidate (entry i - 1). */ + unsigned int i; + for (i = 0; (Py_UCS4)nfc[i].start <= code; i++) { + } + if (i == 0) { + return -1; + } + unsigned int start = nfc[i - 1].start; + if (code <= start + nfc[i - 1].count) { + return nfc[i - 1].index + (code - start); } return -1; } diff --git a/Modules/unicodedata_db.h b/Modules/unicodedata_db.h index 9e88f5cca7115b0..1c961c5e329341c 100644 --- a/Modules/unicodedata_db.h +++ b/Modules/unicodedata_db.h @@ -629,7 +629,7 @@ static struct reindex nfc_first[] = { { 93539, 0, 388}, { 93543, 0, 389}, { 93545, 0, 390}, - {0,0,0} + {0x7fffffff, 0, 0} }; static struct reindex nfc_last[] = { @@ -680,7 +680,7 @@ static struct reindex nfc_last[] = { { 90398, 2, 67}, { 90409, 0, 70}, { 93543, 0, 71}, - {0,0,0} + {0x7fffffff, 0, 0} }; /* string literals */ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e279c8765dd464a..ac2f210d023487d 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -784,16 +784,12 @@ _PyDict_CheckConsistency(PyObject *op, int check_content) } -static PyDictKeysObject* -new_keys_object(uint8_t log2_size, bool unicode) +static inline int +get_log2_bytes(uint8_t log2_size) { - Py_ssize_t usable; int log2_bytes; - size_t entry_size = unicode ? sizeof(PyDictUnicodeEntry) : sizeof(PyDictKeyEntry); - assert(log2_size >= PyDict_LOG_MINSIZE); - usable = USABLE_FRACTION((size_t)1<dk_refcnt = 1; dk->dk_log2_size = log2_size; dk->dk_log2_index_bytes = log2_bytes; - dk->dk_kind = unicode ? DICT_KEYS_UNICODE : DICT_KEYS_GENERAL; + dk->dk_kind = kind; #ifdef Py_GIL_DISABLED dk->dk_mutex = (PyMutex){0}; #endif @@ -837,15 +827,51 @@ new_keys_object(uint8_t log2_size, bool unicode) dk->dk_version = 0; memset(&dk->dk_indices[0], 0xff, ((size_t)1 << log2_bytes)); memset(&dk->dk_indices[(size_t)1 << log2_bytes], 0, entry_size * usable); +} + +static PyDictKeysObject* +new_keys_object(uint8_t log2_size, bool unicode) +{ + Py_ssize_t usable = USABLE_FRACTION((size_t)1<dk_kind == DICT_KEYS_SPLIT) { + ptr = _PyDictKeys_AsSharedKeys(keys); +#ifdef Py_GIL_DISABLED + size += offsetof(struct _instancekeysobject, dsk_keys); +#endif + } #ifdef Py_GIL_DISABLED if (use_qsbr) { - _PyMem_FreeDelayed(keys, _PyDict_KeysSize(keys)); + _PyMem_FreeDelayed(ptr, size); return; } #endif @@ -853,7 +879,7 @@ free_keys_object(PyDictKeysObject *keys, bool use_qsbr) _Py_FREELIST_FREE(dictkeys, keys, PyMem_Free); } else { - PyMem_Free(keys); + PyMem_Free(ptr); } } @@ -1901,6 +1927,7 @@ insert_split_key(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash) if (ix == DKIX_EMPTY && keys->dk_usable > 0) { // Insert into new slot FT_ATOMIC_STORE_UINT32_RELAXED(keys->dk_version, 0); + _PyDict_SplitKeysInvalidated(keys); Py_ssize_t hashpos = find_empty_slot(keys, hash); ix = keys->dk_nentries; dictkeys_set_index(keys, hashpos, ix); @@ -2357,7 +2384,7 @@ dict_getitem(PyObject *op, PyObject *key, const char *warnmsg) } PyDictObject *mp = (PyDictObject *)op; - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { PyErr_FormatUnraisable(warnmsg); return NULL; @@ -2429,7 +2456,7 @@ _PyDict_LookupIndexAndValue(PyDictObject *mp, PyObject *key, PyObject **value) assert(PyDict_CheckExact((PyObject*)mp)); assert(PyUnicode_CheckExact(key)); - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type((PyObject*)mp, key); return -1; @@ -2533,7 +2560,7 @@ PyDict_GetItemRef(PyObject *op, PyObject *key, PyObject **result) return -1; } - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type(op, key); *result = NULL; @@ -2549,7 +2576,7 @@ _PyDict_GetItemRef_Unicode_LockHeld(PyDictObject *op, PyObject *key, PyObject ** ASSERT_DICT_LOCKED(op); assert(PyUnicode_CheckExact(key)); - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type((PyObject*)op, key); *result = NULL; @@ -2587,7 +2614,7 @@ PyDict_GetItemWithError(PyObject *op, PyObject *key) PyErr_BadInternalCall(); return NULL; } - hash = _PyObject_HashFast(key); + hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type(op, key); return NULL; @@ -2646,7 +2673,7 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key) Py_hash_t hash; PyObject *value; - hash = _PyObject_HashFast(key); + hash = _PyObject_HashDictKey(key); if (hash == -1) { return NULL; } @@ -2670,7 +2697,7 @@ _PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObje Py_ssize_t ix; Py_hash_t hash; - hash = _PyObject_HashFast(key); + hash = _PyObject_HashDictKey(key); if (hash == -1) { *res = PyStackRef_NULL; return; @@ -2747,7 +2774,7 @@ setitem_take2_lock_held_known_hash(PyDictObject *mp, PyObject *key, PyObject *va static int setitem_take2_lock_held(PyDictObject *mp, PyObject *key, PyObject *value) { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type((PyObject*)mp, key); Py_DECREF(key); @@ -2925,7 +2952,7 @@ int PyDict_DelItem(PyObject *op, PyObject *key) { assert(key); - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type(op, key); return -1; @@ -3039,7 +3066,7 @@ clear_embedded_values(PyDictValues *values, Py_ssize_t nentries) assert(nentries <= SHARED_KEYS_MAX_SIZE); for (Py_ssize_t i = 0; i < nentries; i++) { refs[i] = values->values[i]; - values->values[i] = NULL; + FT_ATOMIC_STORE_PTR_RELEASE(values->values[i], NULL); } values->size = 0; for (Py_ssize_t i = 0; i < nentries; i++) { @@ -3269,7 +3296,7 @@ pop_lock_held(PyObject *op, PyObject *key, PyObject **result) return 0; } - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type(op, key); if (result) { @@ -3707,7 +3734,7 @@ _PyDict_SubscriptKnownHash(PyObject *self, PyObject *key, Py_hash_t hash) PyObject * _PyDict_Subscript(PyObject *self, PyObject *key) { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type(self, key); return NULL; @@ -4659,7 +4686,7 @@ dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value) Py_hash_t hash; Py_ssize_t ix; - hash = _PyObject_HashFast(key); + hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type((PyObject*)self, key); return NULL; @@ -4696,7 +4723,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu Py_hash_t hash; Py_ssize_t ix; - hash = _PyObject_HashFast(key); + hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type(d, key); if (result) { @@ -5138,7 +5165,7 @@ static PyMethodDef mapp_methods[] = { static int dict_contains(PyObject *op, PyObject *key) { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = _PyObject_HashDictKey(key); if (hash == -1) { dict_unhashable_type(op, key); return -1; @@ -7099,16 +7126,24 @@ dictvalues_reversed(PyObject *self, PyObject *Py_UNUSED(ignored)) PyDictKeysObject * _PyDict_NewKeysForClass(PyHeapTypeObject *cls) { - PyDictKeysObject *keys = new_keys_object(NEXT_LOG2_SHARED_KEYS_MAX_SIZE, 1); - if (keys == NULL) { + int log2_bytes = get_log2_bytes(NEXT_LOG2_SHARED_KEYS_MAX_SIZE); + Py_ssize_t usable = USABLE_FRACTION((size_t)1<dk_nentries == 0); - /* Set to max size+1 as it will shrink by one before each new object */ - keys->dk_usable = SHARED_KEYS_MAX_SIZE; - keys->dk_kind = DICT_KEYS_SPLIT; - } + + shared_keys->dsk_owning_type = (PyTypeObject *)cls; + PyDictKeysObject* keys = &shared_keys->dsk_keys; + init_keys_object(keys, NEXT_LOG2_SHARED_KEYS_MAX_SIZE, log2_bytes, DICT_KEYS_SPLIT, + SHARED_KEYS_MAX_SIZE, sizeof(PyDictUnicodeEntry)); + assert(keys->dk_nentries == 0); + /* Set to max size+1 as it will shrink by one before each new object */ if (cls->ht_type.tp_dict) { PyObject *attrs = PyDict_GetItem(cls->ht_type.tp_dict, &_Py_ID(__static_attributes__)); if (attrs != NULL && PyTuple_Check(attrs)) { @@ -7126,6 +7161,25 @@ _PyDict_NewKeysForClass(PyHeapTypeObject *cls) return keys; } +void +_PyDict_RemoveKeysForClass(PyHeapTypeObject *cls) +{ + struct _instancekeysobject *shared_keys = _PyDictKeys_AsSharedKeys(cls->ht_cached_keys); + FT_ATOMIC_STORE_PTR_RELEASE(shared_keys->dsk_owning_type, NULL); + + _PyDictKeys_DecRef(cls->ht_cached_keys); +} + +void +_PyDict_SplitKeysInvalidated(PyDictKeysObject* keys) +{ + struct _instancekeysobject *shared_keys = _PyDictKeys_AsSharedKeys(keys); + PyTypeObject *type = FT_ATOMIC_LOAD_PTR_ACQUIRE(shared_keys->dsk_owning_type); + if (type) { + PyType_Modified(type); + } +} + void _PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp) { @@ -7244,7 +7298,7 @@ _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value) } if (value == NULL) { - Py_hash_t hash = _PyObject_HashFast(name); + Py_hash_t hash = _PyObject_HashDictKey(name); if (hash == -1) { dict_unhashable_type((PyObject*)dict, name); return -1; diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 34a7844c857732e..149595e64cec144 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2140,10 +2140,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args, return -1; } else { - self->filename = Py_NewRef(filename); + Py_XSETREF(self->filename, Py_NewRef(filename)); if (filename2 && filename2 != Py_None) { - self->filename2 = Py_NewRef(filename2); + Py_XSETREF(self->filename2, Py_NewRef(filename2)); } if (nargs >= 2 && nargs <= 5) { @@ -2158,10 +2158,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args, } } } - self->myerrno = Py_XNewRef(myerrno); - self->strerror = Py_XNewRef(strerror); + Py_XSETREF(self->myerrno, Py_XNewRef(myerrno)); + Py_XSETREF(self->strerror, Py_XNewRef(strerror)); #ifdef MS_WINDOWS - self->winerror = Py_XNewRef(winerror); + Py_XSETREF(self->winerror, Py_XNewRef(winerror)); #endif /* Steals the reference to args */ diff --git a/Objects/frameobject.c b/Objects/frameobject.c index f60cdb2dd1bf20d..b19889d3034e715 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -9,6 +9,7 @@ #include "pycore_function.h" // _PyFunction_FromConstructor() #include "pycore_genobject.h" // _PyGen_GetGeneratorFromFrame() #include "pycore_interpframe.h" // _PyFrame_GetLocalsArray() +#include "pycore_list.h" // _PyList_AppendTakeRef() #include "pycore_modsupport.h" // _PyArg_CheckPositional() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_opcode_metadata.h" // _PyOpcode_Caches @@ -636,9 +637,7 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored)) goto error; } - int rc = PyList_Append(items, pair); - Py_DECREF(pair); - if (rc < 0) { + if (_PyList_AppendTakeRef((PyListObject *)items, pair) < 0) { goto error; } } @@ -655,9 +654,7 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored)) goto error; } - int rc = PyList_Append(items, pair); - Py_DECREF(pair); - if (rc < 0) { + if (_PyList_AppendTakeRef((PyListObject *)items, pair) < 0) { goto error; } } diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index 9c797e8dd6fd2cc..c2083e6fcb77f47 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -572,7 +572,8 @@ PyDoc_STRVAR(genericalias__doc__, "--\n\n" "Represent a PEP 585 generic type\n" "\n" -"E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,)."); +"For example, for t = list[int], t.__origin__ is list and t.__args__\n" +"is (int,)."); static PyObject * ga_getitem(PyObject *self, PyObject *item) diff --git a/Objects/longobject.c b/Objects/longobject.c index 6e6011cb19aab5f..7a38ae8ea5a36f0 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2125,7 +2125,7 @@ long_to_decimal_string_internal(PyObject *aa, if (size_a >= 10 * _PY_LONG_MAX_STR_DIGITS_THRESHOLD / (3 * PyLong_SHIFT) + 2) { PyInterpreterState *interp = _PyInterpreterState_GET(); - int max_str_digits = interp->long_state.max_str_digits; + int max_str_digits = _Py_atomic_load_int(&interp->long_state.max_str_digits); if ((max_str_digits > 0) && (max_str_digits / (3 * PyLong_SHIFT) <= (size_a - 11) / 10)) { PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_STR, @@ -2206,7 +2206,7 @@ long_to_decimal_string_internal(PyObject *aa, } if (strlen > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) { PyInterpreterState *interp = _PyInterpreterState_GET(); - int max_str_digits = interp->long_state.max_str_digits; + int max_str_digits = _Py_atomic_load_int(&interp->long_state.max_str_digits); Py_ssize_t strlen_nosign = strlen - negative; if ((max_str_digits > 0) && (strlen_nosign > max_str_digits)) { Py_DECREF(scratch); @@ -3021,7 +3021,7 @@ long_from_string_base(const char **str, int base, PyLongObject **res) * quadratic algorithm. */ if (digits > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) { PyInterpreterState *interp = _PyInterpreterState_GET(); - int max_str_digits = interp->long_state.max_str_digits; + int max_str_digits = _Py_atomic_load_int(&interp->long_state.max_str_digits); if ((max_str_digits > 0) && (digits > max_str_digits)) { PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_INT, max_str_digits, digits); diff --git a/Objects/mimalloc/init.c b/Objects/mimalloc/init.c index 81b241063ff40fc..7711c827a58b1ca 100644 --- a/Objects/mimalloc/init.c +++ b/Objects/mimalloc/init.c @@ -183,9 +183,9 @@ mi_heap_t* _mi_heap_main_get(void) { // note: in x64 in release build `sizeof(mi_thread_data_t)` is under 4KiB (= OS page size). typedef struct mi_thread_data_s { - mi_heap_t heap; // must come first due to cast in `_mi_heap_done` + mi_heap_t heap; // must come first due to cast in `_mi_heap_done` mi_tld_t tld; - mi_memid_t memid; + mi_memid_t memid; // must come last due to zero'ing } mi_thread_data_t; @@ -231,7 +231,7 @@ static mi_thread_data_t* mi_thread_data_zalloc(void) { } if (td != NULL && !is_zero) { - _mi_memzero_aligned(td, sizeof(*td)); + _mi_memzero_aligned(td, offsetof(mi_thread_data_t,memid)); } return td; } diff --git a/Objects/object.c b/Objects/object.c index e0e26bb50d36537..bd23c2e23881949 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2821,6 +2821,13 @@ PyUnstable_Object_EnableDeferredRefcount(PyObject *op) return 0; } + if (!PyObject_GC_IsTracked(op)) { + // When deferred refcount is enabled, the object will only be + // deallocated by the tracing garbage collector. So it must be tracked + // by the garbage collector. + return 0; + } + uint8_t bits = _Py_atomic_load_uint8(&op->ob_gc_bits); if ((bits & _PyGC_BITS_DEFERRED) != 0) { diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 1809bd30451327b..0947d47c8a55582 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -363,7 +363,10 @@ _PyObject_MiRealloc(void *ctx, void *ptr, size_t nbytes) _mi_memcpy((char*)newp + offset, (char*)ptr + offset, copy_size - offset); } else { - _mi_memcpy(newp, ptr, copy_size); + // memcpy(dst, NULL, 0) is undefined behavior. See gh-151297. + if mi_likely(ptr) { + _mi_memcpy(newp, ptr, copy_size); + } } mi_free(ptr); return newp; diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 6f05395b18d781f..14c1b02405822cd 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -2206,13 +2206,14 @@ update __setitem__ static int mutablemapping_add_pairs(PyObject *self, PyObject *pairs) { + assert(!PyErr_Occurred()); + PyObject *pair, *iterator, *unexpected; int res = 0; iterator = PyObject_GetIter(pairs); if (iterator == NULL) return -1; - PyErr_Clear(); while ((pair = PyIter_Next(iterator)) != NULL) { /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */ diff --git a/Objects/setobject.c b/Objects/setobject.c index 50c5f66c2afc1b8..d198794849f0d15 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -361,7 +361,7 @@ set_unhashable_type(PyObject *key) int _PySet_AddTakeRef(PySetObject *so, PyObject *key) { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { set_unhashable_type(key); Py_DECREF(key); @@ -600,7 +600,7 @@ set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash) static int set_add_key(PySetObject *so, PyObject *key) { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { set_unhashable_type(key); return -1; @@ -611,7 +611,7 @@ set_add_key(PySetObject *so, PyObject *key) static int set_contains_key(PySetObject *so, PyObject *key) { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { set_unhashable_type(key); return -1; @@ -622,7 +622,7 @@ set_contains_key(PySetObject *so, PyObject *key) static int set_discard_key(PySetObject *so, PyObject *key) { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { set_unhashable_type(key); return -1; @@ -2514,7 +2514,7 @@ _PySet_Contains(PySetObject *so, PyObject *key) { assert(so); - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) { set_unhashable_type(key); @@ -2574,7 +2574,7 @@ static PyObject * frozenset___contains___impl(PySetObject *so, PyObject *key) /*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/ { - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) { set_unhashable_type(key); @@ -3039,7 +3039,7 @@ PySet_Contains(PyObject *anyset, PyObject *key) } PySetObject *so = (PySetObject *)anyset; - Py_hash_t hash = _PyObject_HashFast(key); + Py_hash_t hash = PyObject_Hash(key); if (hash == -1) { set_unhashable_type(key); return -1; diff --git a/Objects/stringlib/join.h b/Objects/stringlib/join.h index de6bd83ffe4c8bc..fe460d41f6700f8 100644 --- a/Objects/stringlib/join.h +++ b/Objects/stringlib/join.h @@ -68,13 +68,18 @@ STRINGLIB(bytes_join)(PyObject *sep, PyObject *iterable) buffers[i].len = PyBytes_GET_SIZE(item); } else { + /* item is only borrowed; its __buffer__() may run Python that + drops the sequence's last reference to it. */ + Py_INCREF(item); if (PyObject_GetBuffer(item, &buffers[i], PyBUF_SIMPLE) != 0) { PyErr_Format(PyExc_TypeError, "sequence item %zd: expected a bytes-like object, " "%.80s found", i, Py_TYPE(item)->tp_name); + Py_DECREF(item); goto error; } + Py_DECREF(item); /* If the backing objects are mutable, then dropping the GIL * opens up race conditions where another thread tries to modify * the object which we hold a buffer on it. Such code has data diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 7ad83e37bd732dd..bb5e18cb790acf0 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -957,8 +957,10 @@ tuple___getnewargs___impl(PyTupleObject *self) PyDoc_STRVAR(tuple_class_getitem_doc, "Tuples are generic over the types of their contents.\n\n\ -For example, use ``tuple[int, str]`` for a pair whose first element is an int and second element is a string.\n\n\ -Tuples also support the form ``tuple[T, ...]`` to indicate an arbitrary length tuple of elements of type T."); +For example, use ``tuple[int, str]`` for a pair whose first element\n\ +is an int and second element is a string.\n\n\ +Tuples also support the form ``tuple[T, ...]`` to indicate\n\ +an arbitrary length tuple of elements of type T."); static PyMethodDef tuple_methods[] = { TUPLE___GETNEWARGS___METHODDEF diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e0464fe6475cfd2..59593fd0f6a0b78 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1594,7 +1594,12 @@ type_set_qualname(PyObject *tp, PyObject *value, void *context) } et = (PyHeapTypeObject*)type; - Py_SETREF(et->ht_qualname, Py_NewRef(value)); + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyEval_StopTheWorld(interp); + PyObject *old_qualname = et->ht_qualname; + et->ht_qualname = Py_NewRef(value); + _PyEval_StartTheWorld(interp); + Py_DECREF(old_qualname); return 0; } @@ -3712,9 +3717,9 @@ find_best_base(PyObject *bases) for (i = 0; i < n; i++) { PyObject *base_proto = PyTuple_GET_ITEM(bases, i); if (!PyType_Check(base_proto)) { - PyErr_SetString( + PyErr_Format( PyExc_TypeError, - "bases must be types"); + "bases must be types; got '%T'", base_proto); return NULL; } PyTypeObject *base_i = (PyTypeObject *)base_proto; @@ -3788,7 +3793,7 @@ solid_base(PyTypeObject *type) // or when __bases__ is re-assigned. Since the slots are read without atomic // operations and without locking, we can only safely update them while the // world is stopped. However, with the world stopped, we are very limited on -// which APIs can be safely used. For example, calling _PyObject_HashFast() +// which APIs can be safely used. For example, calling _PyObject_HashDictKey() // or _PyDict_GetItemRef_KnownHash() are not safe and can potentially cause // deadlocks. Hashing can be re-entrant and _PyDict_GetItemRef_KnownHash can // acquire a lock if the dictionary is not owned by the current thread, to @@ -4162,8 +4167,9 @@ _PyType_CalculateMetaclass(PyTypeObject *metatype, PyObject *bases) for (i = 0; i < nbases; i++) { tmp = PyTuple_GET_ITEM(bases, i); tmptype = Py_TYPE(tmp); - if (PyType_IsSubtype(winner, tmptype)) + if (PyType_IsSubtype(winner, tmptype)) { continue; + } if (PyType_IsSubtype(tmptype, winner)) { winner = tmptype; continue; @@ -5524,6 +5530,12 @@ type_from_slots_or_spec( } } + /* Calculate best base, and check that all bases are type objects */ + PyTypeObject *base = find_best_base(bases); // borrowed ref + if (base == NULL) { + goto finally; + } + /* Calculate the metaclass */ if (!metaclass) { @@ -5546,11 +5558,6 @@ type_from_slots_or_spec( goto finally; } - /* Calculate best base, and check that all bases are type objects */ - PyTypeObject *base = find_best_base(bases); // borrowed ref - if (base == NULL) { - goto finally; - } // find_best_base() should check Py_TPFLAGS_BASETYPE & raise a proper // exception, here we just check its work assert(_PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)); @@ -6129,7 +6136,7 @@ PyObject_GetItemData(PyObject *obj) static int find_name_in_mro(PyTypeObject *type, PyObject *name, _PyStackRef *out) { - Py_hash_t hash = _PyObject_HashFast(name); + Py_hash_t hash = _PyObject_HashDictKey(name); if (hash == -1) { PyErr_Clear(); return -1; @@ -7018,7 +7025,7 @@ type_dealloc(PyObject *self) Py_XDECREF(et->ht_qualname); Py_XDECREF(et->ht_slots); if (et->ht_cached_keys) { - _PyDictKeys_DecRef(et->ht_cached_keys); + _PyDict_RemoveKeysForClass(et); } Py_XDECREF(et->ht_module); PyMem_Free(et->_ht_tpname); @@ -11327,6 +11334,7 @@ slot_bf_getbuffer(PyObject *self, Py_buffer *buffer, int flags) wrapper = PyObject_GC_New(PyBufferWrapper, &_PyBufferWrapper_Type); if (wrapper == NULL) { + PyBuffer_Release(buffer); goto fail; } wrapper->mv = ret; diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 8ad590cc6e60936..78750a955d2a492 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -2311,8 +2311,9 @@ PyDoc_STRVAR(generic_class_getitem_doc, "Parameterizes a generic class.\n\ \n\ At least, parameterizing a generic class is the *main* thing this\n\ -method does. For example, for some generic class `Foo`, this is called\n\ -when we do `Foo[int]` - there, with `cls=Foo` and `params=int`.\n\ +method does. For example, for some generic class `Foo`, this is\n\ +called when we do `Foo[int]` - there, with `cls=Foo` and\n\ +`params=int`.\n\ \n\ However, note that this method is also called when defining generic\n\ classes in the first place with `class Foo[T]: ...`.\n\ diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 8446a2dbcf75593..daeba5368b21660 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -416,8 +416,15 @@ get_or_create_weakref(PyTypeObject *type, PyObject *obj, PyObject *callback) Py_TYPE(obj)->tp_name); return NULL; } - if (callback == Py_None) + if (callback == Py_None) { callback = NULL; + } + if (callback != NULL && !PyCallable_Check(callback)) { + PyErr_Format(PyExc_TypeError, + "callback must be callable or None, not '%T'", + callback); + return NULL; + } PyWeakReference **list = GET_WEAKREFS_LISTPTR(obj); if ((type == &_PyWeakref_RefType) || diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index 62312acf248b918..64e50b67be46561 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -133,6 +133,7 @@ + diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters index b0e75ce433ab14d..a3b62e1df663e00 100644 --- a/PCbuild/_testcapi.vcxproj.filters +++ b/PCbuild/_testcapi.vcxproj.filters @@ -132,6 +132,9 @@ Source Files + + Source Files + diff --git a/PCbuild/_testlimitedcapi.vcxproj b/PCbuild/_testlimitedcapi.vcxproj index 34841ff9780a011..69558d204dbb8e7 100644 --- a/PCbuild/_testlimitedcapi.vcxproj +++ b/PCbuild/_testlimitedcapi.vcxproj @@ -117,6 +117,7 @@ + diff --git a/PCbuild/_testlimitedcapi.vcxproj.filters b/PCbuild/_testlimitedcapi.vcxproj.filters index a29973786c9485d..2bcc3f6ff176bd9 100644 --- a/PCbuild/_testlimitedcapi.vcxproj.filters +++ b/PCbuild/_testlimitedcapi.vcxproj.filters @@ -33,6 +33,7 @@ + diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index f6ba3d0fef3a60b..47399fe65d1e542 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,9 +54,9 @@ echo.Fetching external libraries... 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-3.5.6 +if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-3.5.7 set libraries=%libraries% mpdecimal-4.0.0 -set libraries=%libraries% sqlite-3.53.1.0 +set libraries=%libraries% sqlite-3.53.2.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-9.0.3.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-9.0.3.1 set libraries=%libraries% xz-5.8.1.1 @@ -79,7 +79,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.4 -if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.5.6 +if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-3.5.7 if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-9.0.3.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 if NOT "%IncludeLLVM%"=="false" set binaries=%binaries% llvm-21.1.4.0 diff --git a/PCbuild/python.props b/PCbuild/python.props index edcda8fd8fc55d9..8d931bba28a389a 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -98,15 +98,15 @@ - $(ExternalsDir)sqlite-3.53.1.0\ + $(ExternalsDir)sqlite-3.53.2.0\ $(ExternalsDir)bzip2-1.0.8\ $(ExternalsDir)xz-5.8.1.1\ $(ExternalsDir)libffi-3.4.4\ $(libffiDir)$(ArchName)\ $(libffiOutDir)include $(ExternalsDir)\mpdecimal-4.0.0\ - $(ExternalsDir)openssl-3.5.6\ - $(ExternalsDir)openssl-bin-3.5.6\$(ArchName)\ + $(ExternalsDir)openssl-3.5.7\ + $(ExternalsDir)openssl-bin-3.5.7\$(ArchName)\ $(opensslOutDir)include $(ExternalsDir)\nasm-2.11.06\ $(ExternalsDir)\zlib-1.3.1\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index ea8adf21c279a68..7c5eab2eb75a1de 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -242,7 +242,7 @@ _ssl again when building. _sqlite3 - Wraps SQLite 3.53.1, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.53.2, which is itself built by sqlite3.vcxproj Homepage: https://www.sqlite.org/ diff --git a/Parser/action_helpers.c b/Parser/action_helpers.c index 5e52bb838719046..c74eb34deb7c35c 100644 --- a/Parser/action_helpers.c +++ b/Parser/action_helpers.c @@ -1416,6 +1416,9 @@ expr_ty _PyPegen_template_str(Parser *p, Token *a, asdl_expr_seq *raw_expressions, Token *b) { asdl_expr_seq *resized_exprs = _get_resized_exprs(p, a, raw_expressions, b, TSTRING); + if (resized_exprs == NULL) { + return NULL; + } return _PyAST_TemplateStr(resized_exprs, a->lineno, a->col_offset, b->end_lineno, b->end_col_offset, p->arena); @@ -1425,6 +1428,9 @@ expr_ty _PyPegen_joined_str(Parser *p, Token* a, asdl_expr_seq* raw_expressions, Token*b) { asdl_expr_seq *resized_exprs = _get_resized_exprs(p, a, raw_expressions, b, FSTRING); + if (resized_exprs == NULL) { + return NULL; + } return _PyAST_JoinedStr(resized_exprs, a->lineno, a->col_offset, b->end_lineno, b->end_col_offset, p->arena); diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index ed1d2e08df8f400..e2a57177d20afb7 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -487,7 +487,7 @@ def visitField(self, sum): class Obj2ModPrototypeVisitor(PickleVisitor): def visitProduct(self, prod, name): - code = "static int obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena);" + code = "static int obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, const char* field, PyArena* arena);" self.emit(code % (name, get_c_type(name)), 0) visitSum = visitProduct @@ -511,7 +511,7 @@ def recursive_call(self, node, level): def funcHeader(self, name): ctype = get_c_type(name) self.emit("int", 0) - self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) + self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, const char* field, PyArena* arena)" % (name, ctype), 0) self.emit("{", 0) self.emit("int isinstance;", 1) self.emit("", 0) @@ -547,6 +547,18 @@ def simpleSum(self, sum, name): def buildArgs(self, fields): return ", ".join(fields + ["arena"]) + def typeCheck(self, name): + self.emit("tp = state->%s_type;" % name, 1) + self.emit("isinstance = PyObject_IsInstance(obj, tp);", 1) + self.emit("if (isinstance == -1) {", 1) + self.emit("return 1;", 2) + self.emit("}", 1) + self.emit("if (!isinstance && field != NULL) {", 1) + error = "field '%%s' was expecting node of type '%s', got '%%s'" % name + self.emit("PyErr_Format(PyExc_TypeError, \"%s\", field, _PyType_Name(Py_TYPE(obj)));" % error, 2, reflow=False) + self.emit("return 1;", 2) + self.emit("}", 1) + def complexSum(self, sum, name): self.funcHeader(name) self.emit("PyObject *tmp = NULL;", 1) @@ -559,6 +571,7 @@ def complexSum(self, sum, name): self.emit("*out = NULL;", 2) self.emit("return 0;", 2) self.emit("}", 1) + self.typeCheck(name) for a in sum.attributes: self.visitField(a, name, sum=sum, depth=1) for t in sum.types: @@ -593,7 +606,7 @@ def visitSum(self, sum, name): def visitProduct(self, prod, name): ctype = get_c_type(name) self.emit("int", 0) - self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) + self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, const char* field, PyArena* arena)" % (name, ctype), 0) self.emit("{", 0) self.emit("PyObject* tmp = NULL;", 1) for f in prod.fields: @@ -694,8 +707,8 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): self.emit("%s val;" % ctype, depth+2) self.emit("PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));", depth+2) with self.recursive_call(name, depth+2): - self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" % - field.type, depth+2, reflow=False) + self.emit("res = obj2ast_%s(state, tmp2, &val, \"%s\", arena);" % + (field.type, field.name), depth+2, reflow=False) self.emit("Py_DECREF(tmp2);", depth+2) self.emit("if (res != 0) goto failed;", depth+2) self.emit("if (len != PyList_GET_SIZE(tmp)) {", depth+2) @@ -709,8 +722,8 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): self.emit("}", depth+1) else: with self.recursive_call(name, depth+1): - self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" % - (field.type, field.name), depth+1) + self.emit("res = obj2ast_%s(state, tmp, &%s, \"%s\", arena);" % + (field.type, field.name, field.name), depth+1) self.emit("if (res != 0) goto failed;", depth+1) self.emit("Py_CLEAR(tmp);", depth+1) @@ -1701,7 +1714,9 @@ def visitModule(self, mod): /* Conversion Python -> AST */ -static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (obj == Py_None) obj = NULL; @@ -1718,7 +1733,9 @@ def visitModule(self, mod): return 0; } -static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (_PyArena_AddPyObject(arena, obj) < 0) { *out = NULL; @@ -1728,29 +1745,29 @@ def visitModule(self, mod): return 0; } -static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && obj != Py_None) { - PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { - PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string or bytes object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, PyArena* arena) +static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, const char* field, PyArena* arena) { int i; if (!PyLong_Check(obj)) { - PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); + PyErr_Format(PyExc_ValueError, "field \\"%s\\" got an invalid integer value: %R", field, obj); return -1; } @@ -2150,7 +2167,7 @@ class PartingShots(StaticVisitor): } mod_ty res = NULL; - if (obj2ast_mod(state, ast, &res, arena) != 0) + if (obj2ast_mod(state, ast, &res, NULL, arena) != 0) return NULL; else return res; diff --git a/Parser/lexer/state.c b/Parser/lexer/state.c index 3663dc3eb7f9f69..5cf9b4d768c3ebb 100644 --- a/Parser/lexer/state.c +++ b/Parser/lexer/state.c @@ -15,8 +15,11 @@ _PyTokenizer_tok_new(void) struct tok_state *tok = (struct tok_state *)PyMem_Calloc( 1, sizeof(struct tok_state)); - if (tok == NULL) + if (tok == NULL) { + PyErr_NoMemory(); return NULL; + } + tok->buf = tok->cur = tok->inp = NULL; tok->fp_interactive = 0; tok->interactive_src_start = NULL; diff --git a/Parser/pegen.c b/Parser/pegen.c index 569f5afb3120085..bb222b50fc095f2 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -9,6 +9,7 @@ #include "lexer/lexer.h" #include "tokenizer/tokenizer.h" +#include "tokenizer/helpers.h" #include "pegen.h" // Internal parser functions @@ -993,7 +994,7 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2); if (tok == NULL) { if (PyErr_Occurred()) { - _PyPegen_raise_tokenizer_init_error(filename_ob); + _PyTokenizer_raise_init_error(filename_ob); return NULL; } return NULL; @@ -1051,7 +1052,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen } if (tok == NULL) { if (PyErr_Occurred()) { - _PyPegen_raise_tokenizer_init_error(filename_ob); + _PyTokenizer_raise_init_error(filename_ob); } return NULL; } diff --git a/Parser/pegen.h b/Parser/pegen.h index 85c9ada765d9bd4..5c461e82a7f0fa7 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -174,7 +174,6 @@ typedef enum { } TARGETS_TYPE; int _Pypegen_raise_decode_error(Parser *p); -void _PyPegen_raise_tokenizer_init_error(PyObject *filename); int _Pypegen_tokenizer_error(Parser *p); void *_PyPegen_raise_error(Parser *p, PyObject *errtype, int use_mark, const char *errmsg, ...); void *_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 312699415efd9af..b13e1c079220a92 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -10,53 +10,6 @@ // TOKENIZER ERRORS -void -_PyPegen_raise_tokenizer_init_error(PyObject *filename) -{ - if (!(PyErr_ExceptionMatches(PyExc_LookupError) - || PyErr_ExceptionMatches(PyExc_SyntaxError) - || PyErr_ExceptionMatches(PyExc_ValueError) - || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { - return; - } - PyObject *errstr = NULL; - PyObject *tuple = NULL; - PyObject *type; - PyObject *value; - PyObject *tback; - PyErr_Fetch(&type, &value, &tback); - if (PyErr_GivenExceptionMatches(value, PyExc_SyntaxError)) { - if (PyObject_SetAttr(value, &_Py_ID(filename), filename)) { - goto error; - } - PyErr_Restore(type, value, tback); - return; - } - errstr = PyObject_Str(value); - if (!errstr) { - goto error; - } - - PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); - if (!tmp) { - goto error; - } - - tuple = _PyTuple_FromPair(errstr, tmp); - Py_DECREF(tmp); - if (!tuple) { - goto error; - } - PyErr_SetObject(PyExc_SyntaxError, tuple); - -error: - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(tback); - Py_XDECREF(errstr); - Py_XDECREF(tuple); -} - static inline void raise_unclosed_parentheses_error(Parser *p) { int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; diff --git a/Parser/tokenizer/file_tokenizer.c b/Parser/tokenizer/file_tokenizer.c index 8c836a3f7258296..a11702557a07af3 100644 --- a/Parser/tokenizer/file_tokenizer.c +++ b/Parser/tokenizer/file_tokenizer.c @@ -378,6 +378,7 @@ _PyTokenizer_FromFile(FILE *fp, const char* enc, return NULL; if ((tok->buf = (char *)PyMem_Malloc(BUFSIZ)) == NULL) { _PyTokenizer_Free(tok); + PyErr_NoMemory(); return NULL; } tok->cur = tok->inp = tok->buf; diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index 9542969ad3127b9..62b0971d418c396 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -1,6 +1,8 @@ #include "Python.h" #include "errcode.h" +#include "pycore_runtime.h" // _Py_ID() #include "pycore_token.h" +#include "pycore_tuple.h" // _PyTuple_FromPair #include "../lexer/state.h" @@ -149,6 +151,53 @@ _PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_inval return 0; } +void +_PyTokenizer_raise_init_error(PyObject *filename) +{ + if (!(PyErr_ExceptionMatches(PyExc_LookupError) + || PyErr_ExceptionMatches(PyExc_SyntaxError) + || PyErr_ExceptionMatches(PyExc_ValueError) + || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { + return; + } + PyObject *errstr = NULL; + PyObject *tuple = NULL; + PyObject *type; + PyObject *value; + PyObject *tback; + PyErr_Fetch(&type, &value, &tback); + if (PyErr_GivenExceptionMatches(value, PyExc_SyntaxError)) { + if (PyObject_SetAttr(value, &_Py_ID(filename), filename)) { + goto error; + } + PyErr_Restore(type, value, tback); + return; + } + errstr = PyObject_Str(value); + if (!errstr) { + goto error; + } + + PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); + if (!tmp) { + goto error; + } + + tuple = _PyTuple_FromPair(errstr, tmp); + Py_DECREF(tmp); + if (!tuple) { + goto error; + } + PyErr_SetObject(PyExc_SyntaxError, tuple); + +error: + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tback); + Py_XDECREF(errstr); + Py_XDECREF(tuple); +} + int _PyTokenizer_parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...) { @@ -193,6 +242,7 @@ _PyTokenizer_new_string(const char *s, Py_ssize_t len, struct tok_state *tok) char* result = (char *)PyMem_Malloc(len + 1); if (!result) { tok->done = E_NOMEM; + PyErr_NoMemory(); return NULL; } memcpy(result, s, len); @@ -221,6 +271,7 @@ _PyTokenizer_translate_newlines(const char *s, int exec_input, int preserve_crlf buf = PyMem_Malloc(needed_length); if (buf == NULL) { tok->done = E_NOMEM; + PyErr_NoMemory(); return NULL; } for (current = buf; *s; s++, current++) { @@ -416,8 +467,8 @@ _PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_sta if (tok->encoding == NULL) { assert(tok->decoding_readline == NULL); if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { + _PyTokenizer_raise_init_error(tok->filename); _PyTokenizer_error_ret(tok); - PyErr_Format(PyExc_SyntaxError, "encoding problem: %s", cs); PyMem_Free(cs); return 0; } diff --git a/Parser/tokenizer/helpers.h b/Parser/tokenizer/helpers.h index 98f6445d5a3b40e..34303999a60aff7 100644 --- a/Parser/tokenizer/helpers.h +++ b/Parser/tokenizer/helpers.h @@ -15,6 +15,7 @@ int _PyTokenizer_indenterror(struct tok_state *tok); int _PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_invalid_escape_char); int _PyTokenizer_parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...); char *_PyTokenizer_error_ret(struct tok_state *tok); +void _PyTokenizer_raise_init_error(PyObject *filename); char *_PyTokenizer_new_string(const char *s, Py_ssize_t len, struct tok_state *tok); char *_PyTokenizer_translate_newlines(const char *s, int exec_input, int preserve_crlf, struct tok_state *tok); diff --git a/Parser/tokenizer/readline_tokenizer.c b/Parser/tokenizer/readline_tokenizer.c index 0f7769aeb8fd570..917f7b40cfbbfed 100644 --- a/Parser/tokenizer/readline_tokenizer.c +++ b/Parser/tokenizer/readline_tokenizer.c @@ -114,6 +114,7 @@ _PyTokenizer_FromReadline(PyObject* readline, const char* enc, return NULL; if ((tok->buf = (char *)PyMem_Malloc(BUFSIZ)) == NULL) { _PyTokenizer_Free(tok); + PyErr_NoMemory(); return NULL; } tok->cur = tok->inp = tok->buf; diff --git a/Platforms/Android/__main__.py b/Platforms/Android/__main__.py index 5c41aaca6ebf0b4..063e1f316031443 100755 --- a/Platforms/Android/__main__.py +++ b/Platforms/Android/__main__.py @@ -219,8 +219,8 @@ def unpack_deps(host, prefix_dir, cache_dir): for name_ver in [ "bzip2-1.0.8-3", "libffi-3.4.4-3", - "openssl-3.5.6-0", - "sqlite-3.53.1-0", + "openssl-3.5.7-0", + "sqlite-3.53.2-0", "xz-5.4.6-1", "zstd-1.5.7-2" ]: diff --git a/Platforms/Apple/__main__.py b/Platforms/Apple/__main__.py index d94198a309f9269..9f2d2afb0aa0f67 100644 --- a/Platforms/Apple/__main__.py +++ b/Platforms/Apple/__main__.py @@ -319,7 +319,7 @@ def unpack_deps( for name_ver in [ "BZip2-1.0.8-2", "libFFI-3.4.7-2", - "OpenSSL-3.5.6-1", + "OpenSSL-3.5.7-1", "XZ-5.6.4-2", "mpdecimal-4.0.0-2", "zstd-1.5.7-1", diff --git a/Platforms/emscripten/__main__.py b/Platforms/emscripten/__main__.py index c1eac8005474fda..c2fb1c4c36e6087 100644 --- a/Platforms/emscripten/__main__.py +++ b/Platforms/emscripten/__main__.py @@ -650,7 +650,7 @@ def add_cross_build_dir_option(subcommand): help=( "Path to the cross-build directory " f"(default: {DEFAULT_CROSS_BUILD_DIR}). " - "Can also be set with the CROSS_BUILD_DIR environment variable.", + "Can also be set with the CROSS_BUILD_DIR environment variable." ), ) @@ -743,7 +743,7 @@ def main(): nargs=argparse.REMAINDER, help=( "Arguments to pass to the emscripten Python " - "(use '--' to separate from run options)", + "(use '--' to separate from run options)" ), ) add_cross_build_dir_option(run) diff --git a/Platforms/emscripten/config.toml b/Platforms/emscripten/config.toml index ba2dc8f4a482bfa..401e9396ddbb009 100644 --- a/Platforms/emscripten/config.toml +++ b/Platforms/emscripten/config.toml @@ -1,7 +1,7 @@ # Any data that can vary between Python versions is to be kept in this file. # This allows for blanket copying of the Emscripten build code between supported # Python versions. -emscripten-version = "4.0.12" +emscripten-version = "4.0.19" node-version = "24" test-args = [ "-m", "test", diff --git a/Platforms/emscripten/streams.mjs b/Platforms/emscripten/streams.mjs index 76ad79f9247f4cf..1b121d48d4e76c6 100644 --- a/Platforms/emscripten/streams.mjs +++ b/Platforms/emscripten/streams.mjs @@ -112,7 +112,7 @@ const prepareBuffer = (buffer, offset, length) => const TTY_OPS = { ioctl_tiocgwinsz(tty) { - return tty.devops.ioctl_tiocgwinsz?.(); + return tty.devops.ioctl_tiocgwinsz?.() ?? [24, 80]; }, }; @@ -188,6 +188,10 @@ class NodeReader { fsync() { nodeFsync(this.nodeStream.fd); } + + ioctl_tiocgwinsz() { + return [this.nodeStream.rows ?? 24, this.nodeStream.columns ?? 80]; + } } class NodeWriter { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 7246cc06ffff036..74d0fe37ddaeadb 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -2715,8 +2715,8 @@ do_tstate_ensure(void *arg) PyThreadState_Release(tokens[2]); PyThreadState_Release(tokens[1]); PyThreadState_Release(tokens[0]); - PyInterpreterGuard_Close(guard); _Py_atomic_store_int(&data->done, 1); + PyInterpreterGuard_Close(guard); } static int diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 5f3d9c4b17410fb..49b6bf1d12b6fab 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -6026,7 +6026,9 @@ static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b) /* Conversion Python -> AST */ -static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (obj == Py_None) obj = NULL; @@ -6043,7 +6045,9 @@ static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyO return 0; } -static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (_PyArena_AddPyObject(arena, obj) < 0) { *out = NULL; @@ -6053,29 +6057,29 @@ static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, P return 0; } -static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && obj != Py_None) { - PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { - PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string or bytes object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, PyArena* arena) +static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, const char* field, PyArena* arena) { int i; if (!PyLong_Check(obj)) { - PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); + PyErr_Format(PyExc_ValueError, "field \"%s\" got an invalid integer value: %R", field, obj); return -1; } @@ -6954,43 +6958,52 @@ init_types(void *arg) } static int obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_expr_context(struct ast_state *state, PyObject* obj, - expr_context_ty* out, PyArena* arena); + expr_context_ty* out, const char* field, + PyArena* arena); static int obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_operator(struct ast_state *state, PyObject* obj, - operator_ty* out, PyArena* arena); + operator_ty* out, const char* field, PyArena* + arena); static int obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_comprehension(struct ast_state *state, PyObject* obj, - comprehension_ty* out, PyArena* arena); + comprehension_ty* out, const char* field, + PyArena* arena); static int obj2ast_excepthandler(struct ast_state *state, PyObject* obj, - excepthandler_ty* out, PyArena* arena); + excepthandler_ty* out, const char* field, + PyArena* arena); static int obj2ast_arguments(struct ast_state *state, PyObject* obj, - arguments_ty* out, PyArena* arena); + arguments_ty* out, const char* field, PyArena* + arena); static int obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_withitem(struct ast_state *state, PyObject* obj, - withitem_ty* out, PyArena* arena); + withitem_ty* out, const char* field, PyArena* + arena); static int obj2ast_match_case(struct ast_state *state, PyObject* obj, - match_case_ty* out, PyArena* arena); + match_case_ty* out, const char* field, PyArena* + arena); static int obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_type_ignore(struct ast_state *state, PyObject* obj, - type_ignore_ty* out, PyArena* arena); + type_ignore_ty* out, const char* field, PyArena* + arena); static int obj2ast_type_param(struct ast_state *state, PyObject* obj, - type_param_ty* out, PyArena* arena); + type_param_ty* out, const char* field, PyArena* + arena); mod_ty _PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores, @@ -10855,7 +10868,8 @@ ast2obj_type_param(struct ast_state *state, void* _o) int -obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) +obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, const char* + field, PyArena* arena) { int isinstance; @@ -10866,6 +10880,15 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) *out = NULL; return 0; } + tp = state->mod_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'mod', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } tp = state->Module_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -10901,7 +10924,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Module' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -10939,7 +10962,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Module' node")) { goto failed; } - res = obj2ast_type_ignore(state, tmp2, &val, arena); + res = obj2ast_type_ignore(state, tmp2, &val, "type_ignores", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -10989,7 +11012,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Interactive' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11025,7 +11048,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Expression' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &body, arena); + res = obj2ast_expr(state, tmp, &body, "body", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11069,7 +11092,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "argtypes", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11093,7 +11116,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &returns, arena); + res = obj2ast_expr(state, tmp, &returns, "returns", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11110,8 +11133,8 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) } int -obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* - arena) +obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, const char* + field, PyArena* arena) { int isinstance; @@ -11126,6 +11149,15 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* *out = NULL; return 0; } + tp = state->stmt_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'stmt', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -11138,7 +11170,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11155,7 +11187,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11172,7 +11204,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11189,7 +11221,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11220,7 +11252,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11237,7 +11269,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_arguments(state, tmp, &args, arena); + res = obj2ast_arguments(state, tmp, &args, "args", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11268,7 +11300,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11306,7 +11338,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "decorator_list", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11330,7 +11362,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &returns, arena); + res = obj2ast_expr(state, tmp, &returns, "returns", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11347,7 +11379,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11378,7 +11411,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11423,7 +11456,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11440,7 +11473,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_arguments(state, tmp, &args, arena); + res = obj2ast_arguments(state, tmp, &args, "args", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11471,7 +11504,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11509,7 +11542,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "decorator_list", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11533,7 +11566,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &returns, arena); + res = obj2ast_expr(state, tmp, &returns, "returns", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11550,7 +11583,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11581,7 +11615,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11625,7 +11659,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11656,7 +11690,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "bases", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11694,7 +11728,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_keyword(state, tmp2, &val, arena); + res = obj2ast_keyword(state, tmp2, &val, "keywords", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11732,7 +11766,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11770,7 +11804,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "decorator_list", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11808,7 +11842,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11846,7 +11880,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Return' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11890,7 +11924,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Delete' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "targets", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11943,7 +11977,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assign' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "targets", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11967,7 +12001,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11984,7 +12018,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assign' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12016,7 +12051,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &name, arena); + res = obj2ast_expr(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12047,7 +12082,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12071,7 +12106,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12103,7 +12138,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12120,7 +12155,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { goto failed; } - res = obj2ast_operator(state, tmp, &op, arena); + res = obj2ast_operator(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12137,7 +12172,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12170,7 +12205,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12187,7 +12222,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &annotation, arena); + res = obj2ast_expr(state, tmp, &annotation, "annotation", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12204,7 +12239,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12221,7 +12256,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_int(state, tmp, &simple, arena); + res = obj2ast_int(state, tmp, &simple, "simple", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12255,7 +12290,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12272,7 +12307,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &iter, arena); + res = obj2ast_expr(state, tmp, &iter, "iter", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12303,7 +12338,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12341,7 +12376,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12365,7 +12400,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12399,7 +12435,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12416,7 +12452,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &iter, arena); + res = obj2ast_expr(state, tmp, &iter, "iter", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12447,7 +12483,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12485,7 +12521,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12509,7 +12545,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12542,7 +12579,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'While' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12573,7 +12610,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'While' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12611,7 +12648,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'While' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12650,7 +12687,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'If' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12681,7 +12718,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'If' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12719,7 +12756,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'If' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12772,7 +12809,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'With' node")) { goto failed; } - res = obj2ast_withitem(state, tmp2, &val, arena); + res = obj2ast_withitem(state, tmp2, &val, "items", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12810,7 +12847,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'With' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12834,7 +12871,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'With' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12880,7 +12918,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { goto failed; } - res = obj2ast_withitem(state, tmp2, &val, arena); + res = obj2ast_withitem(state, tmp2, &val, "items", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12918,7 +12956,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12942,7 +12980,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12973,7 +13012,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Match' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &subject, arena); + res = obj2ast_expr(state, tmp, &subject, "subject", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13004,7 +13043,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Match' node")) { goto failed; } - res = obj2ast_match_case(state, tmp2, &val, arena); + res = obj2ast_match_case(state, tmp2, &val, "cases", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13042,7 +13081,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Raise' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &exc, arena); + res = obj2ast_expr(state, tmp, &exc, "exc", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13059,7 +13098,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Raise' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &cause, arena); + res = obj2ast_expr(state, tmp, &cause, "cause", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13106,7 +13145,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13144,7 +13183,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_excepthandler(state, tmp2, &val, arena); + res = obj2ast_excepthandler(state, tmp2, &val, "handlers", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13182,7 +13221,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13220,7 +13259,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "finalbody", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13274,7 +13313,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13312,7 +13351,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_excepthandler(state, tmp2, &val, arena); + res = obj2ast_excepthandler(state, tmp2, &val, "handlers", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13350,7 +13389,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13388,7 +13427,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "finalbody", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13426,7 +13465,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assert' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13443,7 +13482,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assert' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &msg, arena); + res = obj2ast_expr(state, tmp, &msg, "msg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13488,7 +13527,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Import' node")) { goto failed; } - res = obj2ast_alias(state, tmp2, &val, arena); + res = obj2ast_alias(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13512,7 +13551,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Import' node")) { goto failed; } - res = obj2ast_int(state, tmp, &is_lazy, arena); + res = obj2ast_int(state, tmp, &is_lazy, "is_lazy", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13545,7 +13584,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &module, arena); + res = obj2ast_identifier(state, tmp, &module, "module", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13576,7 +13615,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_alias(state, tmp2, &val, arena); + res = obj2ast_alias(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13600,7 +13639,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_int(state, tmp, &level, arena); + res = obj2ast_int(state, tmp, &level, "level", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13617,7 +13656,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_int(state, tmp, &is_lazy, arena); + res = obj2ast_int(state, tmp, &is_lazy, "is_lazy", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13661,7 +13700,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Global' node")) { goto failed; } - res = obj2ast_identifier(state, tmp2, &val, arena); + res = obj2ast_identifier(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13712,7 +13751,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Nonlocal' node")) { goto failed; } - res = obj2ast_identifier(state, tmp2, &val, arena); + res = obj2ast_identifier(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13749,7 +13788,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Expr' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13803,8 +13842,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } int -obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* - arena) +obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, const char* + field, PyArena* arena) { int isinstance; @@ -13819,6 +13858,15 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* *out = NULL; return 0; } + tp = state->expr_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'expr', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -13831,7 +13879,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13848,7 +13896,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13865,7 +13913,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13882,7 +13930,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13908,7 +13956,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) { goto failed; } - res = obj2ast_boolop(state, tmp, &op, arena); + res = obj2ast_boolop(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13939,7 +13987,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13977,7 +14025,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13994,7 +14042,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14026,7 +14074,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &left, arena); + res = obj2ast_expr(state, tmp, &left, "left", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14043,7 +14091,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { goto failed; } - res = obj2ast_operator(state, tmp, &op, arena); + res = obj2ast_operator(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14060,7 +14108,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &right, arena); + res = obj2ast_expr(state, tmp, &right, "right", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14091,7 +14139,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) { goto failed; } - res = obj2ast_unaryop(state, tmp, &op, arena); + res = obj2ast_unaryop(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14108,7 +14156,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &operand, arena); + res = obj2ast_expr(state, tmp, &operand, "operand", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14139,7 +14187,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Lambda' node")) { goto failed; } - res = obj2ast_arguments(state, tmp, &args, arena); + res = obj2ast_arguments(state, tmp, &args, "args", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14156,7 +14204,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Lambda' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &body, arena); + res = obj2ast_expr(state, tmp, &body, "body", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14188,7 +14236,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14205,7 +14253,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &body, arena); + res = obj2ast_expr(state, tmp, &body, "body", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14222,7 +14270,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &orelse, arena); + res = obj2ast_expr(state, tmp, &orelse, "orelse", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14267,7 +14315,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Dict' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "keys", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14305,7 +14353,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Dict' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14356,7 +14404,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Set' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "elts", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14394,7 +14442,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ListComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &elt, arena); + res = obj2ast_expr(state, tmp, &elt, "elt", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14425,7 +14473,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ListComp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14463,7 +14511,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'SetComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &elt, arena); + res = obj2ast_expr(state, tmp, &elt, "elt", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14494,7 +14542,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'SetComp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14533,7 +14581,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &key, arena); + res = obj2ast_expr(state, tmp, &key, "key", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14550,7 +14598,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14581,7 +14629,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14619,7 +14667,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &elt, arena); + res = obj2ast_expr(state, tmp, &elt, "elt", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14650,7 +14698,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14687,7 +14735,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Await' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14717,7 +14765,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Yield' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14747,7 +14795,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'YieldFrom' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14779,7 +14827,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Compare' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &left, arena); + res = obj2ast_expr(state, tmp, &left, "left", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14810,7 +14858,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Compare' node")) { goto failed; } - res = obj2ast_cmpop(state, tmp2, &val, arena); + res = obj2ast_cmpop(state, tmp2, &val, "ops", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14848,7 +14896,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Compare' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "comparators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14887,7 +14935,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Call' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &func, arena); + res = obj2ast_expr(state, tmp, &func, "func", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14918,7 +14966,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Call' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "args", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14956,7 +15004,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Call' node")) { goto failed; } - res = obj2ast_keyword(state, tmp2, &val, arena); + res = obj2ast_keyword(state, tmp2, &val, "keywords", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14995,7 +15043,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15012,7 +15060,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { goto failed; } - res = obj2ast_int(state, tmp, &conversion, arena); + res = obj2ast_int(state, tmp, &conversion, "conversion", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15029,7 +15077,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &format_spec, arena); + res = obj2ast_expr(state, tmp, &format_spec, "format_spec", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15063,7 +15111,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15080,7 +15128,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_constant(state, tmp, &str, arena); + res = obj2ast_constant(state, tmp, &str, "str", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15097,7 +15145,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_int(state, tmp, &conversion, arena); + res = obj2ast_int(state, tmp, &conversion, "conversion", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15114,7 +15162,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &format_spec, arena); + res = obj2ast_expr(state, tmp, &format_spec, "format_spec", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15159,7 +15207,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'JoinedStr' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15210,7 +15258,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TemplateStr' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15248,7 +15296,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Constant' node")) { goto failed; } - res = obj2ast_constant(state, tmp, &value, arena); + res = obj2ast_constant(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15265,7 +15313,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Constant' node")) { goto failed; } - res = obj2ast_string(state, tmp, &kind, arena); + res = obj2ast_string(state, tmp, &kind, "kind", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15297,7 +15345,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15314,7 +15362,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &attr, arena); + res = obj2ast_identifier(state, tmp, &attr, "attr", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15331,7 +15379,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15363,7 +15411,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15380,7 +15428,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &slice, arena); + res = obj2ast_expr(state, tmp, &slice, "slice", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15397,7 +15445,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15428,7 +15476,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Starred' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15445,7 +15493,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Starred' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15476,7 +15524,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Name' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &id, arena); + res = obj2ast_identifier(state, tmp, &id, "id", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15493,7 +15541,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Name' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15538,7 +15586,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'List' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "elts", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15562,7 +15610,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'List' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15607,7 +15655,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Tuple' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "elts", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15631,7 +15679,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Tuple' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15663,7 +15711,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Slice' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &lower, arena); + res = obj2ast_expr(state, tmp, &lower, "lower", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15680,7 +15728,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Slice' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &upper, arena); + res = obj2ast_expr(state, tmp, &upper, "upper", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15697,7 +15745,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Slice' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &step, arena); + res = obj2ast_expr(state, tmp, &step, "step", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15716,7 +15764,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* int obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { int isinstance; @@ -15750,8 +15798,8 @@ obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* } int -obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena* - arena) +obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -15778,7 +15826,7 @@ obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena* int obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { int isinstance; @@ -15892,8 +15940,8 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } int -obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, - PyArena* arena) +obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -15935,8 +15983,8 @@ obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, } int -obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* - arena) +obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -16027,7 +16075,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* int obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { PyObject* tmp = NULL; expr_ty target; @@ -16047,7 +16095,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16064,7 +16112,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &iter, arena); + res = obj2ast_expr(state, tmp, &iter, "iter", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16095,7 +16143,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "ifs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16119,7 +16167,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_int(state, tmp, &is_async, arena); + res = obj2ast_int(state, tmp, &is_async, "is_async", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16134,7 +16182,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* int obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { int isinstance; @@ -16149,6 +16197,15 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* *out = NULL; return 0; } + tp = state->excepthandler_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'excepthandler', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -16161,7 +16218,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16178,7 +16235,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16195,7 +16252,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16212,7 +16269,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16239,7 +16296,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &type, arena); + res = obj2ast_expr(state, tmp, &type, "type", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16256,7 +16313,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16287,7 +16344,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16313,7 +16370,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* int obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { PyObject* tmp = NULL; asdl_arg_seq* posonlyargs; @@ -16350,7 +16407,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp2, &val, arena); + res = obj2ast_arg(state, tmp2, &val, "posonlyargs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16388,7 +16445,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp2, &val, arena); + res = obj2ast_arg(state, tmp2, &val, "args", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16412,7 +16469,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp, &vararg, arena); + res = obj2ast_arg(state, tmp, &vararg, "vararg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16443,7 +16500,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp2, &val, arena); + res = obj2ast_arg(state, tmp2, &val, "kwonlyargs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16481,7 +16538,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "kw_defaults", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16505,7 +16562,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp, &kwarg, arena); + res = obj2ast_arg(state, tmp, &kwarg, "kwarg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16536,7 +16593,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "defaults", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16558,7 +16615,8 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, } int -obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) +obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, const char* + field, PyArena* arena) { PyObject* tmp = NULL; identifier arg; @@ -16581,7 +16639,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &arg, arena); + res = obj2ast_identifier(state, tmp, &arg, "arg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16598,7 +16656,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &annotation, arena); + res = obj2ast_expr(state, tmp, &annotation, "annotation", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16615,7 +16673,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16632,7 +16690,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16649,7 +16707,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16666,7 +16724,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16683,7 +16741,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16698,8 +16756,8 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } int -obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, - PyArena* arena) +obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, const + char* field, PyArena* arena) { PyObject* tmp = NULL; identifier arg; @@ -16721,7 +16779,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &arg, arena); + res = obj2ast_identifier(state, tmp, &arg, "arg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16738,7 +16796,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16755,7 +16813,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16772,7 +16830,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16789,7 +16847,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16806,7 +16864,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16821,8 +16879,8 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } int -obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* - arena) +obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, const + char* field, PyArena* arena) { PyObject* tmp = NULL; identifier name; @@ -16844,7 +16902,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16861,7 +16919,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &asname, arena); + res = obj2ast_identifier(state, tmp, &asname, "asname", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16878,7 +16936,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16895,7 +16953,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16912,7 +16970,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16929,7 +16987,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16945,7 +17003,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* int obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { PyObject* tmp = NULL; expr_ty context_expr; @@ -16963,7 +17021,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'withitem' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &context_expr, arena); + res = obj2ast_expr(state, tmp, &context_expr, "context_expr", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16980,7 +17038,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'withitem' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &optional_vars, arena); + res = obj2ast_expr(state, tmp, &optional_vars, "optional_vars", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16995,7 +17053,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, int obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { PyObject* tmp = NULL; pattern_ty pattern; @@ -17014,7 +17072,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'match_case' node")) { goto failed; } - res = obj2ast_pattern(state, tmp, &pattern, arena); + res = obj2ast_pattern(state, tmp, &pattern, "pattern", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17031,7 +17089,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'match_case' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &guard, arena); + res = obj2ast_expr(state, tmp, &guard, "guard", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17062,7 +17120,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'match_case' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17083,8 +17141,8 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, } int -obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, - PyArena* arena) +obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -17099,6 +17157,15 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, *out = NULL; return 0; } + tp = state->pattern_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'pattern', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -17111,7 +17178,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17128,7 +17195,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17145,7 +17212,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17162,7 +17229,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17187,7 +17254,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchValue' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17217,7 +17284,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchSingleton' node")) { goto failed; } - res = obj2ast_constant(state, tmp, &value, arena); + res = obj2ast_constant(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17261,7 +17328,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchSequence' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17314,7 +17381,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "keys", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17352,7 +17419,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17376,7 +17443,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &rest, arena); + res = obj2ast_identifier(state, tmp, &rest, "rest", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17409,7 +17476,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &cls, arena); + res = obj2ast_expr(state, tmp, &cls, "cls", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17440,7 +17507,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17478,7 +17545,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_identifier(state, tmp2, &val, arena); + res = obj2ast_identifier(state, tmp2, &val, "kwd_attrs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17516,7 +17583,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "kwd_patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17554,7 +17621,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchStar' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17585,7 +17652,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchAs' node")) { goto failed; } - res = obj2ast_pattern(state, tmp, &pattern, arena); + res = obj2ast_pattern(state, tmp, &pattern, "pattern", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17602,7 +17669,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchAs' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17646,7 +17713,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchOr' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17672,7 +17739,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, int obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { int isinstance; @@ -17683,6 +17750,15 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* *out = NULL; return 0; } + tp = state->type_ignore_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'type_ignore', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } tp = state->TypeIgnore_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -17704,7 +17780,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* if (_Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17721,7 +17797,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* if (_Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) { goto failed; } - res = obj2ast_string(state, tmp, &tag, arena); + res = obj2ast_string(state, tmp, &tag, "tag", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17739,7 +17815,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* int obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { int isinstance; @@ -17754,6 +17830,15 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, *out = NULL; return 0; } + tp = state->type_param_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'type_param', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -17766,7 +17851,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17783,7 +17868,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17800,7 +17885,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17817,7 +17902,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17844,7 +17929,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17861,7 +17946,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &bound, arena); + res = obj2ast_expr(state, tmp, &bound, "bound", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17878,7 +17963,8 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &default_value, arena); + res = obj2ast_expr(state, tmp, &default_value, "default_value", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17909,7 +17995,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'ParamSpec' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17926,7 +18012,8 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'ParamSpec' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &default_value, arena); + res = obj2ast_expr(state, tmp, &default_value, "default_value", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17957,7 +18044,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVarTuple' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17974,7 +18061,8 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVarTuple' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &default_value, arena); + res = obj2ast_expr(state, tmp, &default_value, "default_value", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -18506,7 +18594,7 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) } mod_ty res = NULL; - if (obj2ast_mod(state, ast, &res, arena) != 0) + if (obj2ast_mod(state, ast, &res, NULL, arena) != 0) return NULL; else return res; diff --git a/Python/assemble.c b/Python/assemble.c index 3df959c36341951..8bcb4c7bf3a9aa4 100644 --- a/Python/assemble.c +++ b/Python/assemble.c @@ -80,9 +80,9 @@ assemble_init(struct assembler *a, int firstlineno) } return SUCCESS; error: - Py_XDECREF(a->a_bytecode); - Py_XDECREF(a->a_linetable); - Py_XDECREF(a->a_except_table); + Py_CLEAR(a->a_bytecode); + Py_CLEAR(a->a_linetable); + Py_CLEAR(a->a_except_table); return ERROR; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 993d231751409ba..beaf6752b87ea2d 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2349,7 +2349,7 @@ dummy_func( assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); assert(index < DK_SIZE(keys)); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); DEOPT_IF(res_o == NULL); #if Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(&entries[index].me_value, res_o, &res); @@ -2368,7 +2368,7 @@ dummy_func( DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != version); assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); DEOPT_IF(res_o == NULL); #if Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(&entries[index].me_value, res_o, &res); @@ -2958,7 +2958,7 @@ dummy_func( assert(keys->dk_kind == DICT_KEYS_UNICODE); assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(keys->dk_nentries)); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(keys) + index; - PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value); + PyObject *attr_o = FT_ATOMIC_LOAD_PTR_CONSUME(ep->me_value); EXIT_IF(attr_o == NULL); #ifdef Py_GIL_DISABLED int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); @@ -4265,13 +4265,6 @@ dummy_func( EXIT_IF(!FT_ATOMIC_LOAD_UINT8(ivs->valid)); } - op(_GUARD_KEYS_VERSION, (keys_version/2, owner -- owner)) { - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version); - } - op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self)) { assert(oparg & 1); /* Cached method object */ @@ -4288,7 +4281,7 @@ dummy_func( _RECORD_TOS_TYPE + _GUARD_TYPE_VERSION + _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT + - _GUARD_KEYS_VERSION + + unused/2 + _LOAD_ATTR_METHOD_WITH_VALUES; op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self)) { @@ -4322,7 +4315,7 @@ dummy_func( _RECORD_TOS_TYPE + _GUARD_TYPE_VERSION + _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT + - _GUARD_KEYS_VERSION + + unused/2 + _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES; op(_LOAD_ATTR_NONDESCRIPTOR_NO_DICT, (descr/4, owner -- attr)) { diff --git a/Python/ceval.c b/Python/ceval.c index a9b31affca9890a..d6dd7f9a82c4314 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -49,7 +49,9 @@ _Py_ReachedRecursionLimitWithMargin(PyThreadState *tstate, int margin_count) #endif } -#if defined(__s390x__) +#if defined(_Py_LINKER_THREAD_STACK_SIZE) +# define Py_C_STACK_SIZE _Py_LINKER_THREAD_STACK_SIZE +#elif defined(__s390x__) # define Py_C_STACK_SIZE 320000 #elif defined(_WIN32) // Don't define Py_C_STACK_SIZE, ask the O/S diff --git a/Python/codecs.c b/Python/codecs.c index a522e6b88068b3e..6d1ae651fa00058 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -11,6 +11,7 @@ Copyright (c) Corporation for National Research Initiatives. #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_codecs.h" // export _PyCodec_LookupTextEncoding() +#include "pycore_initconfig.h" // _Py_DumpPathConfig() #include "pycore_interp.h" // PyInterpreterState.codec_search_path #include "pycore_pyerrors.h" // _PyErr_FormatNote() #include "pycore_pystate.h" // _PyInterpreterState_GET() @@ -1686,6 +1687,8 @@ _PyCodec_InitRegistry(PyInterpreterState *interp) // search functions, so this is done after everything else is initialized. PyObject *mod = PyImport_ImportModule("encodings"); if (mod == NULL) { + PyThreadState *tstate = _PyThreadState_GET(); + _Py_DumpPathConfig(tstate); return PyStatus_Error("Failed to import encodings module"); } Py_DECREF(mod); diff --git a/Python/compile.c b/Python/compile.c index eb9fc827bea40a8..e223ef42a42e22b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -893,12 +893,15 @@ compiler_mod(compiler *c, mod_ty mod) { PyCodeObject *co = NULL; int addNone = mod->kind != Expression_kind; + assert(c->u == NULL); if (compiler_codegen(c, mod) < 0) { goto finally; } co = _PyCompile_OptimizeAndAssemble(c, addNone); finally: - _PyCompile_ExitScope(c); + if (c->u != NULL) { + _PyCompile_ExitScope(c); + } return co; } diff --git a/Python/critical_section.c b/Python/critical_section.c index 98e23eda7cdd77e..dbee6f236a73bea 100644 --- a/Python/critical_section.c +++ b/Python/critical_section.c @@ -72,6 +72,22 @@ _PyCriticalSection2_BeginSlow(PyThreadState *tstate, PyCriticalSection2 *c, PyMu c->_cs_base._cs_prev = 0; return; } + // Same optimization as in _PyCriticalSection_BeginSlow: skip locking when + // recursively acquiring the same locks. + if (tstate->critical_section && + tstate->critical_section & _Py_CRITICAL_SECTION_TWO_MUTEXES) { + PyCriticalSection2 *prev2 = (PyCriticalSection2 *) + untag_critical_section(tstate->critical_section); + assert((uintptr_t)m1 < (uintptr_t)m2); + assert((uintptr_t)prev2->_cs_base._cs_mutex < + (uintptr_t)prev2->_cs_mutex2); + if (prev2->_cs_base._cs_mutex == m1 && prev2->_cs_mutex2 == m2) { + c->_cs_base._cs_mutex = NULL; + c->_cs_mutex2 = NULL; + c->_cs_base._cs_prev = 0; + return; + } + } c->_cs_base._cs_mutex = NULL; c->_cs_mutex2 = NULL; c->_cs_base._cs_prev = tstate->critical_section; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 3d27fd6709013bf..d5bfe60cd234737 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -10301,7 +10301,7 @@ assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); assert(index < DK_SIZE(keys)); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); if (res_o == NULL) { UOP_STAT_INC(uopcode, miss); SET_CURRENT_CACHED_VALUES(0); @@ -10346,7 +10346,7 @@ } assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); if (res_o == NULL) { UOP_STAT_INC(uopcode, miss); SET_CURRENT_CACHED_VALUES(0); @@ -12152,7 +12152,7 @@ assert(keys->dk_kind == DICT_KEYS_UNICODE); assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(keys->dk_nentries)); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(keys) + index; - PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value); + PyObject *attr_o = FT_ATOMIC_LOAD_PTR_CONSUME(ep->me_value); if (attr_o == NULL) { UOP_STAT_INC(uopcode, miss); _tos_cache0 = owner; @@ -16231,103 +16231,6 @@ break; } - case _GUARD_KEYS_VERSION_r01: { - CHECK_CURRENT_CACHED_VALUES(0); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - _PyStackRef owner; - owner = stack_pointer[-1]; - uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32(); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UOP_STAT_INC(uopcode, miss); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_JUMP_TARGET(); - } - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - break; - } - - case _GUARD_KEYS_VERSION_r11: { - CHECK_CURRENT_CACHED_VALUES(1); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - _PyStackRef owner; - _PyStackRef _stack_item_0 = _tos_cache0; - owner = _stack_item_0; - uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32(); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - JUMP_TO_JUMP_TARGET(); - } - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - break; - } - - case _GUARD_KEYS_VERSION_r22: { - CHECK_CURRENT_CACHED_VALUES(2); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - _PyStackRef owner; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - owner = _stack_item_1; - uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32(); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UOP_STAT_INC(uopcode, miss); - _tos_cache1 = owner; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(2); - JUMP_TO_JUMP_TARGET(); - } - _tos_cache1 = owner; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(2); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - break; - } - - case _GUARD_KEYS_VERSION_r33: { - CHECK_CURRENT_CACHED_VALUES(3); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - _PyStackRef owner; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - _PyStackRef _stack_item_2 = _tos_cache2; - owner = _stack_item_2; - uint32_t keys_version = (uint32_t)CURRENT_OPERAND0_32(); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UOP_STAT_INC(uopcode, miss); - _tos_cache2 = owner; - _tos_cache1 = _stack_item_1; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - JUMP_TO_JUMP_TARGET(); - } - _tos_cache2 = owner; - _tos_cache1 = _stack_item_1; - _tos_cache0 = _stack_item_0; - SET_CURRENT_CACHED_VALUES(3); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - break; - } - case _LOAD_ATTR_METHOD_WITH_VALUES_r02: { CHECK_CURRENT_CACHED_VALUES(0); ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); diff --git a/Python/flowgraph.c b/Python/flowgraph.c index eb0faf8cd183885..f135f243c74e2f6 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -404,7 +404,6 @@ cfg_builder_maybe_start_new_block(cfg_builder *g) static bool cfg_builder_check(cfg_builder *g) { - assert(g->g_entryblock->b_iused > 0); for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) { assert(!_PyMem_IsPtrFreed(block)); if (block->b_instr != NULL) { @@ -3279,6 +3278,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts) index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t)); if (index_map == NULL) { + PyErr_NoMemory(); goto end; } for (Py_ssize_t i = 1; i < nconsts; i++) { @@ -3331,6 +3331,7 @@ remove_unused_consts(basicblock *entryblock, PyObject *consts) /* adjust const indices in the bytecode */ reverse_index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t)); if (reverse_index_map == NULL) { + PyErr_NoMemory(); goto end; } for (Py_ssize_t i = 0; i < nconsts; i++) { @@ -3760,6 +3761,7 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache, int nlocals, int nparams, int firstlineno) { assert(cfg_builder_check(g)); + assert(g->g_entryblock->b_iused > 0); /** Preprocessing **/ /* Map labels to targets and mark exception handlers */ RETURN_IF_ERROR(translate_jump_labels_to_targets(g->g_entryblock)); diff --git a/Python/gc.c b/Python/gc.c index 54ac1b089e503d0..201c621bcc3cb9b 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -1876,6 +1876,8 @@ _PyGC_Fini(PyInterpreterState *interp) GCState *gcstate = &interp->gc; Py_CLEAR(gcstate->garbage); Py_CLEAR(gcstate->callbacks); + PyMem_RawFree(gcstate->generation_stats); + gcstate->generation_stats = NULL; /* Prevent a subtle bug that affects sub-interpreters that use basic * single-phase init extensions (m_size == -1). Those extensions cause objects diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 94384d5db3c107f..a6e0f90d8c1ce2a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -8772,18 +8772,7 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - // _GUARD_KEYS_VERSION - { - uint32_t keys_version = read_u32(&this_instr[4].cache); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - } + /* Skip 2 cache entries */ // _LOAD_ATTR_METHOD_WITH_VALUES { PyObject *descr = read_obj(&this_instr[6].cache); @@ -8840,7 +8829,7 @@ assert(keys->dk_kind == DICT_KEYS_UNICODE); assert(index < FT_ATOMIC_LOAD_SSIZE_RELAXED(keys->dk_nentries)); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(keys) + index; - PyObject *attr_o = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_value); + PyObject *attr_o = FT_ATOMIC_LOAD_PTR_CONSUME(ep->me_value); if (attr_o == NULL) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -8966,18 +8955,7 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - // _GUARD_KEYS_VERSION - { - uint32_t keys_version = read_u32(&this_instr[4].cache); - PyTypeObject *owner_cls = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); - PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls; - PyDictKeysObject *keys = owner_heap_type->ht_cached_keys; - if (FT_ATOMIC_LOAD_UINT32_RELAXED(keys->dk_version) != keys_version) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - } + /* Skip 2 cache entries */ // _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES { PyObject *descr = read_obj(&this_instr[6].cache); @@ -9727,7 +9705,7 @@ } assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); if (res_o == NULL) { UPDATE_MISS_STATS(LOAD_GLOBAL); assert(_PyOpcode_Deopt[opcode] == (LOAD_GLOBAL)); @@ -9794,7 +9772,7 @@ assert(keys->dk_kind == DICT_KEYS_UNICODE); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(keys); assert(index < DK_SIZE(keys)); - PyObject *res_o = FT_ATOMIC_LOAD_PTR_RELAXED(entries[index].me_value); + PyObject *res_o = FT_ATOMIC_LOAD_PTR_CONSUME(entries[index].me_value); if (res_o == NULL) { UPDATE_MISS_STATS(LOAD_GLOBAL); assert(_PyOpcode_Deopt[opcode] == (LOAD_GLOBAL)); diff --git a/Python/import.c b/Python/import.c index 82d15ad0683c190..6da6faf5f28cc3b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -81,8 +81,6 @@ static struct _inittab *inittab_copy = NULL; #define LAST_MODULE_INDEX _PyRuntime.imports.last_module_index #define EXTENSIONS _PyRuntime.imports.extensions -#define PKGCONTEXT (_PyRuntime.imports.pkgcontext) - /*******************************/ /* interpreter import state */ @@ -883,7 +881,6 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp) */ static _Py_thread_local const char *pkgcontext = NULL; -# undef PKGCONTEXT # define PKGCONTEXT pkgcontext const char * @@ -3174,7 +3171,7 @@ find_frozen(PyObject *nameobj, struct frozen_info *info) if (nameobj == NULL || nameobj == Py_None) { return FROZEN_BAD_NAME; } - const char *name = PyUnicode_AsUTF8(nameobj); + const char *name = _PyUnicode_AsUTF8NoNUL(nameobj); if (name == NULL) { // Note that this function previously used // _PyUnicode_EqualToASCIIString(). We clear the error here diff --git a/Python/initconfig.c b/Python/initconfig.c index eb0a5ef7aa01365..f653c00d1f0bed8 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -4641,7 +4641,8 @@ config_get(const PyConfig *config, const PyConfigSpec *spec, if (strcmp(spec->name, "int_max_str_digits") == 0) { PyInterpreterState *interp = _PyInterpreterState_GET(); - return PyLong_FromLong(interp->long_state.max_str_digits); + int maxdigits = _Py_atomic_load_int(&interp->long_state.max_str_digits); + return PyLong_FromLong(maxdigits); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 8895e02d47b1693..102b95279514141 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3941,10 +3941,6 @@ break; } - case _GUARD_KEYS_VERSION: { - break; - } - case _LOAD_ATTR_METHOD_WITH_VALUES: { JitOptRef owner; JitOptRef attr; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 97511d2daf2c8f7..01ca459b2eb2b8f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -429,7 +429,8 @@ interpreter_update_config(PyThreadState *tstate, int only_update_path_config) } } - tstate->interp->long_state.max_str_digits = config->int_max_str_digits; + _Py_atomic_store_int(&tstate->interp->long_state.max_str_digits, + config->int_max_str_digits); // Update the sys module for the new configuration if (_PySys_UpdateConfig(tstate) < 0) { @@ -3731,7 +3732,9 @@ fatal_error(int fd, int header, const char *prefix, const char *msg, This function already did its best to display a traceback. Disable faulthandler to prevent writing a second traceback on abort(). */ - _PyFaulthandler_Fini(); + if (has_tstate_and_gil) { + _PyFaulthandler_Fini(); + } /* Check if the current Python thread hold the GIL */ if (has_tstate_and_gil) { diff --git a/Python/specialize.c b/Python/specialize.c index 2ff0a9d0072cec3..04aeb4a76d4046a 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1285,7 +1285,6 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr, SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS); return 0; } - write_u32(cache->keys_version, shared_keys_version); specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES); } else { diff --git a/Python/symtable.c b/Python/symtable.c index 070e374101b5cd5..00ac510fe76b972 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -834,17 +834,22 @@ inline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp, return 0; } // __class__, __classdict__ and __conditional_annotations__ are - // never allowed to be free through a class scope (see - // drop_class_free) + // not allowed to be free through a class scope (see + // drop_class_free) unless children scopes need it if (scope == FREE && ste->ste_type == ClassBlock && (_PyUnicode_EqualToASCIIString(k, "__class__") || _PyUnicode_EqualToASCIIString(k, "__classdict__") || _PyUnicode_EqualToASCIIString(k, "__conditional_annotations__"))) { scope = GLOBAL_IMPLICIT; - if (PySet_Discard(comp_free, k) < 0) { + int child_needs_free = is_free_in_any_child(comp, k); + if (child_needs_free < 0) { return 0; } - + if (!child_needs_free) { + if (PySet_Discard(comp_free, k) < 0) { + return 0; + } + } if (_PyUnicode_EqualToASCIIString(k, "__class__")) { remove_dunder_class = 1; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index f7e28086d84fab9..d9f7b9c449cfb94 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1874,7 +1874,8 @@ sys_get_int_max_str_digits_impl(PyObject *module) /*[clinic end generated code: output=0042f5e8ae0e8631 input=77fb74e987ba7ecb]*/ { PyInterpreterState *interp = _PyInterpreterState_GET(); - return PyLong_FromLong(interp->long_state.max_str_digits); + int maxdigits = _Py_atomic_load_int(&interp->long_state.max_str_digits); + return PyLong_FromLong(maxdigits); } @@ -3490,14 +3491,39 @@ sys_set_flag(PyObject *flags, Py_ssize_t pos, PyObject *value) int _PySys_SetFlagObj(Py_ssize_t pos, PyObject *value) { - PyObject *flags = PySys_GetAttrString("flags"); - if (flags == NULL) { - return -1; + PyObject *new_flags = NULL; + PyObject *flags_str = &_Py_ID(flags); // immortal ref + + PyObject *old_flags = PySys_GetAttr(flags_str); + if (old_flags == NULL) { + goto error; } - sys_set_flag(flags, pos, value); - Py_DECREF(flags); - return 0; + new_flags = PyStructSequence_New(&FlagsType); + if (new_flags == NULL) { + goto error; + } + + for (Py_ssize_t i = 0; i < (Py_ssize_t)(Py_ARRAY_LENGTH(flags_fields) - 1); i++) { + if (i != pos) { + PyObject *old_value; + old_value = PyStructSequence_GET_ITEM(old_flags, i); // borrowed ref + sys_set_flag(new_flags, i, old_value); + } + else { + sys_set_flag(new_flags, pos, value); + } + } + + int res = _PySys_SetAttr(flags_str, new_flags); + Py_DECREF(old_flags); + Py_DECREF(new_flags); + return res; + +error: + Py_XDECREF(old_flags); + Py_XDECREF(new_flags); + return -1; } @@ -3521,8 +3547,6 @@ set_flags_from_config(PyInterpreterState *interp, PyObject *flags) const PyPreConfig *preconfig = &interp->runtime->preconfig; const PyConfig *config = _PyInterpreterState_GetConfig(interp); - // _PySys_UpdateConfig() modifies sys.flags in-place: - // Py_XDECREF() is needed in this case. Py_ssize_t pos = 0; #define SetFlagObj(expr) \ do { \ @@ -4033,7 +4057,7 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict) /* implementation */ SET_SYS("implementation", make_impl_info(version_info)); - // sys.flags: updated in-place later by _PySys_UpdateConfig() + // sys.flags: updated later by _PySys_UpdateConfig() ENSURE_INFO_TYPE(FlagsType, flags_desc); SET_SYS("flags", make_flags(tstate->interp)); @@ -4153,16 +4177,21 @@ _PySys_UpdateConfig(PyThreadState *tstate) #undef COPY_LIST #undef COPY_WSTR - // sys.flags - PyObject *flags = PySys_GetAttrString("flags"); - if (flags == NULL) { + // replace sys.flags + PyObject *new_flags = PyStructSequence_New(&FlagsType); + if (new_flags == NULL) { return -1; } - if (set_flags_from_config(interp, flags) < 0) { - Py_DECREF(flags); + if (set_flags_from_config(interp, new_flags) < 0) { + Py_DECREF(new_flags); + return -1; + } + + res = _PySys_SetAttr(&_Py_ID(flags), new_flags); + Py_DECREF(new_flags); + if (res < 0) { return -1; } - Py_DECREF(flags); SET_SYS("dont_write_bytecode", PyBool_FromLong(!config->write_bytecode)); @@ -4675,7 +4704,7 @@ _PySys_SetIntMaxStrDigits(int maxdigits) // Set PyInterpreterState.long_state.max_str_digits // and PyInterpreterState.config.int_max_str_digits. PyInterpreterState *interp = _PyInterpreterState_GET(); - interp->long_state.max_str_digits = maxdigits; - interp->config.int_max_str_digits = maxdigits; + _Py_atomic_store_int(&interp->long_state.max_str_digits, maxdigits); + _Py_atomic_store_int(&interp->config.int_max_str_digits, maxdigits); return 0; } diff --git a/Tools/.ruff.toml b/Tools/.ruff.toml new file mode 100644 index 000000000000000..fd9cde5e6cad650 --- /dev/null +++ b/Tools/.ruff.toml @@ -0,0 +1,14 @@ +extend = "../.ruff.toml" # Inherit the project-wide settings + +[per-file-target-version] +"jit/*.py" = "py312" # Reused-quote f-strings (PEP 701) + +[lint] +select = [ + "F401", # Unused import +] + +[lint.per-file-ignores] +"c-analyzer/c_parser/__init__.py" = ["F401"] # Re-exports from submodules +"c-analyzer/c_parser/preprocessor/__init__.py" = ["F401"] # Re-exports from submodules +"c-analyzer/c_parser/preprocessor/common.py" = ["F401"] # Re-exported by preprocessor/__init__.py diff --git a/Tools/c-analyzer/c_parser/preprocessor/clang.py b/Tools/c-analyzer/c_parser/preprocessor/clang.py index 574a23f8f6d6f9f..738c261d1ecd80a 100644 --- a/Tools/c-analyzer/c_parser/preprocessor/clang.py +++ b/Tools/c-analyzer/c_parser/preprocessor/clang.py @@ -1,5 +1,4 @@ import os.path -import re, sys from . import common as _common from . import gcc as _gcc diff --git a/Tools/c-analyzer/distutils/util.py b/Tools/c-analyzer/distutils/util.py index f687a28ec2f40e8..c8e92658d953661 100644 --- a/Tools/c-analyzer/distutils/util.py +++ b/Tools/c-analyzer/distutils/util.py @@ -8,7 +8,6 @@ import re import string import sys -from distutils.errors import DistutilsPlatformError def get_host_platform(): """Return a string that identifies the current platform. This is used mainly to diff --git a/Tools/cases_generator/generators_common.py b/Tools/cases_generator/generators_common.py index bdc4324b6702006..8c66ad4885ccfc8 100644 --- a/Tools/cases_generator/generators_common.py +++ b/Tools/cases_generator/generators_common.py @@ -7,14 +7,12 @@ analysis_error, Label, CodeSection, - Uop, ) from cwriter import CWriter from typing import Callable, TextIO, Iterator, Iterable from lexer import Token from stack import Storage, StackError from parser import Stmt, SimpleStmt, BlockStmt, IfStmt, ForStmt, WhileStmt, MacroIfStmt -from stack import PRINT_STACKS DEBUG = False class TokenIterator: diff --git a/Tools/cases_generator/opcode_metadata_generator.py b/Tools/cases_generator/opcode_metadata_generator.py index 21407ad7df1e9a5..00f6804f1724b59 100644 --- a/Tools/cases_generator/opcode_metadata_generator.py +++ b/Tools/cases_generator/opcode_metadata_generator.py @@ -19,7 +19,6 @@ cflags, ) from cwriter import CWriter -from dataclasses import dataclass from typing import TextIO from stack import get_stack_effect diff --git a/Tools/cases_generator/parser.py b/Tools/cases_generator/parser.py index ccf8bf649520ff6..aa6c0b1446fb76b 100644 --- a/Tools/cases_generator/parser.py +++ b/Tools/cases_generator/parser.py @@ -20,7 +20,6 @@ MacroIfStmt, ) -import pprint CodeDef = InstDef | LabelDef diff --git a/Tools/cases_generator/tier1_generator.py b/Tools/cases_generator/tier1_generator.py index d2fa749e1417f51..ebc914a6837e2eb 100644 --- a/Tools/cases_generator/tier1_generator.py +++ b/Tools/cases_generator/tier1_generator.py @@ -9,8 +9,6 @@ Analysis, Instruction, Uop, - Label, - CodeSection, Part, analyze_files, Skip, @@ -24,13 +22,9 @@ write_header, type_and_null, Emitter, - TokenIterator, - always_true, - emit_to, ) from cwriter import CWriter from typing import TextIO -from lexer import Token from stack import Local, Stack, StackError, get_stack_effect, Storage DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h" diff --git a/Tools/check-c-api-docs/ignored_c_api.txt b/Tools/check-c-api-docs/ignored_c_api.txt index dfec0524cfe016d..fa53b205c4ff6af 100644 --- a/Tools/check-c-api-docs/ignored_c_api.txt +++ b/Tools/check-c-api-docs/ignored_c_api.txt @@ -43,10 +43,6 @@ PyDescr_TYPE PyWrapperFlag_KEYWORDS # cpython/fileobject.h Py_UniversalNewlineFgets -# cpython/ceval.h -PyUnstable_CopyPerfMapFile -PyUnstable_PerfTrampoline_CompileCode -PyUnstable_PerfTrampoline_SetPersistAfterFork # cpython/pyframe.h PyUnstable_EXECUTABLE_KINDS PyUnstable_EXECUTABLE_KIND_BUILTIN_FUNCTION diff --git a/Tools/inspection/benchmark_external_inspection.py b/Tools/inspection/benchmark_external_inspection.py index 8e367422a961da2..b7aa0e5de7ed99b 100644 --- a/Tools/inspection/benchmark_external_inspection.py +++ b/Tools/inspection/benchmark_external_inspection.py @@ -4,7 +4,6 @@ import sys import contextlib import tempfile -import os import argparse from _colorize import get_colors, can_colorize diff --git a/Tools/jit/_stencils.py b/Tools/jit/_stencils.py index e2ae3d988fc7ac9..d4547dc8e8e3c12 100644 --- a/Tools/jit/_stencils.py +++ b/Tools/jit/_stencils.py @@ -2,7 +2,6 @@ import dataclasses import enum -import sys import typing import _schema diff --git a/Tools/jit/template.c b/Tools/jit/template.c index 72379165f3b610e..f1e2e25aaecdada 100644 --- a/Tools/jit/template.c +++ b/Tools/jit/template.c @@ -1,8 +1,10 @@ #include "Python.h" +#ifndef NDEBUG #undef assert #define assert(TEST) ((TEST) ? 0 : _Py_jit_assertion_failure(__LINE__)) +#endif #include "pycore_backoff.h" #include "pycore_call.h" @@ -40,8 +42,10 @@ #include "jit.h" +#ifndef NDEBUG #undef assert #define assert(TEST) ((TEST) ? 0 : _Py_jit_assertion_failure(__LINE__)) +#endif #undef CURRENT_OPERAND0_64 #define CURRENT_OPERAND0_64() (_operand0_64) diff --git a/Tools/picklebench/memory_dos_impact.py b/Tools/picklebench/memory_dos_impact.py index 3bad6586c469437..0a7cef8668565c8 100755 --- a/Tools/picklebench/memory_dos_impact.py +++ b/Tools/picklebench/memory_dos_impact.py @@ -24,7 +24,6 @@ import argparse import gc -import io import json import os import pickle @@ -32,11 +31,10 @@ import struct import subprocess import sys -import tempfile import tracemalloc from pathlib import Path from time import perf_counter -from typing import Any, Dict, List, Tuple, Optional +from typing import Any, Dict, List, Tuple # Configuration diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index ad3e4b6596ed7ae..1a213187b897d1d 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -46,15 +46,15 @@ "1.1.1w", "3.1.8", "3.2.6", + "3.3.7", ] OPENSSL_RECENT_VERSIONS = [ - "3.0.20", - "3.3.7", - "3.4.5", - "3.5.6", - "3.6.2", - "4.0.0", + "3.0.21", + "3.4.6", + "3.5.7", + "3.6.3", + "4.0.1", # See make_ssl_data.py for notes on adding a new version. ] @@ -65,7 +65,7 @@ ] AWSLC_RECENT_VERSIONS = [ - "1.68.0", + "5.0.0", ] # store files in ../multissl diff --git a/Tools/unicode/gen_expat_table.py b/Tools/unicode/gen_expat_table.py new file mode 100644 index 000000000000000..ff08fb4c87dab39 --- /dev/null +++ b/Tools/unicode/gen_expat_table.py @@ -0,0 +1,107 @@ +import sys + + +def info(msg, *args): + print(msg % args, file=sys.stderr) + +def fail(msg, *args): + info(msg, *args) + sys.exit(2) + +# ASCII characters that can appear in a well-formed XML document +# except the characters "$@\^`{}~". +compulsory_chars = (set(b'\t\n\r') | set(range(32, 127))) - set(br'$@\^`{}~') + +def check_compatibility(encoding): + for i in compulsory_chars: + c = chr(i) + b = bytes([i]) + try: + decoded = b.decode(encoding) + except UnicodeDecodeError: + info('Cannot decode byte %#04x (%a)', i, c) + return False + if decoded != c: + info('Incompatible encoding: %#04x (%a) -> %a', i, c, decoded) + return False + return True + +def create_table(encoding): + mapping = [-1] * 256 + + non_bmp = None + for i in range(0x110000): + char = chr(i) + try: + encoded = char.encode(encoding) + except UnicodeEncodeError: + continue + if i >= 0x10000 and non_bmp is None: + non_bmp = i + info('Non-BMP character: %r (U+%04X)', char, i) + length = len(encoded) + k = encoded[0] + v = mapping[k] + if length == 1: + if v == -1: + mapping[k] = i + elif v < 0: + fail('Ambiguous mapping for %#04x: ' + '%r (U+%04X) and %d-byte sequence', + k, c, i, -v) + else: + info('Ambiguous mapping for %#04x: ' + '%r (U+%04X) and %r (U+%04X)', + k, chr(v), v, char, i) + else: + if length > 4: + fail('Too long encoding for %r (U+%04X): %r', + char, i, encoded) + if v == -1: + mapping[k] = -length + elif v != -length: + if v < 0: + fail('Ambiguous mapping for %#04x: ' + '%d-byte sequence and %d-byte sequence %r', + k, -v, length, encoded) + else: + fail('Ambiguous mapping for %#04x: ' + '%r (U+%04X) and %d-byte sequence %r', + k, chr(v), v, length, encoded) + return mapping + +def print_table(mapping): + print(' '*8 + '_expat_decoding_table=(', end='') + if mapping[:128] == list(range(128)): + print('*range(128),') + start = 128 + else: + print() + start = 0 + line = '' + pos = 0 + i = start + while True: + if i % 8 == 0: + if len(line) > 68: + print(' '*12 + line[:pos].rstrip()) + line = line[pos:] + pos = len(line) + if i == 256: + break + v = mapping[i] + if v >= 0: + v = hex(v) + line += f'{v}, ' + i += 1 + print(' '*12 + line.rstrip().rstrip(',') + '),') + + +encoding = sys.argv[1] + +if not check_compatibility(encoding): + print(' '*8 + '_expat_decoding_table=False,') + sys.exit(1) + +mapping = create_table(encoding) +print_table(mapping) diff --git a/Tools/unicode/makeunicodedata.py b/Tools/unicode/makeunicodedata.py index 5db850ca2d1f0c0..76283d6b794a0b0 100644 --- a/Tools/unicode/makeunicodedata.py +++ b/Tools/unicode/makeunicodedata.py @@ -342,15 +342,21 @@ def makeunicodedata(unicode, trace): fprint("#define TOTAL_FIRST",total_first) fprint("#define TOTAL_LAST",total_last) fprint("struct reindex{int start;short count,index;};") + # The reindex tables are read only by find_nfc_index(), which scans + # forward while .start <= code. The trailing sentinel's .start must + # exceed every codepoint (so the scan stops with a single comparison) + # and fit the signed int .start field. + nfc_sentinel = 0x7fffffff + assert sys.maxunicode < nfc_sentinel <= 0x7fffffff fprint("static struct reindex nfc_first[] = {") for start,end in comp_first_ranges: fprint(" { %d, %d, %d}," % (start,end-start,comp_first[start])) - fprint(" {0,0,0}") + fprint(" {0x%x, 0, 0}" % nfc_sentinel) fprint("};\n") fprint("static struct reindex nfc_last[] = {") for start,end in comp_last_ranges: fprint(" { %d, %d, %d}," % (start,end-start,comp_last[start])) - fprint(" {0,0,0}") + fprint(" {0x%x, 0, 0}" % nfc_sentinel) fprint("};\n") # FIXME: the following tables could be made static, and diff --git a/configure b/configure index eb53b200bf78bc5..7408fac738b8a39 100755 --- a/configure +++ b/configure @@ -642,6 +642,7 @@ ac_includes_default="\ #endif" ac_header_c_list= +ac_func_c_list= ac_subst_vars='LTLIBOBJS MODULE_BLOCK JIT_SHIM_BUILD_O @@ -3421,6 +3422,13 @@ as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H" as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H" +as_fn_append ac_func_c_list " acospi HAVE_ACOSPI" +as_fn_append ac_func_c_list " asinpi HAVE_ASINPI" +as_fn_append ac_func_c_list " atanpi HAVE_ATANPI" +as_fn_append ac_func_c_list " atan2pi HAVE_ATAN2PI" +as_fn_append ac_func_c_list " cospi HAVE_COSPI" +as_fn_append ac_func_c_list " sinpi HAVE_SINPI" +as_fn_append ac_func_c_list " tanpi HAVE_TANPI" # Auxiliary files required by this configure script. ac_aux_files="install-sh config.guess config.sub" @@ -9593,7 +9601,7 @@ printf "%s\n" "$BOLT_INSTRUMENT_FLAGS" >&6; } printf %s "checking BOLT_APPLY_FLAGS... " >&6; } if test -z "${BOLT_APPLY_FLAGS}" then - BOLT_APPLY_FLAGS=" ${BOLT_COMMON_FLAGS} -reorder-blocks=ext-tsp -reorder-functions=cdsort -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 " + BOLT_APPLY_FLAGS=" ${BOLT_COMMON_FLAGS} -reorder-blocks=ext-tsp -reorder-functions=cdsort -split-functions -icf=0 -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 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BOLT_APPLY_FLAGS" >&5 @@ -9919,6 +9927,10 @@ printf "%s\n" "$ac_cv_thread_stack_size" >&6; } if test "$ac_cv_thread_stack_size" != "default" -a "$ac_cv_thread_stack_size" != "unknown"; then LDFLAGS="$LDFLAGS -Wl,-z,stack-size=$ac_cv_thread_stack_size" + # Stack size used by Python/ceval.c to set Py_C_STACK_SIZE + +printf "%s\n" "#define _Py_LINKER_THREAD_STACK_SIZE $ac_cv_thread_stack_size" >>confdefs.h + fi fi @@ -27003,6 +27015,27 @@ esac fi done + +ac_func= +for ac_item in $ac_func_c_list +do + if test $ac_func; then + ac_fn_c_check_func "$LINENO" $ac_func ac_cv_func_$ac_func + if eval test \"x\$ac_cv_func_$ac_func\" = xyes; then + echo "#define $ac_item 1" >> confdefs.h + fi + ac_func= + else + ac_func=$ac_item + fi +done + + + + + + + LIBS=$LIBS_SAVE { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX semaphores are enabled" >&5 @@ -35087,8 +35120,8 @@ fi if test "x$py_cv_module__ctypes_test" = xyes then : - as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_CFLAGS=$LIBFFI_CFLAGS$as_nl" - as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_LDFLAGS=$LIBFFI_LIBS $LIBM$as_nl" + + as_fn_append MODULE_BLOCK "MODULE__CTYPES_TEST_LDFLAGS=$LIBM$as_nl" fi if test "$py_cv_module__ctypes_test" = yes; then diff --git a/configure.ac b/configure.ac index b2f3f7210050693..dbc781b545dd362 100644 --- a/configure.ac +++ b/configure.ac @@ -2255,7 +2255,7 @@ then -reorder-blocks=ext-tsp -reorder-functions=cdsort -split-functions - -icf=1 + -icf=0 -inline-all -split-eh -reorder-functions-use-hot-size @@ -2507,6 +2507,9 @@ EOF if test "$ac_cv_thread_stack_size" != "default" -a "$ac_cv_thread_stack_size" != "unknown"; then LDFLAGS="$LDFLAGS -Wl,-z,stack-size=$ac_cv_thread_stack_size" + # Stack size used by Python/ceval.c to set Py_C_STACK_SIZE + AC_DEFINE_UNQUOTED([_Py_LINKER_THREAD_STACK_SIZE], [$ac_cv_thread_stack_size], + [Thread stack size set by the linker (in bytes).]) fi fi @@ -6367,6 +6370,8 @@ AC_CHECK_FUNCS( [], [AC_MSG_ERROR([Python requires C99 compatible libm])] ) + +AC_CHECK_FUNCS_ONCE(acospi asinpi atanpi atan2pi cospi sinpi tanpi) LIBS=$LIBS_SAVE dnl For multiprocessing module, check that sem_open @@ -8445,9 +8450,11 @@ PY_STDLIB_MOD([_testmultiphase], [test "$TEST_MODULES" = yes], [test "$ac_cv_fun PY_STDLIB_MOD([_testsinglephase], [test "$TEST_MODULES" = yes], [test "$ac_cv_func_dlopen" = yes]) PY_STDLIB_MOD([xxsubtype], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_xxtestfuzz], [test "$TEST_MODULES" = yes]) +dnl Check have_libffi so _ctypes_test is only built if _ctypes is built. +dnl _ctypes_test doesn't use libffi directly. PY_STDLIB_MOD([_ctypes_test], [test "$TEST_MODULES" = yes], [test "$have_libffi" = yes -a "$ac_cv_func_dlopen" = yes], - [$LIBFFI_CFLAGS], [$LIBFFI_LIBS $LIBM]) + [], [$LIBM]) dnl Limited API template modules. dnl Emscripten does not support shared libraries yet. diff --git a/pyconfig.h.in b/pyconfig.h.in index 7ef83fcd0b9e0bf..999a55a5efd0fb0 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -55,6 +55,9 @@ /* Define to 1 if you have the 'acosh' function. */ #undef HAVE_ACOSH +/* Define to 1 if you have the 'acospi' function. */ +#undef HAVE_ACOSPI + /* struct addrinfo (netdb.h) */ #undef HAVE_ADDRINFO @@ -73,12 +76,21 @@ /* Define to 1 if you have the 'asinh' function. */ #undef HAVE_ASINH +/* Define to 1 if you have the 'asinpi' function. */ +#undef HAVE_ASINPI + /* Define to 1 if you have the header file. */ #undef HAVE_ASM_TYPES_H +/* Define to 1 if you have the 'atan2pi' function. */ +#undef HAVE_ATAN2PI + /* Define to 1 if you have the 'atanh' function. */ #undef HAVE_ATANH +/* Define to 1 if you have the 'atanpi' function. */ +#undef HAVE_ATANPI + /* Define to 1 if you have the 'backtrace' function. */ #undef HAVE_BACKTRACE @@ -179,6 +191,9 @@ /* Define to 1 if you have the 'copy_file_range' function. */ #undef HAVE_COPY_FILE_RANGE +/* Define to 1 if you have the 'cospi' function. */ +#undef HAVE_COSPI + /* Define to 1 if you have the 'ctermid' function. */ #undef HAVE_CTERMID @@ -1255,6 +1270,9 @@ /* Define to 1 if you have the 'sigwaitinfo' function. */ #undef HAVE_SIGWAITINFO +/* Define to 1 if you have the 'sinpi' function. */ +#undef HAVE_SINPI + /* Define to 1 if you have the 'snprintf' function. */ #undef HAVE_SNPRINTF @@ -1527,6 +1545,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_XATTR_H +/* Define to 1 if you have the 'tanpi' function. */ +#undef HAVE_TANPI + /* Define to 1 if you have the 'tcgetpgrp' function. */ #undef HAVE_TCGETPGRP @@ -2067,6 +2088,9 @@ /* Define if you have the 'PR_SET_VMA_ANON_NAME' constant. */ #undef _Py_HAVE_PR_SET_VMA_ANON_NAME +/* Thread stack size set by the linker (in bytes). */ +#undef _Py_LINKER_THREAD_STACK_SIZE + /* Define to 1 if the machine stack grows down (default); 0 if it grows up. */ #undef _Py_STACK_GROWS_DOWN